You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java GUI打印按钮触发NullPointerException:无法调用List.iterator()

问题:点击Print Doctors按钮触发空指针异常

我正在为控制台应用开发GUI,但点击Print Doctors按钮时遇到无法理解的错误。以下是相关代码:

package com.company;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import javax.swing.*;

public class WestminsterSkinConsultationManagerGUI extends JFrame {
    private static WestminsterSkinConsultationManager manager;
    private final ArrayList<Doctor> doctors;
    private JTextField nameField;
    private JTextField surnameField;
    private JTextField dobField;
    private JTextField mobileField;
    private JTextField licenseField;
    private JTextField specializationField;
    private JTextField deleteField;
    private JButton addButton;
    private JButton deleteButton;
    private JButton printButton;
    private JButton saveButton;
    private JButton exitButton;
    private JTextArea doctorListArea;

    public WestminsterSkinConsultationManagerGUI() {
        // Initialize the manager
        manager = new WestminsterSkinConsultationManager();
        this.doctors = new ArrayList<Doctor>();


        // Set up the frame
        setTitle("Westminster Skin Consultation Manager");
        setSize(600, 400);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        // Create the panel for the input fields
        JPanel inputPanel = new JPanel();
        inputPanel.setLayout(new GridLayout(7, 2));

        // Create the input fields
        nameField = new JTextField();
        surnameField = new JTextField();
        dobField = new JTextField();
        mobileField = new JTextField();
        licenseField = new JTextField();
        specializationField = new JTextField();
        deleteField = new JTextField();

        // Add the input fields to the panel
        inputPanel.add(new JLabel("Name:"));
        inputPanel.add(nameField);
        inputPanel.add(new JLabel("Surname:"));
        inputPanel.add(surnameField);
        inputPanel.add(new JLabel("Date of birth:"));
        inputPanel.add(dobField);
        inputPanel.add(new JLabel("Mobile number:"));
        inputPanel.add(mobileField);
        inputPanel.add(new JLabel("Medical license number:"));
        inputPanel.add(licenseField);
        inputPanel.add(new JLabel("Specialization:"));
        inputPanel.add(specializationField);
        inputPanel.add(new JLabel("Medical license number to delete:"));
        inputPanel.add(deleteField);

        // Create the panel for the buttons
        JPanel buttonPanel = new JPanel();
        buttonPanel.setLayout(new GridLayout(5, 1));

        // Create the buttons
        addButton = new JButton("Add Doctor");
        deleteButton = new JButton("Delete Doctor");
        printButton = new JButton("Print Doctors");
        saveButton = new JButton("Save to File");
        exitButton = new JButton("Exit");

        // Add the buttons to the panel
        buttonPanel.add(addButton);
        buttonPanel.add(deleteButton);
        buttonPanel.add(printButton);
        buttonPanel.add(saveButton);
        buttonPanel.add(exitButton);

        // Create the panel for the doctor list
        JPanel listPanel = new JPanel();
        doctorListArea = new JTextArea();
        doctorListArea.setEditable(false);
        JScrollPane scrollPane = new JScrollPane(doctorListArea);
        listPanel.add(scrollPane);

        // Add the input panel, button panel, and list panel to the frame
        add(inputPanel, BorderLayout.WEST);
        add(buttonPanel, BorderLayout.EAST);
        add(listPanel, BorderLayout.SOUTH);

        // Add action listeners to the buttons
        addButton.addActionListener(new AddButtonListener());
        deleteButton.addActionListener(new DeleteButtonListener());
        printButton.addActionListener(new PrintButtonListener());
        saveButton.addActionListener(new SaveButtonListener());
        exitButton.addActionListener(new ExitButtonListener());

        // Display the frame
        setVisible(true);
    }

    // Inner class for the Add button listener
    private class AddButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            // Get the input values
            String name = nameField.getText();
            String surname = surnameField.getText();
            String dobString = dobField.getText();
            String mobile = mobileField.getText();
            String license = licenseField.getText();
            String specialization = specializationField.getText();

            // Create a new doctor object with the input values
            DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
            Date dob = null;
            try {
                dob = df.parse(dobString);
            } catch (ParseException ex) {
                JOptionPane.showMessageDialog(null, "Error: Invalid date of birth format. Use dd/MM/yyyy.");
                return;
            }
            Doctor doctor = new Doctor(name, surname, dob, mobile, license, specialization);

