子类没有看到父变量

时间:2013-03-05 15:06:07

标签: java nullpointerexception subtype

public class Program {

    public static void main(String[] args) {
        Listener listener = new Listener();
        listener.listen();
    }
}

public class Listener {

    ServerQuery query;
    int test = 1;

    public listen() {
        query = new ServerQuery();
        Channel ch = new Channel();
        ch.dupa();
    }
}

public class Channel extends Listener {

    public dupa() {
        System.out.print(test); // works fine 
        super.query.doSomething(); // null pointer
        query.doSomething(); //  null pointer
    }
}

我无法在“Channel”类中访问变量“query”。 谁能解释我为什么?

5 个答案:

答案 0 :(得分:3)

你误解了超类型和子类型的概念。

直接问题是您需要在使用之前实例化查询变量。

在致电ch.listen()之前致电dupa或在dupa内拨打电话。

这里的主要问题是理解子类型 - 超类型关系。

您的Channel对象没有Listener实例的引用,它只是它的一个子类型。 因此,如果您需要访问超类型的字段,例如访问类的字段 - 您必须在使用它之前对其进行实例化。

在Listener中创建Channel对象没有逻辑。 Channel是一个Listener,所以你可以改为创建它。

我建议您详细了解here或其他任何地方。

对于您的代码,您可以使用:

public class Program {

    public static void main(String[] args) {
        Channel ch = new Channel();
        ch.listen(); // will instantiate ch.query
        ch.dupa(); 
    }
}
public class Listener {

    ServerQuery query;
    int test = 1;

    public listen() {
        query = new ServerQuery();
    }
}

public class Channel extends Listener {

    public dupa() {
        System.out.print(test);
        super.query.doSomething();
        query.doSomething();
    }
}

答案 1 :(得分:1)

编辑以获得更多解释:

超类中的变量必须定义为protected,以允许由子类实现。如果您未声明范围,则该字段将声明为package-private。

有关范围的更多信息,请参阅官方tutorial

您的代码的另一个注意事项:您的query变量未在此处实例化,因此如果您不首先调用方法listen(),它将始终返回NPE。

答案 2 :(得分:0)

我通过制作类似的东西来解决它:

public class Channel extends Listener {
     ServerQuery queryInstance;
     Listener(ServerQuery listener){
         queryInstance = listener;
     }
     public dupa() {

        System.out.print(test); // works fine 
        super.query.doSomething(); // null pointer
        query.doSomething(); //  null pointer
    }
}

答案 3 :(得分:0)

Channel ch = new Channel();未初始化query

您正在dupa()对象上调用Channel而未调用listen()来初始化query引用。

答案 4 :(得分:0)

您正在使用两个Listener对象。一个在Channel类中(比如Channel.super())和一个在你的main方法中。

我认为令人困惑的是,您假设您的Channel对象将使用您在main方法中声明的相同侦听器类。

简而言之,答案是查询变量未初始化。

所以主要是你有一个设计问题。你可以通过几种方式解决它。 一个简单的方法是将查询传递给你的dupa方法并使用该查询对象。