Java 最终修饰符
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4012167/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java final modifier
提问by Margus
I was told that, I misunderstand effects of final
. What are the effects of final
keyword?
有人告诉我,我误解了final
. final
关键字的作用是什么?
Here is short overview of what I think, I know:
这是我的想法的简短概述,我知道:
Java final modifier (aka aggregation relation)
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 final 修饰符(又名聚合关系)
原始变量:只能设置一次。(内存和性能增益)
对象变量:可以修改,最终适用于对象引用。
fields:只能设置一次。
方法:不能被覆盖,隐藏。
类:不能扩展。
垃圾收集:将强制 Java 分代垃圾收集标记扫描进行双重扫描。
Can's and Cant's
罐头和罐头
- Can make clone fail (this is both good and bad)
- Can make immutable primitives aka const
- Can make blank immutable - initialized at creation aka 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)
- Can make objects threadsafe (if object is defined as final, it wont make method arguments 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
- 可以使克隆失败(这有好有坏)
- 可以制作不可变的原语又名 const
- 可以使空白不可变 - 在创建时初始化又名只读
- 可以使对象浅不可变
- 可以使范围/可见性不可变
- 可以使方法调用开销更小(因为不需要虚表)
- 可以将方法参数用作最终的(即使你不是)
- 可以使对象线程安全(如果对象被定义为 final,它不会使方法参数成为 final)
- 可以进行模拟测试(不是说您可以对此做任何事情-您可以说是有缺陷的)
- 不能交朋友(与其他朋友可变,休息不可变)
- 不能使以后更改为不可变的可变(但可以使用工厂模式,如修复)
- 不能使数组元素不可变,即深度不可变
- 不能创建对象的新实例(这既好又坏)
- 无法使序列化工作
There are no alternatives to final
, but there is wrapper + private and enums.
没有替代品final
,但有包装器 + 私有和枚举。
采纳答案by Stephen C
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.
objects 变量:可以修改,final 适用于对象引用。
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 whatsoeverto garbage collection. 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. The GC then runs the finalize method on the object and sets its flag ... and continues. The next time the GC runs, the object is treated as a normal object:
但即使是终结器也不会强制执行额外的扫描。发生的情况是需要终结的对象被设置在一侧,直到主 GC 完成。GC 然后在对象上运行 finalize 方法并设置它的标志......并继续。下次 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; i.e. 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
可以制作不可变的原语又名 const
Yes.
是的。
Can make blank immutable - initialized at creation aka 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. 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.
对象可变性是关于可观察状态是否可能改变。因此,声明属性final
可能会也可能不会使对象表现为不可变的。此外,“浅不可变”的概念没有得到很好的定义,尤其是因为如果没有对类语义的深入了解,就无法映射“浅”的概念。
(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. (Clever stuff happens ...)
在实践中,这无关紧要。如果非最终方法没有被应用程序实际使用的任何类覆盖,现代 JIT 编译器也会对非最终方法进行这种优化。(聪明的事情发生了......)
Can make method arguments used as final (even if thy are not)
可以将方法参数用作最终的(即使你不是)
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)
(如果对象被定义为最终的,它不会使方法参数最终)
Yes, if you mean if classis 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. But if you take this approach, you need to be a lot more careful with synchronization ... if your objects need to be thread-safe.
或者,您可以实现使用非最终字段来表示不可变状态的不可变对象,并且您可以设计 API,以便您可以“翻转开关”使以前的可变对象从现在开始不可变。但是如果你采用这种方法,你需要更加小心同步......如果你的对象需要是线程安全的。
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.
不。没有什么能阻止您使用 final 字段或 final 类或 final 方法创建对象的新实例。
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.)
不。序列化有效。(当然,final
使用自定义readObject
方法对字段进行反序列化会出现问题……尽管您可以使用反射技巧来解决这些问题。)
There are no alternatives to final,
除了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
可以是可变的。
回答by Katie
Final keyword is usually used to preserve immutability. To use final for classes or methods is to prevent linkages between methods from being broken. For example, suppose the implementation of some method of class X assumes that method M will behave in a certain way. Declaring X or M as final will prevent derived classes from redefining M in such a way as to cause X to behave incorrectly.
final 关键字通常用于保持不变性。对类或方法使用 final 是为了防止方法之间的链接被破坏。例如,假设类 X 的某个方法的实现假定方法 M 将以某种方式运行。将 X 或 M 声明为 final 将防止派生类以导致 X 行为不正确的方式重新定义 M。