将项目添加到 JList 导致 java.lang.NullPointerException
Adding items to JList caused java.lang.NullPointerException
我已经在我的代码中搜索一个问题超过 4 个小时,但找不到...问题是,我有一个 java class 和一个 JFrame ,我把 JList 和 DefaultListModel 放在了一起。然后我有另一个 java class 尝试将项目添加到 DefaultListModel。问题是,除了将项目添加到 DefaultListModel 之外,一切正常。关于这里出了什么问题的任何想法?
主要javaclass:
package ledpanelplayer;
imports; //IMPORTS
/**
*
* @author Dominik
*/
public class LedPanelPlayer extends JFrame {
public static String RUN_PATH;
public static String LIB_PATH;
public static String PREFERENCES_FILE;
public static String LOG_FILE;
public static file_helper f;
public static json_helper j;
public static Player player;
public static Preferences preferences;
public static Schedule s;
public static Console c;
public static JFrame WINDOW_FRAME;
public static int WINDOW_W;
public static int WINDOW_H;
public static String WINDOW_TITLE;
public static JList SCHEDULE_LIST;
public static DefaultListModel SCHEDULE_LIST_MODEL;
public static void main(String[] args) {
setLookAndFeel();
setUIFont(new javax.swing.plaf.FontUIResource("Arial",Font.PLAIN,12));
init(); //Init application
}
private static void setLookAndFeel() {} //Doesn't matter
public static void setUIFont (javax.swing.plaf.FontUIResource f){} //Doesn't matter
public static void init() {
RUN_PATH = new File("").getAbsolutePath()+"\"; //Get local directory
LIB_PATH = RUN_PATH + "\lib"; //Set libs directory
PREFERENCES_FILE = RUN_PATH + "\preferences.lpp"; //Set preferences file path
LOG_FILE = RUN_PATH + "\log.txt"; //Set log file path
f = new file_helper(); //Create new file_helper()
c = new Console(); //Create new Console()
c.init_files();
j = new json_helper(); //Create new json_helper()
player = new Player(); //Create new Player()
preferences = new Preferences(); //Create new Preferences()
s = new Schedule(); //Create new Schedule()
WINDOW_FRAME = new JFrame(); //Create new JFrame()
WINDOW_W = 800;
WINDOW_H = 540;
WINDOW_TITLE = "Demo";
WINDOW_FRAME.setSize(WINDOW_W,WINDOW_H);
WINDOW_FRAME.setLocationRelativeTo(null);
WINDOW_FRAME.setVisible(true);
WINDOW_FRAME.setTitle(WINDOW_TITLE);
WINDOW_FRAME.setDefaultCloseOperation(EXIT_ON_CLOSE);
WINDOW_FRAME.getContentPane().setLayout(null);
WINDOW_FRAME.getContentPane().setBackground(new Color(237, 237, 237));
WINDOW_FRAME.setResizable(false);
SCHEDULE_LIST_MODEL = new DefaultListModel();
SCHEDULE_LIST = new JList(SCHEDULE_LIST_MODEL); //Create new JList()
SCHEDULE_LIST.setBounds(20, 20, 382, 444);
SCHEDULE_LIST.setBackground(new Color(226,226,226));
//SCHEDULE_LIST_MODEL.addElement("<html><b>1.</b> Demo <p> duration: 10s | file: demo.mp4 | repeat: *36000</p></html>");
WINDOW_FRAME.add(SCHEDULE_LIST);
}
public static void addElement(String e) {
SCHEDULE_LIST_MODEL.addElement(e);
}
}
其他class:
public static void updateList() {
for (int i = 0; i < SCHEDULE.size(); i++) {
try {
JSONObject object = (JSONObject)SCHEDULE.get(i);
String name = object.get("name").toString();
String duration = object.get("duration").toString();
String file = object.get("file").toString();
String repeat = object.get("repeat").toString();
LedPanelPlayer.addElement("<html><b>"+i+".</b> "+name+" <p> duration: "+(Integer.parseInt(duration)/1000)+"s | file: "+file+" | repeat: *"+repeat+"</p></html>");
}
catch(Exception e) {e.printStackTrace();c.err("Schedule.updateList() : " + e.toString());}
}
}
提前致谢!
堆栈跟踪:
java.lang.NullPointerException
at ledpanelplayer.LedPanelPlayer.addElement(LedPanelPlayer.java:369)
at ledpanelplayer.Schedule.updateList(Schedule.java:69)
at ledpanelplayer.Preferences.load(Preferences.java:50)
at ledpanelplayer.LedPanelPlayer.init(LedPanelPlayer.java:142)
at ledpanelplayer.LedPanelPlayer.main(LedPanelPlayer.java:98)
堆栈跟踪表明您正在调用 Preferences 的 load
方法,但在您问题的代码中,您只调用了 new Preferences()
。没有调用任何加载方法。尽管如此,您的堆栈跟踪是由代码生成的,其 init 方法实际上调用了 Preferences.load,后者又调用了 Schedule.updateList,后者又调用了 LedPanelPlayer.addElement.
问题是所有这些都发生在 SCHEDULE_LIST_MODEL 被赋值之前。在 Java 中,所有对象字段都默认初始化为 null
,除非您将它们初始化为其他内容。您不能在 null 上调用方法,这就是异常的原因。
将 SCHEDULE_LIST_MODEL 的赋值移动到调用任何首选项方法之前的一行,您的问题应该就会消失。
虽然 VGR 的答案(移动 SCHEDULE_LIST_MODEL 以便在初始化 Preferences 时它不为空)确实解决了您的即时问题,但我认为您遇到的问题仅仅是循环依赖问题的症状,这将使维护您的程序变得乏味(正如您花了大约 4 个小时发现的那样),并且简单地移动 SCHEDULE_LIST_MODEL 被赋值的位置最多是一个创可贴修复。
你的程序结构如下:LedPanelPlayer依赖于Preferences和Schedule,Preferences依赖于Schedule,Schedule依赖于LedPanelPlayer。您遇到的循环依赖问题在于 LedPanelPlayer 和 Schedule 都相互依赖才能发挥作用。 Schedule 需要 LedPanelPlayer.addElement,LedPanelPlayer 构建了一个 schedule(并且可能在您未发布的 LedPanelPlayer 的某些部分使用它,否则它只是闲逛而没有用)。
考虑完全从 LedPanelPlayer 中删除 SCHEDULE_LIST_MODEL,并使其成为实际管理它的 class 的实例字段(计划)。然后将 Schedule.getScheduleListModel() 添加到 Schedule 以便任何需要处理 Scheduling 的东西都可以简单地引用它,并使 updateList 不是静态的并引用 ScheduleListModel 的新家。由于 Preferences 想要处理调度信息,因此在其构造函数中需要一个调度实例。
这样,LedPanelPlayer将依赖Preferences和Schedule,Preferences依赖于Schedule,而现在Schedule将不再依赖于LedPanelPlayer正常运行,不仅解决了你的眼前问题,而且解决了根本原因(和使您的代码更易于阅读、理解和维护!)。
我已经在我的代码中搜索一个问题超过 4 个小时,但找不到...问题是,我有一个 java class 和一个 JFrame ,我把 JList 和 DefaultListModel 放在了一起。然后我有另一个 java class 尝试将项目添加到 DefaultListModel。问题是,除了将项目添加到 DefaultListModel 之外,一切正常。关于这里出了什么问题的任何想法?
主要javaclass:
package ledpanelplayer;
imports; //IMPORTS
/**
*
* @author Dominik
*/
public class LedPanelPlayer extends JFrame {
public static String RUN_PATH;
public static String LIB_PATH;
public static String PREFERENCES_FILE;
public static String LOG_FILE;
public static file_helper f;
public static json_helper j;
public static Player player;
public static Preferences preferences;
public static Schedule s;
public static Console c;
public static JFrame WINDOW_FRAME;
public static int WINDOW_W;
public static int WINDOW_H;
public static String WINDOW_TITLE;
public static JList SCHEDULE_LIST;
public static DefaultListModel SCHEDULE_LIST_MODEL;
public static void main(String[] args) {
setLookAndFeel();
setUIFont(new javax.swing.plaf.FontUIResource("Arial",Font.PLAIN,12));
init(); //Init application
}
private static void setLookAndFeel() {} //Doesn't matter
public static void setUIFont (javax.swing.plaf.FontUIResource f){} //Doesn't matter
public static void init() {
RUN_PATH = new File("").getAbsolutePath()+"\"; //Get local directory
LIB_PATH = RUN_PATH + "\lib"; //Set libs directory
PREFERENCES_FILE = RUN_PATH + "\preferences.lpp"; //Set preferences file path
LOG_FILE = RUN_PATH + "\log.txt"; //Set log file path
f = new file_helper(); //Create new file_helper()
c = new Console(); //Create new Console()
c.init_files();
j = new json_helper(); //Create new json_helper()
player = new Player(); //Create new Player()
preferences = new Preferences(); //Create new Preferences()
s = new Schedule(); //Create new Schedule()
WINDOW_FRAME = new JFrame(); //Create new JFrame()
WINDOW_W = 800;
WINDOW_H = 540;
WINDOW_TITLE = "Demo";
WINDOW_FRAME.setSize(WINDOW_W,WINDOW_H);
WINDOW_FRAME.setLocationRelativeTo(null);
WINDOW_FRAME.setVisible(true);
WINDOW_FRAME.setTitle(WINDOW_TITLE);
WINDOW_FRAME.setDefaultCloseOperation(EXIT_ON_CLOSE);
WINDOW_FRAME.getContentPane().setLayout(null);
WINDOW_FRAME.getContentPane().setBackground(new Color(237, 237, 237));
WINDOW_FRAME.setResizable(false);
SCHEDULE_LIST_MODEL = new DefaultListModel();
SCHEDULE_LIST = new JList(SCHEDULE_LIST_MODEL); //Create new JList()
SCHEDULE_LIST.setBounds(20, 20, 382, 444);
SCHEDULE_LIST.setBackground(new Color(226,226,226));
//SCHEDULE_LIST_MODEL.addElement("<html><b>1.</b> Demo <p> duration: 10s | file: demo.mp4 | repeat: *36000</p></html>");
WINDOW_FRAME.add(SCHEDULE_LIST);
}
public static void addElement(String e) {
SCHEDULE_LIST_MODEL.addElement(e);
}
}
其他class:
public static void updateList() {
for (int i = 0; i < SCHEDULE.size(); i++) {
try {
JSONObject object = (JSONObject)SCHEDULE.get(i);
String name = object.get("name").toString();
String duration = object.get("duration").toString();
String file = object.get("file").toString();
String repeat = object.get("repeat").toString();
LedPanelPlayer.addElement("<html><b>"+i+".</b> "+name+" <p> duration: "+(Integer.parseInt(duration)/1000)+"s | file: "+file+" | repeat: *"+repeat+"</p></html>");
}
catch(Exception e) {e.printStackTrace();c.err("Schedule.updateList() : " + e.toString());}
}
}
提前致谢!
堆栈跟踪:
java.lang.NullPointerException
at ledpanelplayer.LedPanelPlayer.addElement(LedPanelPlayer.java:369)
at ledpanelplayer.Schedule.updateList(Schedule.java:69)
at ledpanelplayer.Preferences.load(Preferences.java:50)
at ledpanelplayer.LedPanelPlayer.init(LedPanelPlayer.java:142)
at ledpanelplayer.LedPanelPlayer.main(LedPanelPlayer.java:98)
堆栈跟踪表明您正在调用 Preferences 的 load
方法,但在您问题的代码中,您只调用了 new Preferences()
。没有调用任何加载方法。尽管如此,您的堆栈跟踪是由代码生成的,其 init 方法实际上调用了 Preferences.load,后者又调用了 Schedule.updateList,后者又调用了 LedPanelPlayer.addElement.
问题是所有这些都发生在 SCHEDULE_LIST_MODEL 被赋值之前。在 Java 中,所有对象字段都默认初始化为 null
,除非您将它们初始化为其他内容。您不能在 null 上调用方法,这就是异常的原因。
将 SCHEDULE_LIST_MODEL 的赋值移动到调用任何首选项方法之前的一行,您的问题应该就会消失。
虽然 VGR 的答案(移动 SCHEDULE_LIST_MODEL 以便在初始化 Preferences 时它不为空)确实解决了您的即时问题,但我认为您遇到的问题仅仅是循环依赖问题的症状,这将使维护您的程序变得乏味(正如您花了大约 4 个小时发现的那样),并且简单地移动 SCHEDULE_LIST_MODEL 被赋值的位置最多是一个创可贴修复。
你的程序结构如下:LedPanelPlayer依赖于Preferences和Schedule,Preferences依赖于Schedule,Schedule依赖于LedPanelPlayer。您遇到的循环依赖问题在于 LedPanelPlayer 和 Schedule 都相互依赖才能发挥作用。 Schedule 需要 LedPanelPlayer.addElement,LedPanelPlayer 构建了一个 schedule(并且可能在您未发布的 LedPanelPlayer 的某些部分使用它,否则它只是闲逛而没有用)。
考虑完全从 LedPanelPlayer 中删除 SCHEDULE_LIST_MODEL,并使其成为实际管理它的 class 的实例字段(计划)。然后将 Schedule.getScheduleListModel() 添加到 Schedule 以便任何需要处理 Scheduling 的东西都可以简单地引用它,并使 updateList 不是静态的并引用 ScheduleListModel 的新家。由于 Preferences 想要处理调度信息,因此在其构造函数中需要一个调度实例。
这样,LedPanelPlayer将依赖Preferences和Schedule,Preferences依赖于Schedule,而现在Schedule将不再依赖于LedPanelPlayer正常运行,不仅解决了你的眼前问题,而且解决了根本原因(和使您的代码更易于阅读、理解和维护!)。