如果我在Synapse
是抽象类型的类中有以下语句:
private final List<Synapse> synapses;
final
允许我仍然能够更改Synapse
中List
对象的状态,但是阻止我将新的Synapse
对象添加到列表中吗?如果我错了,请您解释一下final
在做什么以及何时应该使用关键字final
。
否,final关键字不会使列表或其内容不变。如果您想要一个不可变的列表,则应使用:
List<Synapse> unmodifiableList = Collections.unmodifiableList(synapses);
final关键字的作用是防止您为'synapses'变量分配新值。即,您不能写:
final List<Synapse> synapses = createList();
synapses = createNewList();
但是您可以写:
List<Synapse> synapses = createList();
synapses = createNewList();
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)