简体   繁体   English

Java final修饰符

[英]Java final modifier

I was told that, I misunderstand effects of final . 有人告诉我,我误解了final影响。 What are the effects of final keyword? final关键字有什么影响?

Here is short overview of what I think, I know: 以下简要概述了我的想法,我知道:

Java final modifier (aka aggregation relation) Java final修饰符(又称聚合关系)

primitive variables : can be set only once. 原始变量 :只能设置一次。 (memory and performance gain) (记忆和性能增益)
objects variables : may be modified, final applies to object reference. 对象变量 :可以修改,最终应用于对象引用。
fields : can be set only once. 字段 :只能设置一次。
methods : can't be overridden, hidden. 方法 :不能被覆盖,隐藏。
classes : can't be extended. 课程 :不能扩展。
garbage collection : will force Java generational garbage collection mark-sweep to double sweep. 垃圾收集 :将强制Java世代垃圾收集标记扫描双扫。

Can's and Cant's Can's和Cant's

  • Can make clone fail (this is both good and bad) 可以使克隆失败(这既好又坏)
  • Can make immutable primitives aka const 可以使不可变的原语aka const
  • Can make blank immutable - initialized at creation aka readonly 可以使空白不可变 - 在创建时初始化也称为readonly
  • Can make objects shallowly immutable 可以使对象浅不可变
  • Can make scope / visibility immutable 可以使范围/可见性不可变
  • Can make method invocation overhead smaller (because it does not need virtual table) 可以使方法调用开销更小(因为它不需要虚拟表)
  • Can make method arguments used as final (even if thy are not) 可以使方法参数用作final(即使你不是)
  • Can make objects threadsafe (if object is defined as final, it wont make method arguments final) 可以使对象线程安全(如果对象被定义为final,它不会使方法参数最终)
  • Can make mock tests (not that you could do anything about it - you can say bugs are intended) 可以进行模拟测试(不是你可以对它做任何事情 - 你可以说错误是有意的)
  • Can't make friends (mutable with other friends and immutable for rest) 不能交朋友(与其他朋友互相变化,休息不变)
  • Can't make mutable that is changed to be immutable later (but can with factory pattern like fix) 以后不能将变为不可变的变量(但可以像工厂模式一样修复)
  • Can't make array elements immutable aka deeply immutable 无法使数组元素成为不可变的,也是不可变的
  • Can't make new instances of object (this is both good and bad) 无法创建对象的新实例(这既好又坏)
  • Can't make serialization work 无法进行序列化工作

There are no alternatives to final , but there is wrapper + private and enums. final没有替代品,但有包装+私人和枚举。

Answering each of your points in turn: 依次回答你的每一点:

primitive variables: can be set only once. 原始变量:只能设置一次。 (memory and performance gain) (记忆和性能增益)

Yes, but no memory gain, and no performance gain. 是的,但没有内存增益,也没有性能提升。 (Your supposed performance gain comes from setting only once ... not from final .) (你假设的性能增益来自于只设置一次......而不是来自final 。)

objects variables: may be modified, final applies to object reference. 对象变量:可以修改,最终应用于对象引用。

Yes. 是。 (However, this description miss the point that this is entirely consistent with the way that the rest of the Java language deals with the object / reference duality. For instance, when objects are passed as parameters and returned as results.) (但是,这个描述忽略了这与Java语言的其余部分处理对象/引用二元性的方式完全一致。例如,当对象作为参数传递并作为结果返回时。)

fields: can be set only once. 字段:只能设置一次。

The real answer is: same as for variables. 真正的答案是:与变量相同。

methods: can't be overridden, hidden. 方法:不能被覆盖,隐藏。

Yes. 是。 But also note that what is going on here is that the final keyword is being used in a different syntactic context to mean something different to final for an field / variable. 但同时请注意,这里发生的事情是, final关键字在不同的句法上下文中使用,表示字段/变量的final值不同。

