【发布时间】:2012-10-26 00:47:42
【问题描述】:
如果我在 Synapse 是抽象类型的类中有以下语句:
private final List<Synapse> synapses;
final 是否允许我仍然能够更改List 中Synapse 对象的状态,但阻止我将新的Synapse 对象添加到列表中?如果我错了,请您解释一下final 正在做什么以及何时应该使用关键字final。
【问题讨论】:
如果我在 Synapse 是抽象类型的类中有以下语句:
private final List<Synapse> synapses;
final 是否允许我仍然能够更改List 中Synapse 对象的状态,但阻止我将新的Synapse 对象添加到列表中?如果我错了,请您解释一下final 正在做什么以及何时应该使用关键字final。
【问题讨论】:
不,final 关键字不会使列表或其内容不可变。如果你想要一个不可变的列表,你应该使用:
List<Synapse> unmodifiableList = Collections.unmodifiableList(synapses);
final 关键字的作用是阻止您为“突触”变量分配新值。即,你不能写:
final List<Synapse> synapses = createList();
synapses = createNewList();
不过,你可以写:
List<Synapse> synapses = createList();
synapses = createNewList();
本质上,您仍然可以更改、添加和删除列表的内容,但不能创建分配给变量突触的新列表。
【讨论】:
unmodifiableList 这样的构造中无法添加、删除或替换任何内容,但列表中的元素仍然可以更改其状态(如果它们是可变的)。列表声明或构造都无法阻止这种情况。
final List<Synapse> synapses = createList();,然后再做synapses.add(newSynapse())?那么这意味着synapses 不能指向除此列表之外的任何其他内容,对吗?
synapses 是像 ArrayList 这样的可变对象。
final 阻止您在分配一次后重新分配 synapses - 您仍然可以像往常一样添加/删除元素。您可以阅读有关final 关键字here 的更多信息。
【讨论】:
您仍然可以更改、添加和删除列表的内容,但不能创建分配给变量的新列表。
【讨论】:
Java 语言规范writes:
变量可以声明为final。最终变量只能分配一次。声明一个变量 final 可以作为有用的文档,说明它的值不会改变,并且可以帮助避免编程错误。
如果最终变量被分配给它是一个编译时错误,除非它在分配之前被明确地未分配(第 16 节)。
一个空白的final是一个final变量,它的声明缺少一个初始化器。
一旦分配了最终变量,它总是包含相同的值。如果最终变量持有对对象的引用,则对象的状态可能会通过对对象的操作而改变,但变量将始终引用同一个对象。
因此,如果您希望强制通过变量到达的状态不变,您必须声明变量final,使用不可修改的列表(例如Collections.unmodifiableList),并创建Synapse 对象不可变。
【讨论】:
最终实现意味着对象引用一旦启动,引用本身就永远不能改变,但内容当然可以。它根本不违反规则。您只指定了一条关于参考更改的规则,该规则正在相应地起作用。如果您希望这些值也永远不会改变,您应该选择不可变列表,即
List<String> items = Collections.unmodifiableList(Arrays.asList("a", "b", "c"));
请参阅以下相关问题。
【讨论】:
上面的答案在理论上解释了所有在这里你可以找到运行代码并查看实际差异,建议使用本地变量
package exp_test;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class testList {
final static List<String> synapses = new ArrayList();;
public static void main(String[] args) {
synapses.add("A");
System.out.println(synapses);
//
System.out.println(finalLisTest(synapses));
//
System.out.println(synapses);
//
synapses.add("B");
List<String> unmodifiableList = Collections.unmodifiableList(synapses);
System.out.println(finalLisTest(unmodifiableList));
//
System.out.println(unmodifiableList);
}
private static List finalLisTest(List<String> list) {
list.remove(0);
return null;
}
}
结果:
[A]
null
[]
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableList.remove(Collections.java:1317)
at exp_test.testList.finalLisTest(testList.java:29)
at exp_test.testList.main(testList.java:22)
【讨论】: