使用final方法初始化实例变量

时间:2010-01-28 12:14:06

标签: java

来自Sun docs

  

通常,你会把代码放到   初始化一个实例变量   建设者。
有两个   使用构造函数的替代方法   初始化实例变量:   初始化块和最终方法。

我可以理解初始化块的使用。任何人都可以解释使用最终方法进行var初始化吗?非最终的公共制定者可以完成这项工作。为什么不直接使用它们?

3 个答案:

答案 0 :(得分:21)

优点已在您链接到的相同Sun教程中进行了描述:

  

无法在子类中重写最终方法。这将在有关接口和继承的课程中讨论。

     

如果子类可能想要重用初始化方法,这将特别有用。该方法是最终的,因为在实例初始化期间调用非final方法可能会导致问题。约书亚布洛赫在Effective Java(item 17 Design and document for inheritance)中更详细地描述了这一点。

非final方法在初始化时很危险的原因是因为超类的实例初始化在初始化子类之前执行。因此,如果非最终方法在子类中被覆盖并且在超类的初始化期间执行,则它可能正在访问子类的未初始化字段,从而产生错误结果。

一般规则是(引用Effective Java):构造函数不得直接或间接调用可覆盖的方法。

答案 1 :(得分:3)

它在参考教程的同一页面上进行了解释。原因是up-subclass可以覆盖非final方法。这是一个例子:

class Whatever {
    private List<String> myVar = initializeInstanceVariable();

    protected List<String> initializeInstanceVariable() {
        return new ArrayList<String>();
    }
}

class Whoever extends Whatever {

    @Override
    protected List<String> initializeInstanceVariable() {
       return Collections.unmodifiableList(super.initializeInstanceVariable());
    }

}

因此,如果您创建了Whoever,myVar将变为不可修改; - )

答案 2 :(得分:3)

其他例子

来自alykhantejani.github.io

我将其编辑并简化了它。

<强> Duck.java

public class Duck {

    String sound = "quack";
    protected String speech;

    public Duck() {
        initSpeech();
    }

    protected void initSpeech() {
        speech = "sound = " + sound;
    }

    public void speak() {
        System.out.println(speech);
    }

    protected String getSound() {
        return sound;
    }
}

<强> SqueakyDuck

public class SqueakyDuck extends Duck {

    String squeakSound = "squeak";

    public SqueakyDuck() {
        super();
    }

    @Override
    protected void initSpeech() {
        speech = "sound = " + squeakSound;
    }

    @Override
    protected String getSound() {
        return squeakSound;
    }
}

<强> Main.java

public class Main {

    public static void main(String[] args){
        Duck squeaky = new SqueakyDuck();
        squeaky.speak();
        System.out.println(squeaky.getSound());
    }
}

<强>输出:

sound = null
squeak

我的例子

<强> Superclass.java

public class Superclass {

    protected int x = m();

    protected int m() {
        return 8;
    }

}

<强> Subclass.java

public class Subclass extends Superclass {

    private int y = 7;

    @Override
    protected int m() {
        return y;
    }

}

<强> Main.java

public class Main {
    public static void main(String[] args) {
        Superclass s = new Subclass();
        System.out.println(s.x);
    }
}

<强>输出:

0

执行顺序:

  • main
  • 来自m的{​​li> Subclassy此时未初始化0int的默认值)
  • 构造函数Superclass
  • 构造函数Subclass
相关问题