Java 如果将“final”放在变量之前,它会做什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4011520/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 08:21:54  来源:igfitidea点击:

What does "final" do if you place it before a variable?

java

提问by Hyman Love

Very basic question, but, what does "final" do if you place it before a variable such as below...

非常基本的问题,但是,如果将“final”放在如下变量之前,它会做什么...

final EditText myTextField = (EditText) findViewById(R.id.myTextField);

What does finaldo?

有什么作用final

采纳答案by Andrew Swan

Short Answer

简答

Stops the "myTextField" variable being assigned to something else.

停止将“myTextField”变量分配给其他变量。

Long Answer

长答案

  • Does NOT stop the "myTextField" variable being mutated, e.g. having its fields set to new values.
  • Makes code more readable (IMHO) because the reader never has to wonder whether the "myTextField" variable will be reassigned later on in the code.
  • Guards against the category of bug whereby variables are accidentally reassigned (same reasoning behind making instances immutable, only on a smaller scale).
  • 不会阻止“myTextField”变量发生变异,例如将其字段设置为新值。
  • 使代码更具可读性(恕我直言),因为读者永远不必怀疑“myTextField”变量是否会在代码中重新分配。
  • 防止意外重新分配变量的错误类别(使实例不可变背后的原因相同,只是规模较小)。

For the reasons given above, I always apply the "final" modifier wherever I can to static fields, instance fields, local variables, and method parameters. It does bloat the code a little, but for me it's worth the extra readability and robustness.

由于上述原因,我总是尽可能将“final”修饰符应用于静态字段、实例字段、局部变量和方法参数。它确实使代码膨胀了一点,但对我来说,额外的可读性和健壮性是值得的。

回答by rkg

You can't modify the reference of myTextFieldonce it is assigned. More information below from Wikipedia

myTextField一旦分配了引用,您就无法修改它。以下来自维基百科的更多信息

A final variable can only be assigned once. This assignment does not grant the variable immutable status. If the variable is a field of a class, it must be assigned in the constructor of its class. (Note: If the variable is a reference, this means that the variable cannot be re-bound to reference another object. But the object that it references is still mutable, if it was originally mutable.) Unlike the value of a constant, the value of a final variable is not necessarily known at compile time.

final 变量只能赋值一次。此赋值不会授予变量不可变状态。如果变量是类的字段,则必须在其类的构造函数中赋值。(注意:如果变量是引用,这意味着该变量不能被重新绑定到引用另一个对象。但它引用的对象仍然是可变的,如果它原来是可变的。)与常量的值不同,在编译时不一定知道最终变量的值。

回答by Michael Aaron Safyan

The keyword final, in this context, means that you cannot update the implicit pointer myTextFieldto point to a different object (although you can modify the object pointed to by myTextField). The keyword may also be used to prevent overriding (when applied to classes or methods).

final在此上下文中,关键字意味着您无法更新隐式指针myTextField以指向不同的对象(尽管您可以修改 指向的对象myTextField)。该关键字还可用于防止覆盖(当应用于类或方法时)。

One reason why you might see this is that anonymous classes that reference local variables can only reference variables marked final. This is so that the anonymous classes need only store a duplicate reference and do not need to maintain the complete access to the local function stack. For example:

您可能会看到这一点的原因之一是,引用局部变量的匿名类只能引用标记为 的变量final。这样匿名类只需要存储一个重复的引用,而不需要维护对本地函数堆栈的完整访问。例如:

Runnable r = new Runnable() { public static void run() {
         // do something with myTextField
         // this would require myTextField to have been marked final.
}};
doSomethingLater(r);

回答by irrelephant

The keyword finaldeclares myTextFieldas a constant variable.

关键字final声明myTextField为常量变量。

回答by Suresh Kumar

The finalkeyword will ensure that myTextFieldholds the reference of whatever findViewByID() returns and disallows any other assignment to myTextFieldvariable i.e. after the execution of the