classes: can't be extended. 课程:不能扩展。

Yes. 是。 But also see note above. 但也见上面的注释。

garbage collection: will force Java generational garbage collection mark-sweep to double sweep. 垃圾收集:将强制Java世代垃圾收集标记扫描双扫。

This is nonsense. 这是无稽之谈。 The final keyword has no relevance whatsoever to garbage collection. final关键字没有垃圾收集相关任何责任 You might be confusing final with finalization ... they are unrelated. final可能会把final弄糊涂......他们是无关的。

But even finalizers don't force an extra sweep. 但即使是终结者也不会强行进行额外的扫描。 What happens is that an object that needs finalization is set on one side until the main GC finishes. 发生的情况是,需要完成的对象在一侧设置,直到主GC完成。 The GC then runs the finalize method on the object and sets its flag ... and continues. 然后GC在对象上运行finalize方法并设置其标志......并继续。 The next time the GC runs, the object is treated as a normal object: GC下次运行时,该对象被视为普通对象:

  • if it is reachable it is marked and copied 如果可以到达则标记并复制
  • if it is not reachable it is not marked. 如果无法访问,则不会标记。

(Your characterization - "Java generational garbage collection mark-sweep" is garbled. A garbage collector can be either "mark-sweep" OR "generational" (a subclass of "copying"). It can't be both. Java normally uses generational collection, and only falls back to mark-sweep in emergencies; ie when running out of space or when a low pause collector cannot keep up.) (你的特征 - “Java代垃圾收集标记扫描”是乱码。垃圾收集器可以是“标记扫描”或“世代”(“复制”的子类)。它不能同时存在。通常使用Java世代收集,只会在紧急情况下回落到标记扫描;即当空间不足或低暂停收集器无法跟上时。)

Can make clone fail (this is both good and bad) 可以使克隆失败(这既好又坏)

I don't think so. 我不这么认为。

Can make immutable primitives aka const 可以使不可变的原语aka const

Yes. 是。

Can make blank immutable - initialized at creation aka readonly 可以使空白不可变 - 在创建时初始化也称为readonly

Yes ... though I've never heard the term "blank immutable" used before. 是的......虽然我从未听过之前用过的“空白不可变”这个词。

Can make objects shallowly immutable 可以使对象浅不可变

Object mutability is about whether observable state may change. 对象可变性是关于可观察状态是否可能改变。 As such, declaring attributes final may or may not make the object behave as immutable. 因此,声明属性final可能会也可能不会使对象表现为不可变。 Besides the notion of "shallowly immutable" is not well defined, not least because the notion of what "shallow" is cannot be mapped without deep knowledge of the class semantics. 除了“浅不可变”的概念之外没有明确定义,尤其是因为没有对类语义的深入了解,就无法映射“浅”的概念。

(To be clear, the mutability of variables / fields is a well defined concept in the context of the JLS. It is just the concept of mutability of objects that is undefined from the perspective of the JLS.) (要明确的是,变量/字段的可变性是JLS上下文中定义明确的概念。从JLS的角度来看,它只是对象的可变性概念。)

Can make scope / visibility immutable 可以使范围/可见性不可变

Terminology error. 术语错误。 Mutability is about object state. 可变性是关于对象状态。 Visibility and scope are not. 可见性和范围不是。

Can make method invocation overhead smaller (because it does not need virtual table) 可以使方法调用开销更小(因为它不需要虚拟表)

In practice, this is irrelevant. 在实践中,这是无关紧要的。 A modern JIT compiler does this optimization for non-final methods too, if they are not overridden by any class that the application actually uses. 如果它们没有被应用程序实际使用的任何类重写,那么现代JIT编译器也会对非final方法执行此优化。 (Clever stuff happens ...) (聪明的事情发生......)

Can make method arguments used as final (even if thy are not) 可以使方法参数用作final(即使你不是)

Huh? 咦? I cannot parse this sentence. 我无法解析这句话。

Can make objects threadsafe 可以使对象线程安全

In certain situations yes. 在某些情况下是的。

(if object is defined as final, it wont make method arguments final) (如果对象被定义为final,则不会使方法参数最终)

Yes, if you mean if class is final. 是的,如果你的意思是上课是最终的。 Objects are not final. 对象不是最终的。

Can make mock tests (not that you could do anything about it - you can say bugs are intended) 可以进行模拟测试(不是你可以对它做任何事情 - 你可以说错误是有意的)

Doesn't parse. 不解析。

Can't make friends (mutable with other friends and immutable for rest) 不能交朋友(与其他朋友互相变化,休息不变)

Java doesn't have "friends". Java没有“朋友”。

Can't make mutable that is changed to be immutable later (but can with factory pattern like fix) 以后不能将变为不可变的变量(但可以像工厂模式一样修复)

Yes to the first, a final field can't be switched from mutable to immutable. 对于第一个是, final字段不能从可变到不可变。

It is unclear what you mean by the second part. 目前还不清楚你的意思是第二部分。 It is true that you can use a factory (or builder) pattern to construct immutable objects. 确实,您可以使用工厂(或构建器)模式来构造不可变对象。 However, if you use final for the object fields at no point will the object be mutable. 但是,如果对象字段使用final ,则该对象不会是可变的。

Alternatively, you can implement immutable objects that use non-final fields to represent immutable state, and you can design the API so that you can "flip a switch" to make a previously mutable object immutable from now onwards. 或者,您可以实现使用非最终字段表示不可变状态的不可变对象,并且您可以设计API,以便您可以“翻转开关”以使先前可变对象从现在开始不可变。 But if you take this approach, you need to be a lot more careful with synchronization ... if your objects need to be thread-safe. 但是如果你采用这种方法,你需要对同步更加小心......如果你的对象需要是线程安全的。

Can't make array elements immutable aka deeply immutable 无法使数组元素成为不可变的,也是不可变的

Yes, but your terminology is broken; 是的,但是你的术语被打破了; see comment above about "shallow mutability". 请参阅上面有关“浅层可变性”的评论。

Can't make new instances of object (this is both good and bad) 无法创建对象的新实例(这既好又坏)

No. There's nothing stopping you making a new instance of an object with final fields or a final class or final methods. 没有。没有什么能阻止你用最终字段或最终类或最终方法创建一个对象的新实例。

Can't make serialization work 无法进行序列化工作

No. Serialization works. 编号序列化工作。 (Granted, deserialization of final fields using a custom readObject method presents problems ... though you can work around them using reflection hacks.) (当然,使用自定义readObject方法对final字段进行反序列化会出现问题......虽然您可以使用反射方法解决它们。)

There are no alternatives to final, 最终没有其他选择,

Correct. 正确。

but there is wrapper + private 但有包装+私人

Yes, modulo that (strictly speaking) an unsynchronized getter for a non-final field may be non-thread-safe ... even if it is initialized during object construction and then never changed ! 是的,模数(严格地说)非最终字段的非同步getter可能是非线程安全的...... 即使它在对象构造期间被初始化然后从未改变过

and enums. 和枚举。

Solves a different problem. 解决了另一个问题。 And enums can be mutable. enums可以是可变的。

Final keyword is usually used to preserve immutability. Final关键字通常用于保持不变性。 To use final for classes or methods is to prevent linkages between methods from being broken. 对类或方法使用final是为了防止方法之间的联系被破坏。 For example, suppose the implementation of some method of class X assumes that method M will behave in a certain way. 例如,假设类X的某些方法的实现假定方法M将以某种方式运行。 Declaring X or M as final will prevent derived classes from redefining M in such a way as to cause X to behave incorrectly. 将X或M声明为final将阻止派生类重新定义M,从而导致X行为不正确。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM