17

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

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,这使得该变量保持不变。

4

7 回答 7

37

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

它不能被重新分配。但是您可以更改它的内部结构(如果它最初是可变的,它是可变的)。所以这有效:

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

但这不是:

  final A ob = new A();
  ob = new A();
于 2012-06-29T10:26:18.607 回答
12

如果您指示任何变量是最终的,则意味着您不希望它包含在内存中的值发生变化。在原始类型的情况下,由变量表示的值是实际值。在对象类型的情况下,内存中的值是对对象的引用,而不是实际对象。

例如,您有:

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关键字在这方面几乎是一致的。

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

于 2012-06-29T11:26:03.440 回答
4

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

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

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

于 2012-06-29T10:28:19.833 回答
3

如果一个对象是final您可以像往常一样调用任何进行内部更改的方法,但您不能重新分配引用以指向不同的对象。尝试这样做:

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

并注意代码不会编译。

将此视为一个恒定的参考。

于 2012-06-29T10:27:47.180 回答
2

好吧,在对象的情况下,引用的值是对象的地址。所以ob的值将是最终创建的对象的地址new A();,您将无法更改其值。意思是,您不能为此引用分配新对象。

你不能这样写。

final A ob = new A();

ob= new A(); // not allowed
于 2012-06-29T10:28:31.900 回答
1

在java中,与C++相反,所有对象都是指针,所以一个final对象是可以改变的,它只是不能指向任何新的地方,也就是说,你不能把它放在赋值运算符的左边。

于 2012-06-29T10:27:38.927 回答
1

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

所以 :

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

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

但:

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

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

于 2012-06-29T11:08:16.000 回答