目录
- 前言
- 插件实现
- 创建项目
- 猜拳游戏实现
- 游戏弹窗实现
- 监听空指针异常
- 安装插件
- 演示
- 最后
前言
“java.lang.NullPointerException” 空指针异常可以说是Java程序最容易出现的异常了,我写了一个 IDEA
插件,每当程序出现空指针异常时就会弹出一个“猜拳游戏”窗口,该窗口不能直接关闭,只有当你游戏获胜时,窗口才会自动关闭。
作用是啥?
嘲讽罢了。
插件实现
创建项目
IDEA
创建一个插件开发项目非常方便,已经内置了。
猜拳游戏实现
很简单。
实现原理:提供3个按钮,分别为“石头、剪刀、布”,对应值“1、2、3”,再为按钮绑定点击事件,按键点击之后调用处理函数传入对应的值即可。
处理函数 handle(int selectedValue)
的实现:利用随机数随机为电脑生成一个值与用户选择的值做比较,“石头赢剪刀、剪刀赢布、布赢石头”,然后显示游戏结果,用户获胜时会触发回调函数(用于关闭弹窗)。
package cn.xeblog.mora.ui;
import javax.swing.*;
import java.awt.*;
import java.util.Random;
/**
* @author anlingyi
* @date 2022/8/11 8:02 PM
*/
public class MoraGame extends JPanel {
/**
* 猜拳获胜调用
*/
private Runnable runnable;
/**
* 提示标签
*/
private JLabel tipsLabel;
/**
* 结束标记
*/
private boolean isOver;
public MoraGame(Runnable runnable) {
setMinimumSize(new Dimension(250, 100));
setLayout(new BorderLayout());
this.runnable = runnable;
init();
}
private void init() {
this.tipsLabel = new JLabel("请出拳!", JLabel.CENTER);
this.tipsLabel.setPreferredSize(new Dimension(250, 50));
this.tipsLabel.setFont(new Font("", 0, 15));
this.tipsLabel.setForeground(new Color(255, 128, 128));
JButton stoneButton = new JButton("石头");
JButton shearsButton = new JButton("剪刀");
JButton clothButton = new JButton("布");
stoneButton.setFocusPainted(false);
stoneButton.setBorderPainted(false);
stoneButton.addActionListener(l -> handle(1));
shearsButton.setFocusPainted(false);
shearsButton.setBorderPainted(false);
shearsButton.addActionListener(l -> handle(2));
clothButton.setFocusPainted(false);
clothButton.setBorderPainted(false);
clothButton.addActionListener(l -> handle(3));
JPanel centerPanel = new JPanel();
centerPanel.setPreferredSize(new Dimension(250, 30));
centerPanel.add(stoneButton);
centerPanel.add(shearsButton);
centerPanel.add(clothButton);
add(tipsLabel, BorderLayout.NORTH);
add(centerPanel, BorderLayout.CENTER);
}
private void handle(int selectedValue) {
if (isOver) {
return;
}
int value = new Random().nextInt(3) + 1;
boolean isWin = selectedValue == (value - 1 == 0 ? 3 : value - 1);
String result;
if (isWin) {
isOver = true;
result = "你赢~";
} else if (selectedValue == value) {
result = "平局~";
} else {
result = "电脑赢~";
}
showTips("电脑 -> " + getText(value) + ",你 -> " + getText(selectedValue) + "," + result);
if (isWin) {
new Thread(() -> {
try {
Thread.sleep(800);
this.runnable.run();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
}
}
private String getText(int value) {
switch (value) {
case 1:
return "石头";
case 2:
return "剪刀";
case 3:
return "布";
}
return "";
}
private void showTips(String tips) {
tipsLabel.setText(tips);
}
}
游戏弹窗实现
将窗口设置为不可关闭,传递弹窗关闭回调函数到游戏处理对象。
package cn.xeblog.mora.ui;
import com.intellij.openapi.ui.DialogWrapper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
/**
* @author anlingyi
* @date 2022/8/11 7:58 PM
*/
public class MoraDialog extends DialogWrapper {
public MoraDialog() {
super(true);
setTitle("猜拳游戏?");
setResizable(false);
setCrossClosesWindow(false);
init();
}
@Override
protected @Nullable JComponent createCenterPanel() {
return new MoraGame(() -> SwingUtilities.invokeLater(() -> this.close(0)));
}
@Override
protected @NotNull Action[] createActions() {
return new Action[]{};
}
}
监听空指针异常
实现控制台过滤接口,判断控制台的输出内容是否包含 java.lang.NullPointerException
,如果包含则弹出游戏窗口。
package cn.xeblog.mora.filter;
import cn.xeblog.mora.ui.MoraDialog;
import com.intellij.execution.filters.ConsoleFilterProvider;
import com.intellij.execution.filters.Filter;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
/**
* @author anlingyi
* @date 2022/8/11 11:46 PM
*/
public class ConsoleFilter implements ConsoleFilterProvider {
@Override
public Filter @NotNull [] getDefaultFilters(@NotNull Project project) {
return new Filter[]{(line, entireLength) -> {
if (line.contains("java.lang.NullPointerException")) {
SwingUtilities.invokeLater(() -> new MoraDialog().show());
}
return null;
}};
}
}
注册过滤器
plugin.xml
添加我们自定义的控制台过滤器实现。
<extensions defaultExtensionNs="com.intellij">
<consoleFilterProvider implementation="cn.xeblog.mora.filter.ConsoleFilter"/>
</extensions>
安装插件
插件打包
Gradle -> Tasks -> build -> assemble
打包之后的文件位于项目的 build
目录下:build/distributions/xxx.zip
插件安装
进入插件中心,选择本地文件安装即可。
演示
会出现空指针的代码
public static void main(String[] args) {
Object obj = null;
System.out.println(obj.toString());
}
运行之后
当我猜拳赢了之后,窗口就自动关闭了。