fegin需要实现类_【第24条】静态成员类优于非静态成员类

第24条

静态成员类优于非静态成员类

嵌套类(nested class)是指定义在另一个类的内部的类。嵌套类存在的目的应该只是为它的外围类(enclosing class)提供服务。如果嵌套类将来可能会用于其他的某个环境中,它就应该是顶层类(top-level class)。嵌套类有四种:静态成员类(static member class)、非静态成员类(nonstatic member class)、匿名类(anonymous class)和局部类(local class)。除了第一种之外,其他三种都称为内部类(inner class) 。本条目将告诉你什么时候应该使用哪种嵌套类,以及这样做的原因。

静态成员类是最简单的一种嵌套类。最好把它看作是普通的类,只是碰巧被声明在另一个类的内部而已,它可以访问外围类的所有成员,包括那些声明为私有的成员。静态成员类是外围类的一个静态成员,与其他的静态成员一样,也遵守同样的可访问性规则。如果它被声明为私有的,它就只能在外围类的内部才可以被访问,等等。

静态成员类的一种常见用法是作为公有的辅助类,只有与它的外部类一起使用才有意义。例如,以枚举为例,它描述了计算器支持的各种操作(详见第34条)。Operation枚举应该是Calculator类的公有静态成员类,之后Calculator类的客户端就可以用诸如 Calculator.Operation.PLUS 和 Calculator.Operation.MINUS 这样的名称来引用这些操作。

从语法上讲,静态成员类和非静态成员类之间唯一的区别是,静态成员类的声明中包含修饰符static。尽管它们的语法非常相似,但是这两种嵌套类有很大的不同。非静态成员类的每个实例都隐含地与外围类的一个外围实例(enclosing instance)相关联。在非静态成员类的实例方法内部,可以调用外围实例上的方法,或者利用修饰过的this(qualified this)构造获得外围实例的引用。如果嵌套类的实例可以在它外围类的实例之外独立存在,这个嵌套类就必须是静态成员类:在没有外围实例的情况下,要想创建非静态成员类的实例是不可能的。

当非静态成员类的实例被创建的时候,它和外围实例之间的关联关系也随之被建立起来;而且,这种关联关系以后不能被修改。通常情况下,当在外围类的某个实例方法的内部调用非静态成员类的构造器时,这种关联关系被自动建立起来。使用表达式enclosingInstance.newMemberClass(args)来手工建立这种关联关系也是有可能的,但是很少使用。正如你所预料的那样,这种关联关系需要消耗非静态成员类实例的空间,并且会增加构造的时间开销。

非静态成员类的一种常见用法是定义一个Adapter,它允许外部类的实例被看作是另一个不相关的类的实例。例如,Map接口的实现往往使用非静态成员类来实现它们的集合视图(collection view),这些集合视图是由Map的keySet、entrySet和values方法返回的。同样地,诸如Set和List这种集合接口的实现往往也使用非静态成员类来实现它们的迭代器(iterator):

// Typical use of a nonstatic member classpublic class MySet<E> extends AbstractSet<E> {  ... // Buik of the class omitted  ©Override public Iterator iterator() (    return new Mylterator();  }  private class Mylterator implements Iterator<E> {  }}

如果声明成员类不要求访问外围实例,就要始终把修饰符static放在它的声明中,使它成为静态成员类,而不是非静态成员类。如果省略了static修饰符,则每个实例都将包含一个额外的指向外围对象的引用。如前所述,保存这份引用要消耗时间和空间,并且会导致外围实例在符合垃圾回收(详见第7条)时却仍然得以保留。由此造成的内存泄漏可能是灾难性的。但是常常难以发现,因为这个引用是不可见的。

私有静态成员类的一种常见用法是代表外围类所代表的对象的组件。以Map实例为例,它把键(key)和值(value)关联起来。许多Map实现的内部都有一个Entry对象,对应于Map中的每个键-值对。虽然每个entry都与一个Map关联,但是entry上的方法(getKey、getValue和setValue)并不需要访问该Map。因此,使用非静态成员类来表示entry是很浪费的:私有的静态成员类是最佳的选择。如果不小心漏掉了entry声明中的static修饰符,该Map仍然可以工作,但是每个entry中将会包含一个指向该Map的引用,这样就浪费了空间和时间。

如果相关的类是导出类的公有或受保护的成员,毫无疑问,在静态和非静态成员类之间做出正确的选择是非常重要的。在这种情况下,该成员类就是导出的API元素,在后续的发行版本中,如果不违反向后兼容性,就无法从非静态成员类变为静态成员类。

顾名思义,匿名类是没有名字的。它不是外围类的一个成员。它并不与其他的成员一起被声明,而是在使用的同时被声明和实例化。匿名类可以出现在代码中任何允许存在表达式的地方。当且仅当匿名类出现在非静态的环境中时,它才有外围实例。但是即使它们出现在静态的环境中,也不可能拥有任何静态成员,而是拥有常数变量(constant variable),常数变量是final基本类型,或者被初始化成常量表达式的字符串域。

