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”。 谁能解释我为什么?
答案 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方法并使用该查询对象。