繁体   English   中英

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

[英]Using final methods to initialize an instance variable

来自Sun的文档

通常,您可以使用代码在构造函数中初始化实例变量。
使用构造函数初始化实例变量有两种选择:初始化块和最终方法。

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

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

不能在子类中重写最终方法。 这在接口和继承的课程中讨论。

如果子类可能希望重用初始化方法,这尤其有用。 该方法是最终的,因为在实例初始化期间调用非final方法可能会导致问题。 Joshua Bloch在Effective Java(第17项设计和继承文档)中更详细地描述了这一点。

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

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

它在参考教程的同一页面上进行了解释。 原因是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将变得无法修改;-)

其他例子

来自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来自Subclass (此时y 未初始化0int的默认值)
  • 构造函数Superclass
  • 构造函数Subclass

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM