为啥 Java 变量不更频繁地声明为“final”?与 swift 中的 let 关键字进行比较 [关闭]
Posted
技术标签:
【中文标题】为啥 Java 变量不更频繁地声明为“final”?与 swift 中的 let 关键字进行比较 [关闭]【英文标题】:Why isn't Java variable declared as `final` more often? Compare to let keyword in swift [closed]为什么 Java 变量不更频繁地声明为“final”?与 swift 中的 let 关键字进行比较 [关闭] 【发布时间】:2016-11-03 12:53:22 【问题描述】:在swift中,如果变量在初始化后没有变化,建议使用let
关键字声明变量。我看到很多变量声明为let
。
在java中,我认为关键字final
可以达到同样的目的。但根据我有限的经验,我只看到人们在极少数情况下将变量声明为final
,例如PI。
为什么不经常将 Java 变量声明为 final
?我有什么遗漏吗?
【问题讨论】:
因为它是额外的打字并且程序员很懒惰。但是,如果您使用 IDE,它可能会在您保存文件时自动“在可能的情况下添加 final”。 因为人都是懒惰的。final
在 Java 8 之前对于闭包是必需的,但除此之外很少使用。我和Robert Simmons Jr. 主张它的采用率更高。主要原因是它确实在编译时过滤掉了一些愚蠢的错别字。但由于它对程序运行时间没有影响,与 C++ 中的const
不同,对于额外的打字和代码噪音,没有足够强大的(对许多人而言)论据。
是的,你应该这样做。它清楚地表明了您的意图(不想意外更改值)。您与编译器交流的每一个意图都有助于捕获错误(与 @Override
相同的参数——可能应该是强制性的和/或关键字,但现在为时已晚,语言已经过时了)。
请注意:这不是一个好问题;你基本上是在询问意见。我的两分钱:您想让尽可能多的字段(静态或非静态)最终化;但我个人不参与将 final 放在方法参数或局部变量上的业务。
@Jägermeister:嗯,对于字段,大多数开发人员会同意使用 final 很有用。但是对于参数和局部变量,不同的开发者有不同的看法。因此,这个问题的答案不一定是关于意见,而是指出存在不同意见。
【参考方案1】:
见In Java, should I use “final” for parameters and locals even when I don't have to?
基本上,对于字段来说,它是有用的并且还会改变它们的并发属性。 见Java concurrency: is final field (initialized in constructor) thread-safe?
但是,对于局部变量和参数,final 的值不太清楚。它有一些语义价值,但另一方面,它也可能是噪音
public void foo (final int x, final int y)
try
final int z = x+y;
catch (final Exception z)
final String message = "";
throw new RuntimeException(message);
相比
public void foo (int x, int y)
try
int z = x+y;
catch ( Exception z)
String message = "";
throw new RuntimeException(message);
如果你有简短的方法(你通常应该有),那么很明显变量没有被改变。
因此,一些开发人员更喜欢使用 final 的语义值,而另一些开发人员则不喜欢使用它,因为它很冗长。
【讨论】:
“而其他人不喜欢使用它,因为它很冗长”。对于许多人来说,这适用于整个 Java :-) @Thilo:确实如此,但由于 Java 已经非常冗长,因此您不必在不必要时使其更加冗长 :)【参考方案2】:Java 遵循传统的 C 思维方式,如果我们创建某些东西(原始类型或对象),默认情况下它是一个变量,您必须在 java 中放入“final”,在 C/C++ 中放入“const”才能实现一个常数。与这些语言相比,Swift 是非常新的,它的目标是安全的编程模式和简单性。如果您在 Java 方面获得更多经验,您就会知道人们确实更经常地使用最终实践和最佳实践。我认为(正如您也提到的)的主要原因是您对 Java 的了解有限。
【讨论】:
【参考方案3】:为什么不经常将 Java 变量声明为 final?我有什么遗漏吗?
你缺少的是“人性”。
简单地说,Java 的语法使不添加final
变得更容易。一般来说,人们不会这样做,因为不这样做更容易。
请注意,“变量默认不是最终的”设计决策来自 Java 的祖先。
当然,这并没有解决您隐含的问题,即 Java 程序员应该更频繁地使用final
1。但这是一个意见问题,*** 不鼓励基于意见的问答。
1 - .... 在适当的情况下。在变量显然需要可变的情况下使用 final
会适得其反。
【讨论】:
这也适用于类和方法,有人说默认应该是final
。
是的......虽然这是一个不同的问题。在那里,您正在处理由于继承导致的抽象破坏问题。
@shmosel 您应该尽可能声明方法final
(只要您不会覆盖它)。否则它们默认是虚拟的并且有性能损失。
@StephenC 你能告诉我在哪里可以问这种与编程相关的基于意见的问答吗?
@XiaojunChen - 这是不正确的。 JIT 编译器会处理这个问题。【参考方案4】:
在 Java 中使用 final
初始化变量允许编译器确保您只能初始化一次。如果是int
或doubles
这样的原始类型,则可以保证值不能改变。但是,对于Object
,final
仅与引用本身有关,与被引用对象的内容无关。它不保证被引用的对象内部的值保持不变。
例如,我可以用 final 定义一个 List 如下:
final List<String> foo = new ArrayList<String>();
上面的List
foo
不能再次初始化,但它的内容可以改变,即它不会使foo
不可变。因此,这会使 final
关键字的用处降低。
final
关键字在声明一个常量值时占有一席之地,尤其是当类中只需要一个使用static
关键字的实例时。以下是java.util.Random.Math
中的示例:
public final class Math
public static final double PI = 3.14159265358979323846;
【讨论】:
【参考方案5】:我认为这是因为 Java 中没有这样的“传统”。
你看,我读的第一本关于 Swift 的书(Apple Inc. 的 The Swift Programming Language 2.0)说,你创建的每个没有变异的变量都应该声明为 let
常量。
由于 The Swift Programming Language 2.0(本书)是 Swift 的官方指南,因此几乎每个人都遵循它。即使人们不读那本书,他们也会读读过那本书的人写的教程。结果大家的编码风格都是这样的。
相比之下,我读过的第一本关于 Java 的书(傻瓜用 Java 编程)并没有强调如果值不会改变我们应该使用 final
。官方文件也很少这样做。所以只有少数程序员遵循这条规则。这导致大多数人编写的代码实际上都遵循此规则。
此外,在 Java 中,你必须多写 5 个字符(单词“final”加上一个空格)来声明一个常量,而在 Swift 中,你不需要写任何额外的字符(var 和 let 有相同的数字)字符)!程序员很懒,你知道的。
【讨论】:
【参考方案6】:至少根据我的经验,如果变量在启动后没有改变,建议使用final
。对于原始类型,JVM 会将其视为常量并进行一些优化。
在其他情况下,例如在 Java 中,所有方法默认情况下都是虚拟的,除非声明为 final
。它还将获得计算性能。
【讨论】:
以上是关于为啥 Java 变量不更频繁地声明为“final”?与 swift 中的 let 关键字进行比较 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章