匿名类的运用受到诸多的限制。除了在它们被声明的时候之外,是无法将它们实例化的。不能执行instanceof测试,或者做任何需要命名类的其他事情。无法声明一个匿名类来实现多个接口,或者扩展一个类,并同时扩展类和实现接口。除了从超类型中继承得到之外,匿名类的客户端无法调用任何成员。由于匿名类出现在表达式中,它们必须保持简短(大约10行或者更少),否则会影响程序的可读性。

在Java中增加lambda(详见第6章)之前,匿名类是动态地创建小型函数对象(function object)和过程对象(process object)的最佳方式,但是现在会优先选择lambda(详见第42条)。匿名类的另一种常见用法是在静态工厂方法的内部(参见第20条中的intArrayAsList方法)。

局部类是四种嵌套类中使用最少的类。在任何“可以声明局部变量”的地方,都可以声明局部类,并且局部类也遵守同样的作用域规则。局部类与其他三种嵌套类中的每一种都有一些共同的属性。与成员类一样,局部类有名字,可以被重复使用。与匿名类一样,只有当局部类是在非静态环境中定义的时候,才有外围实例,它们也不能包含静态成员。与匿名类一样,它们必须非常简短,以便不会影响可读性。

总而言之,共有四种不同的嵌套类,每一种都有自己的用途。如果一个嵌套类需要在单个方法之外仍然是可见的,或者它太长了,不适合放在方法内部,就应该使用成员类。如果成员类的每个实例都需要一个指向其外围实例的引用,就要把成员类做成非静态的;否则,就做成静态的。假设这个嵌套类属于一个方法的内部,如果你只需要在一个地方创建实例,并且已经有了一个预置的类型可以说明这个类的特征,就要把它做成匿名类;否则,就做成局部类。

扫描二维码

获取更多精彩

Java乐分享

b830a14227a6d72050246452121aeeff.png

 92828ef5065e8f93f728f11401755e42.png感谢支持92828ef5065e8f93f728f11401755e42.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/537588.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Springboot 多线程的使用

直接上代码 线程配置类 package zengmg.nbpi.com.thread;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework…

vlookup函数练习_为什么职场要学excel函数?看这个案例演示:自动计算快递价格...

在上一篇文章里面&#xff0c;我们讲了如何整理完成一个规范化的表格&#xff0c;以便于下一步的函数计算。最初的信息内容如图所示。经过整理&#xff0c;我们得到了表2这样的规范化表格。现在&#xff0c;我们就通过表2来实现快递费用自动计算&#xff0c;最终实现图中这样的…

蓝牙芯片排行_7月TWS 全球品牌出货量排行榜出炉

数据铸造影响力撰文 / 旭日大数据编辑 / 柏序旭日大数据公布了2020年7月全球TWS品牌销量排行榜&#xff0c;与上期数据相比&#xff0c;全球品牌七排名TOP20汰换率为15%&#xff0c;其中DOSS&#xff0c;万魔、BOSE跌出前20&#xff0c;广州由我&#xff0c;Tzumi登榜&…

project 打印的时候上面的表格和下面的图例中间有个很大的空白,这块东西怎么能去掉呢?

“打印预览”的“页面设置”里面&#xff0c;“页面”选项卡里的“缩放”项设为1页宽&#xff0c;1页高就可以了&#xff0c; 当然如果你的任务项比较少的话&#xff0c;怎么调也不容易去掉下面的空白 操作如下图&#xff08;下图的任务太少&#xff0c;去不掉空白的&#xf…

加密机工作原理_端子机压力检测装置工作原理

上期我们介绍了端子机压力管理装置的使用常识&#xff0c;这期我们介绍端子机压力管理装置的工作原理&#xff0c;端子机压接管理装置&#xff0c;有单通道压力监测和双通道压力监测二种&#xff0c;双通道压力监测装置&#xff0c;一般用于双头端子压接机上&#xff0c;一台主…

win10解决java多版本java -version问题

电脑环境 先安装了Jdk8&#xff0c;后安装了jdk11.&#xff08;发现Jdk11没有单独的jre&#xff0c;官网也不提供下载&#xff0c;集成在一起了&#xff09; Java -version 将环境变量切换为 JDK11 后 javac -version 是 java编译环境是jdk11了&#xff0c;但 java -versio…

vs设计窗口不见了_碳纤维的巅峰:VS沛纳海616V3

各位朋友&#xff0c;你们好&#xff01;欢迎大家关注XYZ腕表俱乐部。专注腕表资讯&#xff0c;致力于做腕表拆解测评&#xff0c;为大家普及分享有价值的腕表知识&#xff0c;真正让大家实实在在透明玩表。想了解更多&#xff0c;欢迎搜索&#xff1a;XYZ腕表俱乐部。可以让您…

CSharpGL(49)试水OpenGL软实现

