为什么需要“final”和“mut”这样的关键字?

try*_*arn 2 java rust

https://www.baeldung.com/java-final-performancefinal该博客给出了在java中 使用关键字来提高性能的示例。这是他们给出的例子:

public static String concatNonFinalStrings() {
    String x = "x";
    String y = "y";
    return x + y;
}

public static String concatFinalStrings() {
    final String x = "x";
    final String y = "y";
    return x + y;
}
Run Code Online (Sandbox Code Playgroud)

显然,编译器将优化concatFinalStrings()为仅返回"xy". 为什么编译器不能对 做同样的事情concatNonFinalStrings()x并且y范围有限,并且从未在其他地方使用过。那么,编译器当然应该能够将它们视为最终的吗?不可能有一些外部实体可以改变x和的值y,因为它们在函数外部是不可访问的。我链接的博客将这些称为“有效最终”,并指出编译器不会对“有效最终”变量执行代码优化。为什么不?

此外,为什么mutRust 中存在这样的关键字?也许在 Java 中这是有意义的,你可以拥有公共变量,并且你不知道还.class存在哪些其他文件,但在 Rust 中,如果整个过程立即编译,那么编译器肯定可以mut通过查看哪些变量发生变化来推断出哪些变量。他们的价值?现在这些是否只是为了使代码更清晰而存在,而实际上并没有提供任何类型的优化?

Bla*_*ans 5

首先,尽管编译器可以通过“足够聪明”推断出很多东西,但你必须考虑到编译时间是有限的。编译器不能只是尝试人类已知的所有优化来看看是否有合适的,因为那太长了。由于静态优化可以通过final关键字强制执行,因此编译器为您进行优化没有多大意义(这需要时间)。


至于 Rust,这是一个类似的答案(试图找出代码运行时应该可变的变量的最小数量会很长),此外,即使是这种情况,行为也会非常困难预测,因为单个更改可以完全修改应该可变的最小变量集,以使代码健全(如果甚至存在),如果不存在,则报告的错误将是可怕的(因为编译器不能指责任何特定的代码片段,只是整体上代码无法健全)。要查看此行为的一些示例,您可以查看 OCaml 中的多态变体,其中编译器将为每个值推断出最通用的类​​型,但如果不可能,错误消息很快就会变得可怕。

关于 Rust 中显式可变性的最后一个论点是接口:当然,编译器在编译时知道一切,但是当我编写一个库并声明一个接口(任何接口,可能是函数签名或其他任何东西)时,我可能想要强制变量的可变性,或者相反,强制其不变性,即使不知道消费者将如何使用它。这允许编译器对我的库进行类型检查,包括可变性,即使不知道它的实际使用方式。


我什至没有提到可读性:明确通常也意味着更具可读性。

旁注:您在 Java 中描述的内容实际上被称为最终的。