            // Add the doctor to the manager
            manager.addDoctor(doctor);
        }
    }

    // Inner class for the Delete button listener
    private class DeleteButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            // Get the medical license number to delete
            String license = deleteField.getText();

            // Delete the doctor with the specified medical license number
            manager.deleteDoctor(license);
        }
    }

    // Inner class for the Print button listener
    private class PrintButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            // Clear the text area
            doctorListArea.setText("");


                // Print the list of doctors
                List<Doctor> doctors = manager.getDoctors();
                for (Doctor doctor : doctors) {
                    doctorListArea.append("Name: " + doctor.getName() + "\n");
                    doctorListArea.append("Surname: " + doctor.getSurname() + "\n");
                    doctorListArea.append("Date of birth: " + doctor.getDateOfBirth() + "\n");
                    doctorListArea.append("Mobile number: " + doctor.getMobileNumber() + "\n");
                    doctorListArea.append("Medical license number: " + doctor.getMedicalLicenceNumber() + "\n");
                    doctorListArea.append("Specialization: " + doctor.getSpecialisation() + "\n\n");
                }
            }
        }

        // Inner class for the Save button listener
        private static class SaveButtonListener implements ActionListener {
            public void actionPerformed(ActionEvent e) {
                // Save the list of doctors to a file
                manager.saveToFile();
            }
        }

        // Inner class for the Exit button listener
        private static class ExitButtonListener implements ActionListener {
            public void actionPerformed(ActionEvent e) {
                // Close the program
                System.exit(0);
            }
        }

        public static void main(String[] args) {
            new WestminsterSkinConsultationManagerGUI();
        }
    }

触发的错误信息如下:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException: Cannot invoke "java.util.List.iterator()" because "doctors" is null
at com.company.WestminsterSkinConsultationManagerGUI$PrintButtonListener.actionPerformed(WestminsterSkinConsultationManagerGUI.java:158)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1972)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2313)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
at java.desktop/javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:279)
at java.desktop/java.awt.Component.processMouseEvent(Component.java:6616)
at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3398)
at java.desktop/java.awt.Component.processEvent(Component.java:6381)
at java.desktop/java.awt.Container.processEvent(Container.java:2266)
at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4991)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4823)
at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4575)
at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
at java.desktop/java.awt.Component.dispatchEvent(Component.java:4823)
at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:775)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:747)
at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:744)
at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
错误原因分析

错误堆栈明确指出,空指针异常发生在PrintButtonListener的for (Doctor doctor : doctors)循环处,原因是调用manager.getDoctors()返回了null。当尝试遍历一个null的List时,JVM会抛出NullPointerException,因为无法对null对象调用iterator()方法。

问题根源在于WestminsterSkinConsultationManager类的getDoctors()方法实现:要么该方法没有初始化存储医生的List就返回,要么在某些情况下返回了null而不是空列表。

解决方法

方法一:修复WestminsterSkinConsultationManager的getDoctors()方法

确保存储医生的List在类初始化时就被创建,并且getDoctors()方法始终返回一个有效的List(即使是空列表,也不要返回null)。示例实现如下:

public class WestminsterSkinConsultationManager {
    // 初始化医生列表,避免null
    private final List<Doctor> doctors = new ArrayList<>();

    // 添加医生的方法
    public void addDoctor(Doctor doctor) {
        doctors.add(doctor);
    }

    // 删除医生的方法
    public void deleteDoctor(String license) {
        doctors.removeIf(d -> d.getMedicalLicenceNumber().equals(license));
    }

    // 获取医生列表,返回副本避免外部修改内部状态
    public List<Doctor> getDoctors() {
        return new ArrayList<>(doctors);
    }

    // 其他方法...
}

方法二:在GUI代码中增加空值判断

即使getDoctors()可能返回null,也可以在GUI的打印逻辑中提前处理,避免崩溃并给出友好提示:
修改PrintButtonListener的代码:

private class PrintButtonListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
        doctorListArea.setText("");

        List<Doctor> doctors = manager.getDoctors();
        // 增加空判断和空列表判断
        if (doctors == null || doctors.isEmpty()) {
            doctorListArea.append("当前没有医生数据");
            return;
        }

        for (Doctor doctor : doctors) {
            doctorListArea.append("Name: " + doctor.getName() + "\n");
            doctorListArea.append("Surname: " + doctor.getSurname() + "\n");
            doctorListArea.append("Date of birth: " + doctor.getDateOfBirth() + "\n");
            doctorListArea.append("Mobile number: " + doctor.getMobileNumber() + "\n");
            doctorListArea.append("Medical license number: " + doctor.getMedicalLicenceNumber() + "\n");
            doctorListArea.append("Specialization: " + doctor.getSpecialisation() + "\n\n");
        }
    }
}

建议优先使用方法一,从根源上避免返回null的情况,这是更规范的Java编程实践。方法二则作为防御性编程的补充,进一步提升程序稳定性。

内容的提问来源于stack exchange,提问作者Himasha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 12:55:22