Java运行中Thread对象调用方法抛出NullPointerException问题
问题原因
这个空指针和线程运行状态没有直接关系,核心是代码里的变量作用域和赋值逻辑错误:
- 你在
main方法中声明的Graphic_handler grap = new Graphic_handler(bot);是main方法的局部变量,仅在main方法执行范围内有效。两个ActionListener是类级别的匿名内部类,它们引用的grap是外部类的成员变量,这个成员变量从未被初始化赋值,默认值为null,调用grap.next()时自然触发空指针,异常信息里的this.this$0.grap is null就是指外部类实例持有的grap成员为null。 Graphic_handler类的构造方法接收了Instagram_bot bot参数,但没有将参数赋值给类的成员变量bot,后续run方法调用set_time()访问bot.date时同样会触发空指针。- 额外逻辑问题:你在
next()/last()方法中调用了notify(),但run()方法的循环里只有sleep()没有执行wait(),这个notify()调用没有任何实际作用,无法实现线程交互效果。 - 额外线程安全问题:Swing组件的更新必须在AWT事件调度线程执行,你在自定义线程里直接调用
bot.date.setText()会存在UI渲染异常风险。
修正方法
- 将
grap、bot声明为外部类的成员变量,不要在main方法中声明同名局部变量,初始化后赋值给成员变量,保证ActionListener能访问到有效实例。 - 修正
Graphic_handler构造方法,将传入的bot参数赋值给类成员变量。 - 移除无意义的
notify()调用,给共享变量off加volatile关键字保证多线程下的可见性,不要空吞中断异常。 - 把UI更新逻辑包装到
SwingUtilities.invokeLater()中执行,符合Swing线程规范。
修正后代码示例
外部类代码修正:
import javax.swing.*; import java.awt.event.ActionListener; public class YourMainClass { // 声明为类静态成员,保证main方法和ActionListener都能访问 private static Graphic_handler grap; private static Instagram_bot bot; ActionListener right_ear = e -> grap.next(); ActionListener left_ear = e -> grap.last(); public static void main(String[] args) { // 先初始化bot,避免传入null bot = new Instagram_bot(); // 初始化后赋值给类成员,不要声明局部变量 grap = new Graphic_handler(bot); grap.start(); // 其他UI初始化逻辑 } }
Graphic_handler类修正:
import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; public class Graphic_handler extends Thread { // 加volatile保证多线程下off变量的可见性 volatile int off = 0; int columns = 7; int rows = 7; private final Instagram_bot bot; public Graphic_handler(Instagram_bot bot) { // 把传入的bot参数赋值给类成员 this.bot = bot; } public void run() { while (!Thread.currentThread().isInterrupted()) { try { Thread.sleep(1000); } catch (InterruptedException e) { // 恢复中断状态,退出循环,不要空吞异常 Thread.currentThread().interrupt(); break; } set_time(); // 这里可以直接读取off的最新值执行业务逻辑 } } private void set_time() { Date date = Calendar.getInstance().getTime(); DateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy hh:mm:ss"); String strDate = dateFormat.format(date); // Swing UI更新切到事件调度线程执行 SwingUtilities.invokeLater(() -> bot.date.setText(strDate)); } public void change_center(int offset) { } public synchronized void next() { off++; } public synchronized void last() { off--; } }
内容的提问来源于stack exchange,提问作者T.Stark
相关产品推荐
相关产品推荐

