【问题标题】:Java another Static/Non-Static issueJava 另一个静态/非静态问题
【发布时间】:2011-08-17 20:08:40
【问题描述】:

好的,使用 Eclipse IDE 并被静态/非静态问题绊倒。我想我明白了,但不完全,这里是代码。

第一部分,主要是使用 swing UI builder 创建的。 编辑了 cmets/imports

public class Screen {

private JFrame frame;
public JLabel lblNewLabel;
public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                Screen window = new Screen();
                window.frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

public Screen() {
    initialize();
}

void initialize() {
    XListener listenItem = new XListener("Woot"); // creates listen object

    frame = new JFrame();
    frame.setBounds(100, 100, 450, 300);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().setLayout(null);

    JLabel lblNewLabel = new JLabel("New label");
    lblNewLabel.setBounds(193, 154, 56, 16);
    frame.getContentPane().add(lblNewLabel);

    JButton btnNewButton = new JButton("New button");
    btnNewButton.setBounds(163, 73, 97, 25);
    frame.getContentPane().add(btnNewButton);
    btnNewButton.addActionListener(listenItem); // attaches it to listen object
}
void changeLabel(String setString) {
    lblNewLabel.setText(setString);
}
}

第二部分是监听类

// creates class for listen item
public class XListener implements ActionListener {
    String foo;
    XListener(String setString) {
        foo = setString;
    }
    public void actionPerformed(ActionEvent btnNewButton) {
        **Screen.changeLabel(foo);**
    }
}

它抱怨不能从类型 Screen 对非静态方法 changeLabel(String) 进行静态引用。但是,如果我使用窗口代替屏幕,它找不到对象。这让我非常困惑。我理解代码的方式是主要方法创建一个名为 window 的 Screen 对象,该对象在初始化时还会创建一个 XListener 对象。为什么它认为 actionPerformed 方法是静态的?我知道我缺少一些基本的东西,而且我一直在关注 java 的“轨迹”,只是不明白。

【问题讨论】:

标签: java static-methods


【解决方案1】:

您应该在操作发生时传入对要影响的Screen 对象的引用:

// creates class for listen item
public class XListener implements ActionListener {
    String foo;
    Screen myScreen;

    XListener(String setString, Screen scr) {
        foo = setString;
        myScreen = scr;
    }
    public void actionPerformed(ActionEvent btnNewButton) {
        myScreen.changeLabel(foo);
    }
}

然后,像这样初始化你的监听器:

XListener listenItem = new XListener("Woot", this);

您必须这样做,因为changeLabel() 方法是Screen 类的实例方法,但您正试图像static 方法一样访问它。通过访问正确的Screen 实例,您可以正确调用该方法。

【讨论】:

    【解决方案2】:

    您的 XListener 类需要一个对象来调用它。调用Screen.changeLabel(foo) 将尝试调用类 Screen 上的静态方法。您需要将 Screen 对象传递到您的 XListener 类中。

    public class XListener implements ActionListener {
        String foo;
        Screen myScreen; // added
        XListener(String setString, Screen theScreen) {
            foo = setString;
            myScreen= theScreen; // added
        }
        public void actionPerformed(ActionEvent btnNewButton) {
            screen.changeLabel(foo); // fixed
        }
    }
    

    然后改变你的初始化方法:

    void initialize() {
        XListener listenItem = new XListener("Woot",this); // creates listen object
    
        // rest below
    }
    

    【讨论】:

      【解决方案3】:

      方法changeLabel 是一个实例方法,但您正尝试使用. 的静态方法语法来调用它。您需要获取对Screen 对象的引用才能调用此方法。

      解决它的一种方法可能是将这样一个对象传递给侦听器的构造函数,如下所示:

      XListener(Screen screen, String setString)
          ...
          this.screen=screen;
          ...
          }
      

      【讨论】:

        【解决方案4】:

        window 是在main 中创建的匿名Runnable 子类中run 方法内的一个本地 变量。你当然不能在XListener.actionPerformed 中引用它。

        Java 不认为 actionPerformed 方法是静态的 - 它是说 changeLabel 是非静态的,但您正试图 访问它,就好像它是静态的 from actionPerformed,这里:

        Screen.changeLabel(foo);
        

        actionPerformed 是否为静态无关紧要——关键是您需要引用Screen实例 才能调用changeLabel 方法。否则就像问“这个人有多高?” - 除非您指定 您在说的是哪个人,否则这没有意义。

        如果您发现静态/非静态令人困惑,我会强烈建议您暂时不要管用户界面。编写一些简单的 console 应用程序来创建一些对象,调用它们的方法等。熟悉该语言,最好是一些核心库(例如集合和 IO)。 然后您将能够进入有时令人生畏的用户界面世界,并且至少知道 语言 级别发生了什么。

        【讨论】:

          【解决方案5】:

          您已经定义了一个名为 changeLabel 的非静态方法,但是您尝试从类中访问它,即 Screen.changeLabel() ,因为它不是静态方法,所以您不能这样做。您首先需要实例化 Screen ,然后从您创建的实例中调用此方法(或通过实例等,关键是非静态方法需要从对象访问,而不是直接从类访问)。

          【讨论】:

          • 根据 changeLabel() 的作用,您可能需要对 screen 进行一些其他更改以使此方法静态
          • 将 changeLabel 设为静态将无济于事,除非 Screen 类中的其他所有内容也是静态的,这有点愚蠢。
          • 同意,这很愚蠢,但它会编译。我不是在提倡这种解决方案,只是说这是一种选择
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多