我有一个关于java中的final变量的问题,我写了一个简短的代码来演示这个问题。 java8 的语言规范指出:
Once a final variable has been assigned, it always contains the same value. If a final variable holds a reference to an object, then the state of the object may be changed by operations on the object, but the variable will always refer to the same object. Language Specification
为了进一步调查,我在一个小示例代码中尝试了三件事。我尝试的第一件事是创建 Integer
类型的对象并为其分配非最终引用。然后我也给它分配了一个最终引用。在第二个实验中,我对原始 int
做了同样的事情。 。这两个实验都导致相同的结果,编译器不允许我增加最终引用,但允许增加非最终引用,并且在输出中仅非最终变量增加。
在我的第三个实验中,我使用了一个列表,并再次分配了对该列表的非最终引用和最终引用。这里我被允许使用最终和非最终引用来调用 add()
并且在两个引用文献中,尺寸都已更新。
我的测试代码:
public void testFunction () {
Integer nonFinalInteger = 4;
final Integer finalInteger = nonFinalInteger;
nonFinalInteger++;
//Compiler shows error
//finalInteger++;
System.out.println("nonFinal Integer: " + nonFinalInteger);
System.out.println("final Integer: " + finalInteger + "\n");
int nonFinalInt = 4;
final int finalInt = nonFinalInt;
nonFinalInt++;
//Compiler shows error
//finalInt++;
System.out.println("nonFinal primitive int: " + nonFinalInt);
System.out.println("final primitive int: " + finalInt + "\n");
List<String> nonFinalVar = new ArrayList<String>();
final List<String> finalVar = nonFinalVar;
finalVar.add("Hello");
//Compiler does not show error
nonFinalVar.add("World");
System.out.println("nonFinal List Size: " + nonFinalVar.size());
System.out.println("final List Size: " + finalVar.size() + "\n");
}
输出:
nonFinal Integer: 5
final Integer: 4
nonFinal primitive int: 5
final primitive int: 4
nonFinal List Size: 2
final List Size: 2
我现在的问题是:有没有一种方法可以保护对象的状态而不必更改其类的代码?假设我们停留在有一个 List
的上下文中,不允许您在其中添加或删除元素。是否可以以某种方式标记列表,以便编译器显示错误(或至少某种警告)?
编辑:
我似乎在示例中使用数组造成了一些困惑。我的问题应该涉及任何类型的对象,因此我没有在问题或标签中放入列表。我的意思不是告诉编译器禁止更新引用,我只是想知道是否有一种方法隐式告诉编译器拒绝调用可能改变对象状态的函数。
目前,包装类的想法似乎是最吸引人的,尽管它对我来说仍然缺少一件事:它不会阻止我或其他人完全改变对象的状态。最终变量总是具有我在这里寻找的“请勿触摸”特征。
最佳答案
这是一个令人困惑的问题。我会尝试解释一下:
当你将一个变量声明为final时,结果是他的值可以以两种不同的形式赋值:
- 在定义最终变量的同一行中分配值。
- 如果最终变量
B
是一个类的属性A
,然后B
的值可以在A
的构造函数中赋值类。
但重要的是,当我说分配一个值时,我指的是以下形式的分配:
final ArrayList<Integet> myArray = new ArrayList<Integer>(Arrays.asList(1,2,3));
现在变量 myArray
始终指向该数组列表,并且不能再次以相同的形式分配:
myArray = new ArrayList<Integer>(Arrays.asList(4,5,6));
会抛出错误。
但话虽这么说,您仍然可以在该变量中进行操作。例如,如您所见,您可以添加值: myArray.add(4);
.
简而言之:当您标记变量 C
时最后你就是这么做的,说 C
不能分配给另一个对象,但该目标对象可以随时更改其状态。
关于java - 如何将对象的变量设为final?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46755736/