成员未在子类中初始化

pen*_*001 1 java

//src/com/test/animal/Animal.java
package com.test.animal;

public class Animal
{
    Animal()
    {
        init();
    }

    public void init()
    {
        System.out.println("parent init()");
    }
}

//src/com/test/animal/Dog.java 
package com.test.animal;

public class Dog extends Animal
{
    String name = null;

    Dog()
    {
        super();
    }

    public void init()
    {
        System.out.println("child init()");
        super.init();
        name = new String("dog");
        System.out.println("name: "+name);
    }

    public static void main(String[] args)
    {
        Dog d = new Dog();
        System.out.println("name: "+d.name);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出是:

child init()
parent init()
name: dog
name: null
Run Code Online (Sandbox Code Playgroud)

似乎调用了子中的init(),但是没有保存NAME值!为什么?如果我将NAME移动到父级,那就没关系.然而,保留在孩子身上更合理,因为它是特定于狗的.

另外,我可以在child的构造函数中显式调用init()来解决这个问题.这不是那么好.

Jes*_*per 6

执行的顺序如下:

  1. Dog构造函数被调用.
  2. 它调用Animal构造函数.
  3. Animal构造函数调用的init方法.因为它被覆盖Dog,所以Dog调用版本.
  4. Dog.init你设置name"dog".
  5. Dog.init方法返回.
  6. 现在,Dog初始化成员变量.这将设置namenull.

结果:name将是null.

一个很好的例子,说明为什么你不应该调用可以从构造函数中重写的方法 - 因为它会导致像这样的惊喜.

旁注:永远不要这样做:

// Unnecessarily creating a new String object
name = new String("dog");
Run Code Online (Sandbox Code Playgroud)

只需这样做:

name = "Dog";
Run Code Online (Sandbox Code Playgroud)

永远不必String从字符串文字中显式创建新对象.