60

Java中的以下代码使用了一个final数组,String这是毫无疑问的。

final public class Main {
  public static final String[] CONSTANT_ARRAY = {"I", "can", "never", "change"};

  public static void main(String[] args) {
    for (int x = 0; x < CONSTANT_ARRAY.length; x++) {
      System.out.print(CONSTANT_ARRAY[x] + " ");
    }
  }
}

它在控制台上显示以下输出。

I can never change

以下代码也毫无疑问。

final public class Main {
  public static final String[] CONSTANT_ARRAY = {"I", "can", "never", "change"};

  public static void main(String[] args) {
    //CONSTANT_ARRAY={"I", "can", "never", "change"}; //Error - can not assign to final variable CONSTANT_ARRAY.
    for (int x = 0; x < CONSTANT_ARRAY.length; x++) {
      System.out.print(CONSTANT_ARRAY[x] + " ");
    }
  }
}

显然,注释行会导致指定的错误,因为我们试图重新分配声明final的 type 数组String


下面的代码呢。

final public class Main {
  public static final String[] CONSTANT_ARRAY = {"I", "can", "never", "change"};

  public static void main(String[] args) {
    CONSTANT_ARRAY[2] = "always";  //Compiles fine.
    for (int x = 0; x < CONSTANT_ARRAY.length; x++) {
      System.out.print(CONSTANT_ARRAY[x] + " ");
    }
  }
}

它显示I can always change意味着我们可以设法修改finaltype 数组的值String。我们可以在不违反 规则的情况下以这种方式修改整个数组final吗?

4

9 回答 9

100

final在 Java 中影响变量,它与您分配给它的对象无关。

final String[] myArray = { "hi", "there" };
myArray = anotherArray; // Error, you can't do that. myArray is final
myArray[0] = "over";  // perfectly fine, final has nothing to do with it

编辑以添加评论:请注意,我说的是您分配给它的对象。在 Java 中,数组是一个对象。这同样适用于任何其他对象:

final List<String> myList = new ArrayList<String>():
myList = anotherList; // error, you can't do that
myList.add("Hi there!"); // perfectly fine. 
于 2012-04-26T19:23:56.387 回答
19

您误解了最终的实现。final适用于数组对象引用,这意味着一旦启动,引用永远不会改变,但可以填充其自身的数组。“它没有违反规则”您只指定了一条关于参考更改的规则,该规则正在相应地起作用。如果您希望这些值也永远不会改变,您应该选择不可变列表,即

List<String> items = Collections.unmodifiableList(Arrays.asList("I", "can", "never", "change"));
于 2012-04-26T19:34:12.707 回答
11

您只能这样做,因此无法更改数组引用。如果您希望元素无法更改,则需要使用某种不可修改的集合。

于 2012-04-26T19:22:32.753 回答
3

将数组声明为 final 时,可以更改数组中的元素,但不能更改该数组的引用。

于 2012-04-26T19:24:46.353 回答
3

final 只保证原语的不变性。并且还保证一个变量只分配一次。如果一个对象是可变的,您可以更改它定义为 final 的事件的内容。您可以根据需要检查不可变集合。如 Collections.unmodifiableList() http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#unmodifiableList(java.util.List )

于 2012-04-26T19:26:11.690 回答
2

对数组对象的引用是最终的(不能更改,例如,如果您试图将不同的 Java 数组对象(String[] 的实例)关联到同一个最终变量……您会得到一个编译时错误)。

但是您示例中最终数组对象的字段不是最终的,因此您可以修改它们的值。...而您创建的 Java 对象 CONSTANT_ARRAY 在收到初始值后将具有该值“永远”== 直到 JVM 停止。:) 它将是“永远”相同的字符串数组实例。

Java 中的 final 变量没什么大不了的,只需花一些时间仔细消化主题/想法。:-)
我建议所有不确定在此页面上冥想的人,例如: https ://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12 .4

让我引用相应的部分:

"一旦一个 final 变量被赋值,它总是包含相同的值。如果一个 final 变量持有对一个对象的引用,那么对象的状态可能会通过对对象的操作而改变,但变量总是引用同一个对象。

这也适用于数组,因为数组是对象;如果最终变量持有对数组的引用,则数组的组成部分可能会通过对数组的操作而改变,但变量将始终引用同一个数组。"

于 2015-09-13T22:59:12.140 回答
1

变量 CONSTANT_ARRAY 的值不能改变。该变量包含一个(对一个)数组的引用。但是,数组的内容可以更改。当您声明任何非简单标量类型的最终变量(例如对象)时,也会发生同样的事情。

请注意如何命名变量。:-) 称它为 CONSTANT_ARRAY 并不会使数组的内容不可更改。

这是一个很好的参考:final 上的最后一句话

于 2012-04-26T19:25:11.253 回答
0

当一个变量用 final 关键字声明时,它的值不能被修改,本质上是一个常量。这也意味着您必须初始化最终变量。如果最终变量是一个引用,这意味着该变量不能重新绑定到引用另一个对象,但该引用变量指向的对象的内部状态可以更改,即您可以在最终数组中添加或删除元素或最后的集合。

于 2020-06-23T10:29:20.447 回答
-2
    final int[] res;
    int[] res1;
    int[] res2 = new int[1];
    res2[0]=20;

    res1=res2;
    res1=res2;//no error
    System.out.println("res1:"+res1[0]);

    res = res2;//only once
   //res = res2;//error already initialised
    res2[0]=30;

    System.out.println("res:"+res[0]);     

输出:: res1:20 res:30

于 2017-09-18T04:44:06.537 回答