Java 将侦听器分配给类时出现问题
我的问题在于莫名其妙地不能听我的课 该软件是一个基于java swing的桌面应用程序,JFrame的子类MainFrame正在侦听多个对话框。所有对话框窗口都是my PDialog类的子类,该类包含与侦听器相关的变量和函数。这是PDialog类的外观:Java 将侦听器分配给类时出现问题,java,swing,inheritance,nullpointerexception,listener,Java,Swing,Inheritance,Nullpointerexception,Listener,我的问题在于莫名其妙地不能听我的课 该软件是一个基于java swing的桌面应用程序,JFrame的子类MainFrame正在侦听多个对话框。所有对话框窗口都是my PDialog类的子类,该类包含与侦听器相关的变量和函数。这是PDialog类的外观: public class PDialog extends JDialog { private MainFrameChildrenListener listener; // Function that assigns its paramete
public class PDialog extends JDialog {
private MainFrameChildrenListener listener;
// Function that assigns its parameter to local listener value "listener setter"
public void addMainFrameChildrenListener(MainFrameChildrenListener listener) {
this.listener = listener;
}
public void removeMainFrameChildrenListener() {
this.listener = null;
}
public void firePDialogEvent(MainFrameChildrenEventObject event) {
this.listener.dialogEventOccured(event);
}
// This method was useful when I tried to debug with System.out.println() method
public String retrieveListenerInformation(){
if(listener == null){
return "No listener loaded";
}
return this.listener.toString();
}
}
Material dialog: No listener loaded
Customer dialog: view.MainFrame[-deleted the .toString() rubbish to keep things short-]
Order dialog: view.MainFrame[-deleted the .toString() rubbish to keep things short-]
Product dialog: view.MainFrame[-deleted the .toString() rubbish to keep things short-]
因此,我创建了3个对话框,使用它们作为PDialog的子类继承的函数成功地侦听它们。MainFrame类实现MainFrameChildrenListener侦听器对象,并将其作为侦听器传递给其构造函数中的对话框:
public class MainFrame extends JFrame implements MainFrameChildrenListener {
private PDialogCustomer dialogCustomer = new PDialogCustomer();
private PDialogOrder dialogOrder = new PDialogOrder();
private PDialogProduct dialogProduct = new PDialogProduct();
private PDialogMaterial dialogMaterial = new PDialogMaterial();
public MainFrame(){
dialogMaterial.addMainFrameChildrenListener(this);
dialogCustomer.addMainFrameChildrenListener(this);
dialogOrder.addMainFrameChildrenListener(this);
dialogProduct.addMainFrameChildrenListener(this);
System.out.println("Material dialog: " + dialogMaterial.retrieveListenerInformation());
System.out.println("Customer dialog: " + dialogCustomer.retrieveListenerInformation());
System.out.println("Order dialog: " + dialogOrder.retrieveListenerInformation());
System.out.println("Product dialog: " + dialogProduct.retrieveListenerInformation());
}
令人惊讶的是,在应用程序启动后,控制台输出PDialog.retrieveListenerInformation()指令,它看起来是这样的:
public class PDialog extends JDialog {
private MainFrameChildrenListener listener;
// Function that assigns its parameter to local listener value "listener setter"
public void addMainFrameChildrenListener(MainFrameChildrenListener listener) {
this.listener = listener;
}
public void removeMainFrameChildrenListener() {
this.listener = null;
}
public void firePDialogEvent(MainFrameChildrenEventObject event) {
this.listener.dialogEventOccured(event);
}
// This method was useful when I tried to debug with System.out.println() method
public String retrieveListenerInformation(){
if(listener == null){
return "No listener loaded";
}
return this.listener.toString();
}
}
Material dialog: No listener loaded
Customer dialog: view.MainFrame[-deleted the .toString() rubbish to keep things short-]
Order dialog: view.MainFrame[-deleted the .toString() rubbish to keep things short-]
Product dialog: view.MainFrame[-deleted the .toString() rubbish to keep things short-]
如果我试图触发侦听器事件,则PDialog.FireDialogEvent()方法会出现空指针异常。
我曾试图通过其构造函数将侦听器传递给PDialogMaterial类,我甚至试图仅在PDialogMaterial类中创建新方法来传递侦听器,但没有成功。我能够使事情正常运行的唯一方法是创建新的MainFrameChildrenListener变量,该变量声明为public(eek!),并从大型机构造函数直接访问它,如下所示:
public class PDialogMaterial extends PDialog{
public MainFrameChildrenListener testListener;
}
public class MainFrame extends JFrame implements MainFrameChildrenListener{
public MainFrame(){
dialogMaterial.testListener = this;
dialogCustomer.addMainFrameChildrenListener(this);
dialogOrder.addMainFrameChildrenListener(this);
dialogProduct.addMainFrameChildrenListener(this);
}
}
有没有解释为什么四个类中有三个继承了相同的侦听器处理方法,它们的行为与第四个类不同?我会错过什么
意见跟进:
PDialogMaterial(不工作)的完整代码:
这个令人不快的类的问题是它重新声明了
private MainFrameChildrenListener listener;
场。因此有两个私有字段,一个在超类中,一个在子类中,名称相同。当您在子类的方法中时,子类中的一个会覆盖超类中的一个,但对于在超类中定义的方法不可见。删除子类中的listener字段,它应该可以工作。有问题的类中的问题是它重新声明了
private MainFrameChildrenListener listener;
场。因此有两个私有字段,一个在超类中,一个在子类中,名称相同。当您在子类的方法中时,子类中的一个会覆盖超类中的一个,但对于在超类中定义的方法不可见。删除子类中的listener字段,它应该可以工作。如前所述,在不工作的listener中,您正在隐藏listener字段并重新声明setter
为了说明这个问题,我建立了一个小例子:
import java.util.Arrays;
public class HiddenField {
static abstract class Base {
String field = "BASE";
// sets the base's field
void setField(String set) {
this.field = set;
}
// ensures not to be overridden and returns the base's field.
final String getField() {
return this.field;
}
// access the field by getter (ensured to be base) and field 'field'
@Override
public String toString() {
return this.getClass().getSimpleName() + ": get()->" + getField() + " vs. field->" + field;
}
}
static class ProperExtension extends Base {
/* no need to override the base's field */
}
static class HidingExtension extends Base {
// this field isn't related to the one in Base, but has the same name!
String field = "HIDING";
// the setter is overridden (exact copy!) but because of the same-named
// field in this extending class, it sets this class's field and not the
// one in the base-class!
@Override
void setField(String set) {
this.field = set;
}
// copied the toString from above - here it is accessing the
// base-class's field via getter and this class's field directly.
@Override
public String toString() {
return this.getClass().getSimpleName() + ": get()->" + getField() + " vs. field->" + field;
}
}
public static void main(String[] args) {
// build both types of extending classes and invoke their setters
Arrays.asList(new ProperExtension(), new HidingExtension()).forEach(obj -> {
System.out.println("before ~> " + obj);
obj.setField("SET");
System.out.println("after ~> " + obj + "\n");
});
}
}
如前所述,在不工作的侦听器中,您正在隐藏侦听器字段并重新声明setter
为了说明这个问题,我建立了一个小例子:
import java.util.Arrays;
public class HiddenField {
static abstract class Base {
String field = "BASE";
// sets the base's field
void setField(String set) {
this.field = set;
}
// ensures not to be overridden and returns the base's field.
final String getField() {
return this.field;
}
// access the field by getter (ensured to be base) and field 'field'
@Override
public String toString() {
return this.getClass().getSimpleName() + ": get()->" + getField() + " vs. field->" + field;
}
}
static class ProperExtension extends Base {
/* no need to override the base's field */
}
static class HidingExtension extends Base {
// this field isn't related to the one in Base, but has the same name!
String field = "HIDING";
// the setter is overridden (exact copy!) but because of the same-named
// field in this extending class, it sets this class's field and not the
// one in the base-class!
@Override
void setField(String set) {
this.field = set;
}
// copied the toString from above - here it is accessing the
// base-class's field via getter and this class's field directly.
@Override
public String toString() {
return this.getClass().getSimpleName() + ": get()->" + getField() + " vs. field->" + field;
}
}
public static void main(String[] args) {
// build both types of extending classes and invoke their setters
Arrays.asList(new ProperExtension(), new HidingExtension()).forEach(obj -> {
System.out.println("before ~> " + obj);
obj.setField("SET");
System.out.println("after ~> " + obj + "\n");
});
}
}
1) 为了更快地获得更好的帮助,请发布一个or。2) 请参阅并发布
PDialogMaterial
的代码,以及其他类似PDialogOrder
@andreThompson的代码。我已跟踪堆栈跟踪并找到抛出空指针的方法。它并没有让我更接近解决方案,因为其他类使用这个方法没有任何问题。经过简化课程的从头开始,我再也没有例外。我正在研究最小、完整和可验证的示例,但可能需要一段时间:(您需要模型和控制器部分吗?…您需要模型和控制器部分吗?“我们需要一份属于VE的MC。阅读链接并询问任何您不理解的内容。鉴于我是SSCCE的作者,以及MCVE的初稿,我完全有能力解释。可能是1)的副本,为了更快地获得更好的帮助,请发布一份或多份。2) 请参阅并发布PDialogMaterial
的代码,以及其他类似PDialogOrder
@andreThompson的代码。我已跟踪堆栈跟踪并找到抛出空指针的方法。它并没有让我更接近解决方案,因为其他类使用这个方法没有任何问题。经过简化课程的从头开始,我再也没有例外。我正在研究最小、完整和可验证的示例,但可能需要一段时间:(您需要模型和控制器部分吗?…您需要模型和控制器部分吗?“我们需要的是一个虚拟现实的MC。阅读链接并询问您不了解的任何内容。鉴于我是SSCCE的作者,以及MCVE的初稿,我可以很好地进行解释。可能是重复的谢谢!感谢您的努力和您花时间浏览我的意大利面软件!它成功了,现在我终于可以继续了谢谢你!谢谢你的努力和你花的时间来使用我的意大利面软件!它成功了,现在我终于可以继续了。