Java 什么是;“最后的”;如果你把它放在变量之前,你会怎么做?

Java 什么是;“最后的”;如果你把它放在变量之前,你会怎么做?,java,Java,非常基本的问题,但是,如果你把“final”放在一个变量之前,比如下面,它会做什么呢 final EditText myTextField = (EditText) findViewById(R.id.myTextField); final做什么?简短回答 停止将“myTextField”变量分配给其他变量 长答案 不会停止“myTextField”变量的变异,例如将其字段设置为新值 使代码更具可读性(IMHO),因为读者永远不必怀疑“myTextField”变量是否会在代码中重新分配 防止

非常基本的问题,但是,如果你把“final”放在一个变量之前,比如下面,它会做什么呢

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

final
做什么?

简短回答

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

长答案

  • 不会停止“myTextField”变量的变异,例如将其字段设置为新值
  • 使代码更具可读性(IMHO),因为读者永远不必怀疑“myTextField”变量是否会在代码中重新分配
  • 防止意外重新分配变量的错误类别(使实例不可变的原因相同,只是规模较小)

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

一旦分配了
myTextField
的引用,您就不能修改它。更多信息请访问

只能指定最终变量 一旦此任务不授予 变量为不可变状态。如果 变量是类的一个字段,它 必须在的构造函数中指定 它的等级。(注意:如果变量为 参考,这意味着 无法将变量重新绑定到 引用另一个对象。但是 它引用的对象仍然是 可变的,如果它最初是 与a的值不同 常数,最终值 变量不一定是已知的 编译时


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

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

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

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

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

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

如果您尝试为myTextField赋值,您将得到一个编译器错误。

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

跟进

这是JVM特有的吗

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

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


除此之外,Java内存模型的设计允许多核机器运行多个Java线程,而无需不断刷新内存缓存。。。这将扼杀性能。基本上,它指定了一些规则来保证一个Java线程看到来自另一个线程的内存更新。如果应用程序不遵循规则,则线程可能会看到由其他线程编写的某个字段的过时(过期)值,导致偶尔出现未定义的行为。

如果变量被标记为final,则该变量的值不能更改,即final关键字在与变量一起使用时使其成为常量。如果您在编程过程中试图更改该变量的值,编译器将给您一个错误。

试图解释
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

}
输出:

Mike
Jenna
Mike
pwnd
pwnd
Jenna
pwnd
Henna

好!我想我得到了答案!(6个答案!哇!)所有这些工作。如果它提供了有用的功能,我就不认为它是臃肿的。我想我知道最后的足够了,但现在我意识到我必须知道更多。不,在JMM里@安德森-我刚才说:-)机械的重复被低估了@斯蒂芬:很明显,我的拼写练习包括不充分的死记硬背。@andersoj-或者换句话说,你的气味难闻:-)