15

为什么不声明一个数组 final 使其在 Java 中不可变?声明最终的东西不意味着它不能改变吗?

与不可变数组相关的问题中,很明显声明一个数组 final 并不能使其不可更改。

以下是可能的。

final int[] array = new int[] {0, 1, 2, 3};
array[0] = 42;

我的问题是:那么在这里声明 final 的功能是什么?

4

6 回答 6

32

final仅与它所标记的参考有关;Java中没有不可变数组这样的东西。当你说

private final int[] xs = new int[20];

你不能说

xs = new int[10];

稍后的。这就是全部内容final。更一般地说,确保一个对象是不可变的通常是一项艰巨的工作,并且充满了一系列微妙之处。语言本身并没有为此提供太多开箱即用的功能。

于 2012-12-20T20:10:44.573 回答
8

final意味着您不能更改引用- 即您不能将另一个数组分配给该字段。

“不可变”意味着您无法更改数组的内容final-对此没有影响。

如您的代码所示,您可以为数组的一个元素分配一个值,这不会更改对数组的引用

于 2012-12-20T20:12:58.753 回答
3

在这里,您正在创建对象引用 final,而不是原始对象。(数组也是特殊的 Java 对象。)创建一个引用final意味着一旦它被初始化就不能让它引用其他东西。当然,您可以更改由 final 变量引用的对象的状态。

于 2012-12-20T20:10:52.200 回答
1

声明一个数组

在 Java 中,我们声明变量,并创建对象(例如数组)。这些动作是独立的;我们可以在不创建对象的情况下声明一个变量,也可以在不声明变量的情况下创建一个对象。

不变性是对象的属性,而 final 是变量的属性。一个对象可以被多个变量引用。哪个变量应该控制数组对象的不变性?

int[] a = {1,2,3};
final int[] b = a;
a[0] = 10; // should this be legal?

如果我们允许这样做,则假定的不可变值b[0]已更改。但是编译器如何防止这种情况发生呢?通过使无法将非最终引用分配给最终引用?那么我将如何初始化数组呢?我不能循环这样做......

并且:数组是不可变的甚至意味着什么?例如,以下是否应该编译?

final int[][] a = {{1,2}, {3,4}};
a[1][1] = 5;

C++ 通过允许const为每个间接级别指定(或省略)来解决这个问题。在 Java 中,final 可以为每个变量指定(或省略)一次。是的,final是一个更简单const的,就像 Java 是一个更简单的 C++。让我们保持简单,好吗?

于 2012-12-23T19:09:26.660 回答
0

这意味着不允许对象的新实例。

于 2012-12-20T20:11:31.200 回答
0

就像每个人评论的那样,将其声明为 final 不会让您将另一个数组分配给您的变量。在这里阅读更多

数组本身将保留与以前相同的属性。

于 2012-12-20T20:15:50.560 回答