在Java中,我们使用带有变量的final关键字来指定其不被更改的值。 但我看到你可以改变类的构造函数/方法的值。同样,如果变量是静态的,那么这是一个编译错误。

代码如下:

import java.util.ArrayList;
import java.util.List;

class Test {
  private final List foo;

  public Test()
  {
      foo = new ArrayList();
      foo.add("foo"); // Modification-1
  }
  public static void main(String[] args) 
  {
      Test t = new Test();
      t.foo.add("bar"); // Modification-2
      System.out.println("print - " + t.foo);
  }
}

以上代码工作正常,没有错误。

现在将变量更改为静态:

private static final List foo;

现在它是一个编译错误。期末考试是怎么进行的呢?


当前回答

Final关键字有很多种用法:

final类不能被子类化。 final方法不能被子类重写 final变量只能初始化一次

其他用途:

在方法体中定义匿名内部类时, 在该方法范围内声明为final的所有变量为 从内部类内部访问

静态类变量将从JVM开始时就存在,并且应该在类中初始化。如果您这样做,错误消息将不会出现。

其他回答

以下是使用final的不同上下文。

最终变量一个最终变量只能赋值一次。如果变量是引用,这意味着不能将该变量重新绑定到引用另一个对象。

class Main {
   public static void main(String args[]){
      final int i = 20;
      i = 30; //Compiler Error:cannot assign a value to final variable i twice
   }
}

Final变量可以稍后赋值(声明时不强制赋值),但只能赋一次。

Final类不能扩展(继承)

final class Base { }
class Derived extends Base { } //Compiler Error:cannot inherit from final Base

public class Main {
   public static void main(String args[]) {
   }
}

Final方法不能被子类覆盖。

//Error in following program as we are trying to override a final method.
class Base {
  public final void show() {
       System.out.println("Base::show() called");
    }
}     
class Derived extends Base {
    public void show() {  //Compiler Error: show() in Derived cannot override
       System.out.println("Derived::show() called");
    }
}     
public class Main {
    public static void main(String[] args) {
        Base b = new Derived();;
        b.show();
    }
}

假设你有两个储蓄罐,红的和白的。你把这些钱箱只分配给两个孩子,他们不允许交换他们的钱箱。所以你有红色或白色的钱箱(最终),你不能修改盒子,但你可以把钱放在你的盒子上。没人在乎(修改-2)。

值得一提的是一些简单的定义:

类/方法

您可以将类的部分或全部方法声明为final,以指示该方法不能被子类覆盖。

变量

一旦final变量初始化,它总是包含相同的值。

Final基本上避免被任何东西(子类,变量“重赋”)覆盖/上写,这取决于情况。

Final关键字有很多种用法:

final类不能被子类化。 final方法不能被子类重写 final变量只能初始化一次

其他用途:

在方法体中定义匿名内部类时, 在该方法范围内声明为final的所有变量为 从内部类内部访问

静态类变量将从JVM开始时就存在,并且应该在类中初始化。如果您这样做,错误消息将不会出现。

final关键字表示变量只能初始化一次。在你的代码中,你只执行了一次final的初始化,所以条件是满足的。该语句执行foo的单独初始化。注意final != immutable,它只意味着引用不能改变。

foo = new ArrayList();

当你将foo声明为static final时,变量必须在类加载时初始化,并且不能依赖实例化(也就是调用构造函数)来初始化foo,因为静态字段必须在没有类实例的情况下可用。不能保证在使用静态字段之前已经调用了构造函数。

当你在静态final场景下执行你的方法时,Test类在实例化t之前被加载,此时foo没有实例化,这意味着它还没有初始化,所以foo被设置为所有对象的默认值,即null。此时,我假设您的代码在尝试向列表中添加项时抛出NullPointerException。