我正在写一些我上学几天的JAVA作业,但遇到了很奇怪的事情(嗯,至少对我来说是……)。
由于该问题与我的项目无关,所以我写了一些代码来表达我要询问的行为,因此请忽略以下代码中可能遇到的与该特定问题无关的任何问题。
考虑以下类别:

package test;

import java.util.ArrayList;
import java.util.List;

public class Car {

    List<Doors> doors;
    int numOfDoors;

    public Car(int numOfDoors) {
        this.numOfDoors=numOfDoors;
    }

    public void prepare() {
        run(doors);
    }

    public void run(List<Doors> listOfDoors) {
        listOfDoors=new ArrayList<Doors>(numOfDoors);
    }

    public List<Doors> getDoors() {
        return doors;
    }
}


还有这个:

package test;

import java.util.List;

public class TestDrive {

    public static void main(String[] args) {

        Car car=new Car(5);
        car.prepare();
        List<Doors> listOfDoors=car.getDoors();

        if (listOfDoors==null) {
            System.out.println("This is not the desired behaviour.");
        }
        else {
            System.out.println("This is the desired behaviour.");
        }
    }
}


我同意,这有点愚蠢,没有意义,但是再次-我写它只是为了满足我的好奇心。

现在,您可能已经猜到了,输出为“这不是所需的行为。”,这意味着,即使在“ run()”方法中为其分配了新对象,“门”字段仍保留一个空指针。所以我的问题是为什么?为什么它为空?
我的意思是,我知道创建局部变量(可能是原始变量,对象或对对象的引用)会导致在我们离开方法范围时将其失去正确的作用,但实际情况并非如此,因为是对新创建的对象(门)的实时引用,那么JAVA为什么会销毁它?

最佳答案

让我们逐步分析它。

Car car=new Car(5);
car.prepare();


您创建了一辆新车,并希望它在prepare之后有5个车门的列表。
现在让我们看一下prepare期间发生的情况。

public void prepare() {
    run(doors);
}

public void run(List<Doors> listOfDoors) {
    listOfDoors=new ArrayList<Doors>(numOfDoors);
}


new ArrayList被分配给局部变量listOfDoors
编写run(doors)时,没有传递指向变量doors的指针,例如在C上下文中可能会期望的那样。您正在将null(因为doors尚未初始化)传递给run方法。

运行开始时,我们有

List<Doors> listOfDoors = null;


这是在调用时传递null引用的结果。
然后,为该局部变量分配一个新列表,仅在方法终止时销毁。
如您所见,没有为doors分配任何内容,从而导致了意外的行为。

要解决此问题,请删除run方法并重写您的prepare方法。

public void prepare() {
    doors = new ArrayList<Doors>(numOfDoors);
}


这样,您应该会获得预期的行为。

08-04 20:40