为了账号安全,请及时绑定邮箱和手机立即绑定

Java最终修饰符

Java最终修饰符

RISEBY 2019-10-25 10:38:58
有人告诉我,我误解了的影响final。final关键字有什么作用?这是我的想法的简短概述,我知道:Java最终修饰符(又名聚合关系)原始变量:只能设置一次。(内存和性能提升)对象变量:可以修改,最终适用于对象引用。字段:只能设置一次。方法:不能被覆盖,隐藏。类别:无法扩充。垃圾收集:将强制Java代垃圾收集标记扫描进行两次扫描。罐头和罐头会使克隆失败(这既好又坏)可以使不可变的原语又称为const可以使空白不可变-在创建时初始化为aka只读可以使对象浅成不变可以使范围/可见性不变可以使方法调用的开销较小(因为它不需要虚拟表)可以将方法参数用作最终参数(即使您不是)可以使对象成为线程安全的(如果将对象定义为final,则不会使方法参数成为final)可以进行模拟测试(不是您可以做任何事-您可以说是故意的错误)不能交朋友(与其他朋友可变而不能休息)以后不能使可变成为不变的(但可以使用工厂模式,如修复)不能使数组元素不可变又称为深度不可变无法创建对象的新实例(这既好又坏)无法使序列化工作没有其他替代方法final,但是有wrapper + private和enums。
查看完整描述

2 回答

?
繁花如伊

TA贡献2012条经验 获得超12个赞

依次回答您的每个观点:


原始变量:只能设置一次。(内存和性能提升)


是的,但是没有增加内存,也没有提高性能。(您假定的性能提升仅来自设置一次,而不是来自final。)


对象变量:可以修改,最终适用于对象引用。


是。(但是,此描述忽略了一点,即它与其余Java语言处理对象/引用对偶性的方式完全一致。例如,当对象作为参数传递并作为结果返回时。)


字段:只能设置一次。


真正的答案是:与变量相同。


方法:不能被覆盖,隐藏。


是。但也请注意,这里发生的是该final关键字在不同的语法上下文中使用,表示与final字段/变量不同的含义。


类:无法扩展。


是。但也请参阅上面的注释。


垃圾收集:将强制Java代垃圾收集标记扫描进行两次扫描。


这是无稽之谈。该final关键字没有关联任何垃圾收集。您可能final对最终化感到困惑……它们是无关的。


但是,即使终结器也不会强制进行额外的扫描。发生的情况是,需要终结的对象放在一侧,直到主GC完成。然后,GC在对象上运行finalize方法并设置其标志...并继续。下次GC运行时,该对象将被视为普通对象:


如果可以到达,则将其标记并复制

如果无法访问,则不会被标记。

(您的特征-“ Java世代垃圾收集标记扫描”是乱码。垃圾收集器可以是“ mark-sweep”或“ generational”(“ copying”的子类)。不能同时使用。Java通常使用世代收集,并且仅在紧急情况下才退回标记扫描;即,当空间用尽或低暂停收集器无法跟上时。)


会使克隆失败(这既好又坏)


我不这么认为。


可以使不可变的原语又称为const


是。


可以使空白不可变-在创建时初始化为aka只读


是的,虽然我以前从未听说过“空白不变”这一术语。


可以使对象浅成不变


对象可变性是关于可观察状态是否可能改变。这样,声明属性final可能会使对象表现为不可变。除了“浅层不可变”的概念没有得到很好的定义,这尤其是因为没有对类语义的深入了解就无法映射“浅层”的概念。


(很明显,在JLS的上下文中,变量/字段的可变性是一个定义明确的概念。只是从JLS的角度来看,未定义对象的可变性的概念。)


可以使范围/可见性不变


术语错误。可变性与对象状态有关。可见性和范围都没有。


可以使方法调用的开销较小(因为它不需要虚拟表)


实际上,这是无关紧要的。如果未由应用程序实际使用的任何类覆盖非最终方法,那么现代JIT编译器也会对非最终方法进行此优化。(聪明的事情发生了……)


可以将方法参数用作最终参数(即使您不是)


??我无法解析这句话。


可以使对象成为线程安全的


在某些情况下可以。


(如果将对象定义为final,则不会使方法参数成为final)


是的,如果您的意思是课程是最后的。对象不是最终的。


可以进行模拟测试(不是您可以做任何事-您可以说是故意的错误)


不解析。


不能交朋友(与其他朋友可变而不能休息)


Java没有“朋友”。


以后不能使可变成为不变的(但可以使用工厂模式,如修复)


是的,第一个final字段不能从可变更改为不可变。


目前尚不清楚第二部分是什么意思。确实可以使用工厂(或构建器)模式构造不可变对象。但是,如果您final在任何时候都使用对象字段,则该对象将是可变的。


或者,您可以实现使用非最终字段表示不可变状态的不可变对象,并且可以设计API,以便您可以“翻转开关”以使从现在开始可变为先前可变的对象。但是,如果采用这种方法,则在同步时需要更加小心……如果您的对象需要是线程安全的。


不能使数组元素不可变又称为深度不可变


是的,但是您的术语不正确;请参阅上面有关“浅可变性”的评论。


无法创建对象的新实例(这既好又坏)


不会。没有什么可以阻止您使用final字段,final类或final方法来创建对象的新实例。


无法使序列化工作


否。序列化有效。(当然,final使用自定义readObject方法对字段进行反序列化会带来问题……尽管您可以使用反射技巧来解决这些问题。)


除了final,别无选择,


正确。


但是有包装+私人


是的,对非最终字段进行非同步的getter模(严格地说)可能是非线程安全的... 即使在对象构造期间对其进行了初始化,然后再也从未更改!


和枚举。


解决了另一个问题。并且enums可以是可变的。


查看完整回答
反对 回复 2019-10-25
?
大话西游666

TA贡献1817条经验 获得超14个赞

Final关键字通常用于保留不变性。将final用于类或方法是为了防止方法之间的链接断开。例如,假设类X的某些方法的实现假设方法M将以某种方式运行。将X或M声明为final将防止派生类以导致X行为不正确的方式重新定义M。


查看完整回答
反对 回复 2019-10-25
  • 2 回答
  • 0 关注
  • 336 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信