在java中将对象声明为final

有人可以澄清下面代码的重要性。

class A { int i = 10; public void setI(int b) { i = b; } public int getI() { return i; } } class Test { public static void main(String args[]) throws Throwable { final A ob = new A(); ob.setI(10); System.out.println(ob.getI()); } } 

对象A被声明为final,但我可以更改此对象的实例变量的值,并还可以检索更新的值。 那么将对象声明为final是什么意义。 我知道将原始数据类型声明为final,这使得该变量不变。

ob将无法引用任何其他对象: final关键字 。

它无法重新分配。 但你可以改变它的内部(它是可变的,如果它是最初的)。 这样可行:

  final A ob = new A(); ob.setI(6) 

但这不是:

  final A ob = new A(); ob = new A(); 

如果您指定任何变量为final,则表示您不希望更改它在内存中包含的值。 在原始类型的情况下,由变量表示的值是实际值。 对于对象类型,内存中的值是对对象的引用,而不是对实际对象的引用。

例如,您有:

 final int x = 7; final Object y = new Object(); 

您可以通过这种方式考虑在内存中表示的数据:

 +----------+----------+ | block | value | +----------+----------+ | 1001 | 7 | | 1002 | 2110 | +----------+----------+ 

为了便于讨论,让我们省略Java如何实际管理内存的细节(因为我对它也不太了解)。 因此,在上面的示例中,块1001由变量x表示,而1002由y表示。 两者都是最终变量,这意味着它们所代表的值不能改变。 在x的情况下,它是7,这是实际值,但是在y的情况下,2110只是对另一个存储器位置的引用。 两者都不能改变,但原始类型变量成为常量的原因是它们代表实际值。 但实际上,你也可以对对象类型变量说同样的,只是它们所代表的常量是引用。 因此, 最终关键字在这方面非常一致。

因此,对于最终变量,如果它们是原始类型,它们将始终表示您设置它们的任何特定值。 如果它们是对象/引用类型,它们将不断指向您指向它们的任何对象(无论对象的可变性如何)。

如果对象是final对象,则可以像往常一样调用任何进行内部更改的方法,但不能将引用重新指定为指向其他对象。 尝试这样做:

 final A ob = new A(); ob = new A(); 

并注意代码将无法编译。

将此视为一个不变的参考。

这意味着以下是不可能的:

 final A ob = new A(); ob = new A(); // This is not possible 

变量ob也将引用首次分配给它的A类实例。 这就是final关键字在这种情况下的含义。 它确实意味着您可以修改ob的属性,因为它是像A任何其他实例一样的普通对象。

好吧,在对象的情况下,引用的值是对象的地址。 所以ob的值将是new A();创建的对象的地址new A(); 这将是最终的,你将无法改变它的价值。 意思是,你不能为这个引用分配一个新对象。

你不能这样写。

 final A ob = new A(); ob= new A(); // not allowed 

在java中,与C ++相反,所有对象都是指针,因此final对象可以更改,它只是不能指向任何新的,也就是说,您不能将它放在赋值运算符的左侧。

java中不会有任何常量(最终)对象。 对象在堆内存区域中创建。 我们可以随时修改对象。
在java中只有常量(最终)引用: – 表示您不能修改引用并将其重新分配给任何其他对象,因为它是常量,并且在最终引用之外只引用一个被分配的对象宣言。

因此:

  final A objectA = new A(); objectA.setI(6); 

是有效的,因为我们只更改对象内容,而不是引用。

但:

  final A objectA = new A(); objectA = new A(); 

无效是因为您正在尝试修改引用。