1

我一直在学习 Java 认证 Bates 和 Sierra 书,对第 2 章的构造函数解释感到困惑:

public class Animal {
    String name;

    Animal(String name) {
        super();

        {System.out.println("Hello");} //I put this in myself

        this.name = name;
    }

    Animal() {
        this(makeRandomName());
    }


    static String makeRandomName() {
        int x = (int) (Math.random() * 5);
        String name = new String[] {"Fluffy", "Fido",
        "Rover", "Spike",
        "Gigi"}[x];
        return name;
    }

    public static void main (String [] args) {
        Animal a = new Animal();
        System.out.println(a.name);
        Animal b = new Animal("Zeus");
        System.out.println(b.name);
    }
}

以下内容来自 Bates 和 Sierra 书中:

请注意,makeRandomName() 方法被标记为静态!这是因为在超级构造函数运行之前,您不能调用实例(换句话说,非静态)方法(或访问实例变量)。而且由于超级构造函数将从第 3 行的构造函数调用,而不是从第 7 行的构造函数调用,所以第 8 行只能使用静态方法来生成名称。

我做了一个实验,我在重载的构造函数中插入了一个超级调用,我的结果是:

 Hello 
 Rover
 Hello
 Zeus

现在从这些结果来看,似乎重载的构造函数和超级构造函数在静态方法之前执行,因为 Hello 在 Zeus 和 Rover 之前打印。那么,为什么需要静态变量呢?

我错过了什么?

4

3 回答 3

3

该方法在之前makeRandomName()调用super。您的打印语句仅表明您正在使用它在其他构造函数执行后产生的值。要查看差异,请将打印语句直接插入makeRandomName().

于 2013-10-03T01:32:14.947 回答
1

似乎重载的构造函数和超级构造函数在静态方法之前执行,因为 Hello 在 Zeus 和 Rover 之前打印。

您的代码中没有任何内容可以证明这一点。将 trace 放入静态方法中,您将看到真正的执行顺序。

那么,为什么需要静态变量呢?

没有。您发布的代码中没有静态变量。有一个静态方法。尝试使它成为非静态的,你会从错误中看到它不能从内部调用,this()除非它是静态的。

于 2013-10-03T01:56:28.840 回答
1

构造函数中的super()调用不会改变任何东西。无论如何,它都会被编译器隐式添加。

至于执行

Animal a = new Animal();

调用空构造函数,它调用

this(makeRandomName());

makeRandomName()被执行并返回 aString用于调用接受 a 的 1-arg 构造函数String"Hello"打印并name分配字段。构造函数返回。随机名称被打印出来。

然后调用 1-arg 构造函数

Animal b = new Animal("Zeus");

打印"Hello",设置字段,返回。然后是main指纹"Zeus"


那么,为什么需要静态变量呢?

如果您已从static方法中删除makeRandomName(),则以下内容将无法编译

Main() {
    this(makeRandomName());
}

该对象尚未初始化,因此您不能在其上调用方法。

于 2013-10-03T01:34:26.980 回答