【问题标题】:Don’t call subclass methods from a superclass constructor不要从超类构造函数中调用子类方法
【发布时间】:2010-06-18 16:44:33
【问题描述】:

考虑下面的代码

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package example0;

/**
 *
 * @author yccheok
 */
public class Main {

    static class A {
        private final String var;

        public A() {
            var = getVar();
            // Null Pointer Exception.
            System.out.println("var string length is " + var.length());
        }

        public String getVar() {
            return "String from A";
        }
    }

    static class B extends A {
        private final String bString;

        // Before B ever constructed, A constructor will be called.
        // A is invoking a overriden getVar, which is trying to return
        // an initialized bString.
        public B() {                
            bString = "String from B";
        }

        @Override
        public String getVar() {
            return bString;
        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        B b = new B();
    }

}

目前,在我看来,有两种方法可以避免此类问题。

要么让 A 类成为最终类。

static final class A {
    private final String var;

    public A() {
        var = getVar();
        // Null Pointer Exception.
        System.out.println("var string length is " + var.length());
    }

    public String getVar() {
        return "String from A";
    }
}

或者

使 getVar 方法成为最终方法

static class A {
    private final String var;

    public A() {
        var = getVar();
        // Null Pointer Exception.
        System.out.println("var string length is " + var.length());
    }

    public final String getVar() {
        return "String from A";
    }
}

作者试图提出防止上述问题的方法。但是,由于需要遵循一些规则,因此该解决方案似乎很麻烦。

http://benpryor.com/blog/2008/01/02/dont-call-subclass-methods-from-a-superclass-constructor/

除了 make final 和作者建议的方法之外,还有其他方法可以防止上述问题(不要从超类构造函数调用子类方法)发生吗?

【问题讨论】:

  • 到底是什么问题?
  • em,有什么问题?
  • 所有这些行为看起来都完全正确。是的,有一个空指针异常,但这仅仅是因为您有一个返回空值的方法。这是相当合法的。你想要什么样的行为?如果 B 还没有定义一个变量,你想依靠 A 变量吗? B 可以自己做。
  • 你想用这段代码实现什么?如果我们不知道您到底想做什么,就很难提出任何建议。
  • 以后请不要在代码中包含问题或错误消息,而是在代码之外。

标签: java


【解决方案1】:

使 getVar 方法最终化

这绝对是你需要做的。

如果您使用方法的功能来初始化对象,则不应让子类破坏该方法。

回答您的问题,其他方法是在A 中将getVar 设为私有。

查看您的代码的简化版本:

// A.java
class A {
    private final String var;
    public A(){
        var = getVar();
        var.length();
    }
    private String getVar(){
        return "This is the value";
    }
}
class B extends A {
    private final String other;
    public B(){
        other = "Other string";
    }
    public String getVar(){
        return other;
    }
}
class Main{
    public static void main( String [] args ) {
        new B();
    }
}

顺便说一句,你为什么把这些作为静态嵌套类,只是为了制造混乱?

【讨论】:

  • >> 静态嵌套类 抱歉。它们不应该是静态的。我只想从静态 main 快速调用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-05
  • 2013-10-20
相关资源
最近更新 更多