5

我不是 Java 程序员。我阅读了有关“final”的文档,并将其理解为“变量的值可以设置一次且仅一次”。

我正在将一些 Java 翻译成 C#。代码未按预期执行。我试图找出原因,并发现 final 的一些用途没有意义。

代码片段1:

final int[] PRED = { 0, 0, 0 };
...
PRED[1] = 3;

PRED[1] 是 0 还是 3?

代码片段2:

final int[] PRED = new int[this.Nf];
for (int nComponent = 0; nComponent < this.Nf; nComponent++) {
    PRED[nComponent] = 0;
}
...
PRED[1] = 3;

PRED[0] 肯定会保持为 0 吗?

4

6 回答 6

6

我认为您在将final关键字语义应用于 Java 中的数组时存在误解。

在这两个 Java 示例中,数组将保持不变,但它们的元素可能会更改。您的所有分配都将正确执行,并且存储在数组中的值将被更改。但是,如果您尝试

final int[] PRED = new int[this.Nf];
// some other code
PRED = new int[123]; // <<== Compile error

你会看到一个编译错误。

将代码翻译成 C# 时,您可能需要翻译finalsealed(当它应用于 a 时class)或 as readonly(当它应用于成员时)。readonlyC#中的数组和 Java 中的数组语义final相同:您的程序不能重新分配数组,但可以自由修改其元素。

final最后,在 C# 中根本不需要使用时使用 Java 特定的情况:当您需要在 Java 中的匿名本地类的方法中使用变量时,您必须创建该变量final。由于 C# 没有匿名本地类,因此您需要使用其他内容(可能使用匿名委托)来翻译那段代码。此类委托不限于使用只读变量。

于 2012-05-02T10:40:14.693 回答
3

您在 C# 中寻找的词是“const”:

const int SOMETHING = 10;

请注意,SIZE 也应该是常数。

此外,常量只能是 int、bool、string、char 等类型(仅限基本类型)。

所以如果你想要别的东西,比如数组或类,你可以这样做:

static readonly int[] PRED = new int[this.Nf];

Static Readonly 在逻辑上完全是 const 的意思,只是它在后台的定义略有不同,这使您可以更自由地使用它。(当你可以 - 你应该定义常量而不是静态只读的)

数组本身在运行期间不会更改,因此您将无法执行此操作:

PRED = new int[3]; // Error
PRED = null; // Error
PRED = PRED; // Error

但是您可以更改 PRED 数组内部的值:

PRED[0] = 123;

如果你想拥有一个只读集合,你可以使用 ReadOnlyCollection 对象!如果您还希望该对象是常量,则可以使用 static-readonly 组合(不能使用常量,因为它是一个类),您将获得:

static readonly ReadOnlyCollection<int> PRED = new ReadOnlyCollection<int>(new[] {1, 2, 5, 6});

然后 PRED 将始终是 PRED,并且总是大小为 4,并且总是包含 1、2、5、6。

PRED = PRED; // Error (static readonly)
PRED = null; // Error (static readonly)
PRED[1] = 0; // Error (ReadOnlyCollection enforces readonly on the elements)

int i = PRED[1]; // Still works, since you aren't changing the collection.
于 2012-05-02T10:39:07.507 回答
2

final 由编译器检查,而不是在运行时检查。因此,如果赋值PRED[1] = 3无效,编译器会捕捉到它,代码甚至无法编译。

这个赋值是有效的,因为 final 意味着:你不能为变量重新赋值。这并不意味着:您不能改变变量引用的对象。

上面的赋值不会修改PRED. 它修改 的值PRED[1]。如果 PRED 是一个列表,则等价于PRED.set(1, 3). 这没关系。不正确的是PRED = new ArrayList<Integer>().

于 2012-05-02T10:42:02.010 回答
1

如果您希望一个值仅设置一次而不是在 java 中使用 final 在 c# 或 const 中使用 readonly,或者在某些情况下应该使用 seal,但如果您只想阅读 readonly 可能更好;)

于 2012-05-02T10:38:58.020 回答
1

正如您已经说过的,一个final变量只能设置一次。但是改变它的值是合法的。

于 2012-05-02T10:41:17.297 回答
1

Java final 关键字在Java 编程语言中在不同的条件下使用,具有不同的含义。例如:

  1. 要声明一个常量变量,
  2. 声明一个常量方法参数。

    1. 声明为 final 的变量必须在使用前进行初始化。不能为该变量分配新值,例如 (a = b)。但如果变量不是原始类型,则可以使用 set 方法或任何其他公共字段设置其属性。这意味着对象实例引用不能更改,但对象实例的属性可以更改,只要它们本身未声明为 final。

    2. 禁止在使用参数的方法中修改参数。

于 2012-05-02T11:03:06.323 回答