final关键字将确保myTextField保留任何 findViewByID() 返回的引用,并禁止对myTextField变量进行任何其他赋值,即在执行

final EditText myTextField = (EditText) findViewById(R.id.myTextField);

If you try to assign any value to myTextField, you will get a compiler error.

如果您尝试为 myTextField 分配任何值,您将收到编译器错误。

回答by Stephen C

One thing that none of the other answers have noted is that a finalattribute has special properties vis-a-vis the Java memory model. The net effect is that one thread can safely access a finalattribute's value without taking steps to synchronize with other threads.

其他答案都没有注意到的一件事是,final相对于 Java 内存模型,属性具有特殊的属性。最终效果是一个线程可以安全地访问final属性值,而无需采取措施与其他线程同步。

FOLLOWUP

跟进

Is that JVM specific?

那是JVM特定的吗?

The specification of the Java memory model is part of the Java Language Specification, and (AFAIK) hasn't changed since Java 1.5. In that sense this is not JVM specific.

Java 内存模型的规范是 Java 语言规范的一部分,并且 (AFAIK) 自 Java 1.5 以来没有改变。从这个意义上说,这不是特定于 JVM 的。

However, the behaviour of Java if you don't follow the rules (i.e. if your code does not properly synchronize its use of shared data) depends on all sorts of things, including the hardware you run the application on.

但是,如果您不遵守规则(即,如果您的代码没有正确同步其对共享数据的使用),Java 的行为取决于各种因素,包括您运行应用程序的硬件。

Among other things, the Java memory model is designed to allow multi-core machines to run many Java threads without having to continually flush the memory caches ... which would kill performance. Basically, it specifies some rules that will guarantee that one Java thread sees memory updates from another thread. If an application doesn't follow the rules, it is possiblethat a thread will see a stale (out of date) value for some field written by some other thread, resulting in occasional undefined behaviour.

除其他外,Java 内存模型旨在允许多核机器运行多个 Java 线程,而无需不断刷新内存缓存……这会降低性能。基本上,它指定了一些规则,以保证一个 Java 线程可以看到来自另一个线程的内存更新。如果应用程序不遵守规则,则线程可能会看到其他线程写入的某些字段的过时(过时)值,从而导致偶尔出现未定义的行为。

回答by farhankhwaja

If a variable is marked as finalthen the value of that variable cannot be changed i.e final keyword when used with a variable makes it a constant. And if you try to change the value of that variable during the course of your program the compiler will give you an error.

如果一个变量被标记为final,则该变量的值不能改变,即 final 关键字与变量一起使用时使其成为常量。如果您在程序运行期间尝试更改该变量的值,编译器会给您一个错误。

回答by nabster

Trying to explain use of finalmodifier with flow of code:

试图用final代码流来解释修饰符的使用:

public static void main(String[] args) {

    class Person {
        String name;
    }

    Person peep1 = new Person(); // points to obj at address HEX001
    peep1.name = "Mike"; 
    System.out.println(peep1.name);

    Person peep2 = new Person(); // points to obj at address HEX002
    peep2.name = "Jenna";
    System.out.println(peep2.name);

    final Person peep3 = peep1; // also points to obj at address HEX001
    System.out.println(peep3.name);

    peep1.name = "pwnd"; // modifies obj at address HEX001
    System.out.println(peep1.name);
    System.out.println(peep3.name);

    peep1 = peep2; // now it points to obj at address HEX002
    System.out.println(peep1.name);

    System.out.println(peep3.name); // still points to obj at address HEX001

    peep2.name = "Henna"; // modifies obj at address HEX002
    System.out.println(peep2.name);

    peep3 = peep2; // compiler error "The final local variable peep3 cannot be assigned. It must be
                    // blank and not using a compound assignment"

    System.out.println(peep3.name); // assuming it now points to obj at address HEX002

}

Output:

输出:

Mike
Jenna
Mike
pwnd
pwnd
Jenna
pwnd
Henna