Java第二次实例化最终对象

时间:2014-05-17 06:48:39

标签: java object final

这无法实现,您无法实例化已经实例化的最终对象:

private void myMethod(){
    final Object object = null;

    object = new Object();
}

Eclipse会给出一条错误消息:

无法分配最终的局部变量对象。它必须为空白且不使用复合赋值

但是,如果将此对象传递给另一个方法:

private void _myMethod(Object object){
    object = new Object();
}

这可以实现!

最终形式:

private void myMethod(){
    final Object object = null;

    _myMethod(object);
}

private void _myMethod(Object object){
    object = new Object();
}

有人能解释一下吗? Java的运作方式令人困惑。

3 个答案:

答案 0 :(得分:4)

首先,变量名称很难解释,所以:

private void myMethod(){
    final Object finalObject = null;

    _myMethod(finalObject);
}

private void _myMethod(Object methodObject){
    methodObject = new Object();
}

Java通过引用值传递对象。将参数传递给方法意味着methodObject保存了对finalObject的引用副本(但不包含对象的副本)。现在,方法的主体不会更改或重新分配finalObject对象 - 它只是通过更改传递给方法的引用值来重新分配methodObject

请参阅this answer - 我想它会更清楚。

答案 1 :(得分:0)

你必须在这里理解局部变量的概念。

见下图

enter image description here

所有局部变量(基元或对象)都将驻留在其方法堆栈中。

如果它是一个对象,则只引用保留在堆栈中,并且对象驻留在堆中。

并且每个局部变量都放在方法堆栈中。

所以此处2 local variables会在stack中为每个方法添加一个。

其中一个是final而另一个不是。

所以你可以reassign第二个而不是第一个。

在你的情况下,

 final Object object = null

存储在myMethod堆栈中。并在此声明为最终版,

所以在这种方法中你不能再分配它。

然而在里面

private void _myMethod(Object object){
    object = new Object(); //Error here
}

Object object声明生成相同的变量以在_myMethod堆栈位置内获取空间。

所以这里not final因此它可以是reassigned

如果你在这个方法中使用final,那么我的图像中的第二张图片将在其方法堆栈中包含最终Object变量,然后它将不允许第二次分配。

答案 2 :(得分:0)

在java变量中passed by value。对于Objects,它是传递的引用的副本。

private void myMethod(){
    final Object object = null;

    _myMethod(object);
}

private void _myMethod(Object newObject){
    newObject= new Object();
}

因此newObject是一个新的引用,如果类型为Object,指向object所指向的同一个Object。请注意,对象引用是最终的,而不是副本,即newObject 。所以你所做的是第二部分完全有效。

public class Test{  
   final Object object = null;

private void myMethod(){    
    _myMethod(object);
}

 private void _myMethod(Object newObject){
        object = new Object(); //Error here
    }
}

以上将失败,因为对象引用是最终的。