Java Swing按钮监听器向JComboBox添加项触发空指针异常
问题描述
开发学校Swing课程项目时,需要实现点击按钮将文本框输入内容添加到JComboBox下拉框的功能,实现逻辑为先将携带对应属性的Object实例存入集合,再将其添加到名为cbbkateaus的JComboBox组件中。
程序运行后内容无法成功添加到下拉框,抛出如下空指针错误:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException at MtVwGui$2.actionPerformed(MtVwGui.java:119)
后续伴随一系列javax.swing包相关报错,测试发现即使直接添加代码注释中预留的String类型内容,也会触发相同错误(代码内对象命名采用德语),完整复现代码如下:
import java.awt.BorderLayout; public class MtVwGui extends JFrame { private JPanel contentPane; private JTextField txtHersteller; private JTextField txtModell; private JTextField txtBaujahr; private JTextField txtHubraum; private JTextField txtKategorien; private ArrayList<Kategorien> kategorienListe; private ArrayList<Motorraeder> motorraederListe; private Kategorien neueKategorie; private Motorraeder neuesMotorrad; private JComboBox cbbkateaus; /** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { MtVwGui frame = new MtVwGui(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the frame. */ public MtVwGui() { kategorienListe= new ArrayList<Kategorien>(); motorraederListe= new ArrayList<Motorraeder>(); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 888, 501); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(null); JLabel lbHersteller = new JLabel("Hersteller:"); lbHersteller.setBounds(21, 95, 46, 14); contentPane.add(lbHersteller); txtHersteller = new JTextField(); txtHersteller.setBounds(101, 92, 86, 20); contentPane.add(txtHersteller); txtHersteller.setColumns(10); JLabel lbModell = new JLabel("Modell:"); lbModell.setBounds(21, 128, 46, 14); contentPane.add(lbModell); txtModell = new JTextField(); txtModell.setBounds(101, 123, 86, 20); contentPane.add(txtModell); txtModell.setColumns(10); JLabel lbBaujahr = new JLabel("Baujahr:"); lbBaujahr.setBounds(21, 153, 46, 14); contentPane.add(lbBaujahr); txtBaujahr = new JTextField(); txtBaujahr.setBounds(101, 154, 86, 20); contentPane.add(txtBaujahr); txtBaujahr.setColumns(10); JLabel lblNewLabel = new JLabel("Hubraum:"); lblNewLabel.setBounds(21, 190, 54, 14); contentPane.add(lblNewLabel); txtHubraum = new JTextField(); txtHubraum.setBounds(101, 187, 86, 20); contentPane.add(txtHubraum); txtHubraum.setColumns(10); JButton btnaddMtr = new JButton("Motorrad hinzufügen"); btnaddMtr.setBounds(21, 259, 138, 23); contentPane.add(btnaddMtr); txtKategorien = new JTextField(); txtKategorien.setBounds(446, 92, 100, 20); contentPane.add(txtKategorien); txtKategorien.setColumns(10); JButton btnaddKate = new JButton("Kategorie hinzufügen"); btnaddKate.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { neueKategorie = new Kategorien(txtKategorien.getText()); //String addValue = txtKategorien.getText(); kategorienListe.add(neueKategorie); cbbkateaus.addItem(neueKategorie); System.out.println("add Kategorie wurde gedrückt"); System.out.println(neueKategorie.getBezeichnung()); } }); btnaddKate.setBounds(594, 91, 138, 23); contentPane.add(btnaddKate); JComboBox cbbkateaus = new JComboBox(); cbbkateaus.setModel(new DefaultComboBoxModel(new String[] {"none"})); cbbkateaus.setBounds(74, 215, 130, 23); contentPane.add(cbbkateaus); } }
异常产生原因
空指针的根源是Java变量作用域混淆:
类中已经提前声明了成员变量private JComboBox cbbkateaus;,但在构造方法初始化下拉框组件时,写了JComboBox cbbkateaus = new JComboBox();——这行代码相当于在构造方法的局部作用域内,重新定义了一个和成员变量完全同名的局部变量。后续给下拉框设置模型、将组件加入面板的所有操作,都是针对这个局部变量执行的,类的成员变量cbbkateaus自始至终没有被赋值,保持默认初始值null。
按钮的点击监听器是内部类,内部类访问外部类变量时会优先匹配外部类的成员变量,此时拿到的就是值为null的cbbkateaus,调用addItem方法时就会触发空指针异常。
修改方案
- 核心修复:找到构造方法里的
JComboBox cbbkateaus = new JComboBox();,删掉前面的类型声明JComboBox,改为cbbkateaus = new JComboBox();。此时初始化的就是类的成员变量,监听器调用时不会再拿到null值。 - 可选优化:当前下拉框的初始模型是仅接收String类型的
DefaultComboBoxModel,后续添加自定义Kategorien类型对象时,记得重写Kategorien类的toString()方法,返回分类名称字段,否则下拉框会显示对象的默认内存地址字符串,无法看到实际的分类名称。
修改后对应位置的正确代码片段:
// 移除重复的类型声明,直接为成员变量赋值 cbbkateaus = new JComboBox(); cbbkateaus.setModel(new DefaultComboBoxModel(new String[] {"none"})); cbbkateaus.setBounds(74, 215, 130, 23); contentPane.add(cbbkateaus);
内容的提问来源于stack exchange,提问作者kdendon
相关产品推荐
相关产品推荐

