繁体   English   中英

在两个单独的.java文件之间传递数据

[英]Passing data between two separate .java files

我正在学习Java,碰巧遇到了Fred Swartz的leepoint.net网页上的ActionListener示例。 DogYears2.java。

为了学习起见,我通过将ActionListener ConvertBtnListenerDogYears2.java分离为一个单独的顶级类文件ConvertBtnListener.java

DogYears2.java文件

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;  // Needed for ActionListener

//////////////////////////////////////////////////////// class DogYears2
class DogYears2 extends JFrame {
//======================================================== constants
final static int DOG_YEARS_PER_HUMAN_YEAR = 7;

//=============================================== instance variables
private JTextField _humanYearsTF = new JTextField(3);
private JTextField _dogYearsTF   = new JTextField(3);

//====================================================== constructor
public DogYears2() {
    // 1... Create/initialize components
    JButton convertBtn = new JButton("Convert");
    convertBtn.addActionListener(new ConvertBtnListener());

    _dogYearsTF.addActionListener(new ConvertBtnListener());
    _humanYearsTF.setEditable(false);


    // 2... Create content panel, set layout
    JPanel content = new JPanel();
    content.setLayout(new FlowLayout());

    // 3... Add the components to the content panel.
    content.add(new JLabel("Dog Years"));
    content.add(_dogYearsTF);              // Add input field
    content.add(convertBtn);               // Add button
    content.add(new JLabel("Human Years"));
    content.add(_humanYearsTF);            // Add output field

    // 4... Set this window's attributes, and pack it.
    setContentPane(content);
    pack();                               // Layout components.
    setTitle("Dog Year Converter");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setLocationRelativeTo(null);          // Center window.
}

    //====================================================== method main
public static void main(String[] args) {
    DogYears2 window = new DogYears2();
    window.setVisible(true);
}

}

ConvertBtnListener.java文件

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;  // Needed for ActionListener

class ConvertBtnListener implements ActionListener {
JTextField _dogYearsTF;
JTextField _humanYearsTF;
int DOG_YEARS_PER_HUMAN_YEAR = 7;


    public void actionPerformed(ActionEvent e) {
        //... Get the value from the dog years textfield.
        String dyStr = _dogYearsTF.getText();
        int dogYears = Integer.parseInt(dyStr);

        //... Convert it - each dog year is worth 7 human years.
        int humanYears = dogYears * DOG_YEARS_PER_HUMAN_YEAR;

        //... Convert to string and set human yrs textfield
        _humanYearsTF.setText("" + humanYears);
    }

}

现在,当我运行DogYears.java文件时,会弹出GUI,并且当我在文本字段中输入人类年数时,我得到了NullPointerException

为了学习Java Noob,我希望有人能启发我为什么会发生这种情况,如果我坚持维护单独的ActionListener类文件,又该如何解决?

第一步是停止思考文件。 应该在谈论类和对象。

在您的示例中,您定义了两个类(这些定义碰巧放在了两个单独的文件中,但这并不重要)。

在第一类DogYears2 (注意:没有结尾的.java用于文件),您在main方法中创建一个实例(也称为一个对象)。

在第二个类ConvertBtnListener您在DogYears2的构造函数中创建两个实例(也称为两个对象)。

ConvertBtnListener类中的_dogYearsTF_humanYearsTF字段永远不会获得值 ,因此,一旦您尝试对它们进行操作,就会得到NullPointerException

你应该知道, _dogYearsTFConvertBtnListener完全无关 _dogYearsTFDogYears2 此外,场_dogYearsTF中的第一个实例 ConvertBtnListener完全无关的字段_dogYearsTF n中的第二个实例

既然我已经告诉了您为什么它不起作用 ,我可能应该告诉您如何使其起作用:

一种方法是将必要的JTextField对象传递给ConvertBtnListener对象的构造函数。 为此,您需要在该类中创建一个构造函数,该构造函数接受两个JTextField引用并将它们分配给适当的字段。

通常的方法是使侦听器成为UI类的内部类,在这种情况下,它可以直接访问UI类字段,并且不需要这样的构造函数(这就是为什么在原始示例中如此)。

在您的侦听器类中,请初始化文本字段变量。 考虑一下:

class ConvertBtnListener implements ActionListener {
    ....
    ConvertBtnListener(JTextField humanYearsTF, JTextField dogYearsTF) {
        _dogYearsTF = dogYearsTF;
        _humanYearsTF = humanYearsTF;
    }
    ....
 }

public DogYears2() {
    ActionListener listener = new ConvertBtnListener(_humanYearsTF, _dogYearsTF);         
    JButton convertBtn = new JButton("Convert");
    ...
}

另请参阅什么是匿名类。 这是实现此类操作的另一种方法。

---编辑而不是声明

int DOG_YEARS_PER_HUMAN_YEAR = 7;

在ConvertBtnListener类中-仅使用您先前在DogYears.java中声明的静态字段。 因此,这应该是正确的方法。

int humanYears = dogYears * DogYears2.DOG_YEARS_PER_HUMAN_YEAR;

---编辑构造函数参数顺序

ConvertBtnListener您将在此处获得空指针异常:

String dyStr = _dogYearsTF.getText();

... 和这里:

 _humanYearsTF.setText("" + humanYears);

您永远不会在ConvertBtnListener;初始化_dogYearsTF_humanYearsTF ConvertBtnListener; 这些字段与DogYears2的相同名称无关。

您可以尝试使用getSource()函数

 public void actionPerformed(ActionEvent e) {
        //... Get the value from the dog years textfield.
        String dyStr = _dogYearsTF.getText();
        int dogYears = Integer.parseInt(dyStr);
JTextField _humanYearsTF = (JTextField)e.getSource(); // new line.
        //... Convert it - each dog year is worth 7 human years.
        int humanYears = dogYears * DOG_YEARS_PER_HUMAN_YEAR;

        //... Convert to string and set human yrs textfield
        _humanYearsTF.setText("" + humanYears);
    }

这将获取触发操作事件的来源。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM