![图片[1]-为什么阿里建议对 switch 括号内的 String 变量进行判空?-明恒博客](https://www.zym88.cn/wp-content/uploads/2024/08/20240819081126654-2024081900112671.png)
- 引言
- 变量类型为String
- 外部参数
- 总结
引言
空指针NullPointerException
可以说是开发中最经常碰到的异常了。良好的代码规范可以规避掉一些这样的异常。在《阿里巴巴规范手册》中有这样一条规范:
![图片[2]-为什么阿里建议对 switch 括号内的 String 变量进行判空?-明恒博客](https://www.zym88.cn/wp-content/uploads/2024/08/20240819081152994-2024081900115264.png)
我们可以从这句话得出两个前置条件:
- switch括号内的变量类型为String。
- 此变量为外部参数时。
变量类型为String
你知道这行代码输出什么吗?
public class SwitchString {public static void main(String[] args) {method (null);}public static void method(String param) {switch (param) {// 肯定不是进入这里case "sth":System.out.println("it's sth");break;// 也不是进入这里case "null":System.out.println("it's null");break;// 也不是进入这里default:System.out.println("default");}}}public class SwitchString { public static void main(String[] args) { method (null); } public static void method(String param) { switch (param) { // 肯定不是进入这里 case "sth": System.out.println("it's sth"); break; // 也不是进入这里 case "null": System.out.println("it's null"); break; // 也不是进入这里 default: System.out.println("default"); } } }public class SwitchString { public static void main(String[] args) { method (null); } public static void method(String param) { switch (param) { // 肯定不是进入这里 case "sth": System.out.println("it's sth"); break; // 也不是进入这里 case "null": System.out.println("it's null"); break; // 也不是进入这里 default: System.out.println("default"); } } }
如果我们不看上面的注释,你会认为程序会打印出哪句话呢?我们点击运行,报了NullPointerException
空指针异常~
Exception in thread "main" <a href="https://www.zym88.cn/tag/java" title="更多关于 java 的文章" target="_blank">java</a>.lang.NullPointerExceptionat SwitchString.method(SwitchString.java:8)at SwitchString.main(SwitchString.java:4)Exception in thread "main" <a href="https://www.zym88.cn/tag/java" title="更多关于 java 的文章" target="_blank">java</a>.lang.NullPointerException at SwitchString.method(SwitchString.java:8) at SwitchString.main(SwitchString.java:4)Exception in thread "main" java.lang.NullPointerException at SwitchString.method(SwitchString.java:8) at SwitchString.main(SwitchString.java:4)
很奇怪,为啥会空指针呢? 你可能会说第8行param为空,所以空指针了。虽然这样理解也没问题。
我们要知道,NPE异常是代码中使用了这个对象的某些方法或者属性,而这个对象为空所以就会抛出异常。例如以下代码
public class TestNPE {private int id;public static void main(String[] args) {TestNPE testNPE = null;System.out.println(testNPE);System.out.println(testNPE.id);}}public class TestNPE { private int id; public static void main(String[] args) { TestNPE testNPE = null; System.out.println(testNPE); System.out.println(testNPE.id); } }public class TestNPE { private int id; public static void main(String[] args) { TestNPE testNPE = null; System.out.println(testNPE); System.out.println(testNPE.id); } }
我们点击运行可以得知。虽然testNPE这个对象为null,但是我们对其打印是没有问题的,但如果涉及到了对这个对象的某些方法或者属性的调用就会报错。
nullException in thread "main" java.lang.NullPointerExceptionat TestNPE.main(TestNPE.java:8)null Exception in thread "main" java.lang.NullPointerException at TestNPE.main(TestNPE.java:8)null Exception in thread "main" java.lang.NullPointerException at TestNPE.main(TestNPE.java:8)
而我们上面那个例子,它是在哪里使用了这个对象呢?
其实swtich是Java中的一个语法糖。
JDK7之前switch本身只支持基本类型,JDK7开始支持String。
Java中的switch自身原本就支持基本类型。比如int、char等。对于int类型,直接进行数值的比较。对于char类型则是比较其ascii码。所以,对于编译器来说,switch中其实只能使用整型,任何类型的比较都要转换成整型。比如byte。short,char(ackii码是整型)以及int。
我们将上面的代码进行反编译可以得到
public class SwitchString {public static void main(String[] args) {method((String)null);}public static void method(String param) {byte var2 = -1;switch(param.hashCode()) {case 114215:if(param.equals("sth")) {var2 = 0;}break;case 3392903:if(param.equals("null")) {var2 = 1;}}switch(var2) {case 0:System.out.println("it's sth");break;case 1:System.out.println("it's null");break;default:System.out.println("default");}}}public class SwitchString { public static void main(String[] args) { method((String)null); } public static void method(String param) { byte var2 = -1; switch(param.hashCode()) { case 114215: if(param.equals("sth")) { var2 = 0; } break; case 3392903: if(param.equals("null")) { var2 = 1; } } switch(var2) { case 0: System.out.println("it's sth"); break; case 1: System.out.println("it's null"); break; default: System.out.println("default"); } } }public class SwitchString { public static void main(String[] args) { method((String)null); } public static void method(String param) { byte var2 = -1; switch(param.hashCode()) { case 114215: if(param.equals("sth")) { var2 = 0; } break; case 3392903: if(param.equals("null")) { var2 = 1; } } switch(var2) { case 0: System.out.println("it's sth"); break; case 1: System.out.println("it's null"); break; default: System.out.println("default"); } } }
字符串的switch是通过equals()
和hashCode()
方法来实现的。由于调用了这两个方法,而param为null,所以出现了空指针异常。
外部参数
那么为啥还要是外部参数呢?其实很简单,我们把代码修改一下:
public class SwitchString {public static void main(String[] args) {switch (null) {// 肯定不是进入这里case "sth":System.out.println("it's sth");break;// 也不是进入这里case "null":System.out.println("it's null");break;// 也不是进入这里default:System.out.println("default");}}}public class SwitchString { public static void main(String[] args) { switch (null) { // 肯定不是进入这里 case "sth": System.out.println("it's sth"); break; // 也不是进入这里 case "null": System.out.println("it's null"); break; // 也不是进入这里 default: System.out.println("default"); } } }public class SwitchString { public static void main(String[] args) { switch (null) { // 肯定不是进入这里 case "sth": System.out.println("it's sth"); break; // 也不是进入这里 case "null": System.out.println("it's null"); break; // 也不是进入这里 default: System.out.println("default"); } } }
![图片[3]-为什么阿里建议对 switch 括号内的 String 变量进行判空?-明恒博客](https://www.zym88.cn/wp-content/uploads/2024/08/20240819081352708-2024081900135266-1024x563.png)
这样的代码是会报错提示的且编译是无法通过~~
总结
我们对switch这种情况进行了分析,得出了两个条件:
- switch括号内的变量类型为String。
- 此变量为外部参数时。
条件1是String类型的变量参数对象的判断是通过equals()
和hashCode()
方法来实现的。所以变量参数为null,调用这两个方法就会出现NPE。
条件2则是编译器会帮我们检查并且这是不符合语法的不能进行编译。
4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
5 本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报。
6 本站资源大多存储在云盘,如发现链接失效,请联系我们我们会第一时间更新。
暂无评论内容