CSharpGL(49)试水OpenGL软实现 CSharpGL迎来了第49篇。本篇内容是用C#编写一个OpenGL的软实现。暂且将其命名为SoftGL。 目前已经实现了由Vertex Shader和Fragment Shader组成的Pipeline&#xff0c;其效果与显卡支持的OpenGL实现几乎相同。下图左是常规OpenGL渲染的结果&#…

SonarQube结合IDEA实现代码检测

环境准备 1.SonarQube下载&#xff1a;https://www.sonarqube.org/downloads/ 建议用最新版本&#xff0c;SonarQube与idea的结合 需要SonarQube很多插件&#xff0c;需要借助idea的SonarLint 插件。 不同的SonarQube版本&#xff0c;有不同的插件版本 idea的SonarLint 插件…

二维小波变换_【外文文献速读】实时二维水波模拟

题目&#xff1a;Water surface wavelets 作者&#xff1a;Stefan Jeschke&#xff0c; TomšSkřivan&#xff0c; MatthiasMller-Fischer&#xff0c; Nuttapong Chentanez&#xff0c; Miles Macklin&#xff0c; Chris Wojtan

技术开发(委托)合同怎么写?

一直基于宁波市科技局备案合同模板签订合同&#xff0c;并完成科技局备案工作&#xff0c;成功了N次&#xff0c;直接分享模板&#xff0c;该模板通过了法务审核&#xff0c;财务审核&#xff0c;只需要批示修改相关内容即可&#xff0c;一份技术开发委托合同&#xff0c;十几分…

最常用的15个前端表单验证JS正则表达式

2019独角兽企业重金招聘Python工程师标准>>> 在表单验证中&#xff0c;使用正则表达式来验证正确与否是一个很频繁的操作&#xff0c;本文收集整理了15个常用的JavaScript正则表达式&#xff0c;其中包括用户名、密码强度、整数、数字、电子邮件地址&#xff08;Ema…

程序员个人外包合同怎么写?

分享一份工作上经常用到的个人外包合同协议&#xff0c;该协议通过了法务与财务审核&#xff0c;兼顾甲乙双方利益&#xff0c;程序员接私活必备&#xff01;&#xff01;&#xff01;&#xff01; ---需要电子word版&#xff0c;请关注--------- 回复&#xff1a;个人外包合同…

rocketmq新扩容的broker没有tps_深入研究RocketMQ消费者是如何获取消息的

前言小伙伴们&#xff0c;国庆都过的开心吗&#xff1f;国庆后的第一个工作日是不是很多小伙伴还沉浸在假期的心情中&#xff0c;没有工作状态呢&#xff1f;那王子今天和大家聊一聊RocketMQ的消费者是如何获取消息的&#xff0c;通过学习知识来找回状态吧。废话不多说&#xf…

苏宁 11.11:仓库内多 AGV 协作的全局路径规划算法研究

本文为『InfoQ x 苏宁 2018双十一』技术特别策划系列文章之一。 1. 背景 随着物联网和人工智能的发展&#xff0c;越来越多的任务渐渐的被机器人取代&#xff0c;机器人逐渐在发展中慢慢进入物流领域&#xff0c;“智能叉车”&#xff0c;AGV&#xff08;Automated Guided Vehi…

用python绘制玫瑰花的代码_python也能玩出玫瑰花!程序员的表白代码

有些情侣是异地恋&#xff0c;情人节想送朵玫瑰花给女朋友都困难。别担心&#xff0c;用Python就好了&#xff0c;互联网时代的恋爱神器&#xff01;接下来就让我们一起来看看如何用Python变出玫瑰花的。 1、首先我们导入画图工具turtle&#xff0c;即import turtle 2、导入画图…

Springboot 整合 swagger

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主允许不得转载。 https://blog.csdn.net/weixin_40254498/article/details/83622098 swagger 主要是为后端服务的接口文档&#xff0c;懒人必备&#xff0c;swagger就是一款让你更好的书写API文档的框架。 其他的框架…

Project为项目设置预算

假设项目预算10万元&#xff0c;如果项目完成后&#xff0c;花费没有超过10万元&#xff0c;则成本管理是成功的&#xff0c;如果花费了11万&#xff0c;则超过了预算。 预算是10万&#xff0c;一般目标成本设得比预算成本低&#xff0c;比如9.5万。在项目实施过程中&#xff…

activiti7流程设计器_变频空调器通信电路

通信电路由室内机和室外机主板两个部分单元电路组成&#xff0c;并且在实际维修中该电路的故障率比较高&#xff0c;因此单设--节进行详细说明。第三章变频空调器单元电路对比和通信电路第二节通信电路通信电路由室内机和室外机主板两个部分单元电路组成&#xff0c;并且在实际…

PyCharm 中为 Python 项目添加.gitignore文件

文章目录 1.安装.ignore插件 2.在项目中添加.ignore文件 1.安装.ignore插件 在pycharm编译器中&#xff0c;依次点击File->Setting 在跳出Setting的页面中&#xff0c;执行如下操作&#xff1a; 点击左侧的Plugins&#xff0c; 在搜索框中输入.ignore 点击右侧的install 点…