当前位置: 首页 > 科技观察

Java中又一个你天天用但不一定知道的知识点

时间:2023-03-11 21:43:40 科技观察

大家都知道我们在做条件判断的时候除了if-else之外还可以用switch,而且在JDK7之后也加入了String类型的支持进行切换,如下代码所示。publicstaticvoidtestSwitch(Stringlanguage){switch(language){case"C++":System.out.println("C++");break;case"Java":System.out.println("Java");break;case"Python":System.out.println("Python");default:System.out.println("default");break;}}如果不知道有朋友会这么用,那今天你就知道了,不过相信大家都知道这个功能,不过阿芬在这里提出两个问题,看你有没有聪明的回答一下。如果language为null,testSwitch(null)会输出什么?swtich()支持String的原理是什么?当你看到这个时,请停下来思考五秒钟。54321好了,我们来看上面两道题。首先,如果你回答问题1,你会输出default,那阿粉会告诉你,这是错误的。不信,我们来实践一下。毕竟,实践是检验真理的唯一标准。从上面的输出我们可以看到报了一个空指针异常。看到这里有些朋友可能会一头雾水。上面的代码看起来没什么特别的。如果传入null,则应该转到默认分支。为什么会报空指针?如果您有这个问题,请不要担心。看完第二个问题的答案就知道为什么了。同样,要搞清楚问题1的答案为什么是空指针,我们需要知道Stringinswitch背后的原理是什么。现在我们来看第二个问题。首先,我们通过javac编译这段代码,执行命令:javacSwitchTest.java,我们可以得到编译后的SwitchTest.class文件,然后通过反编译可以得到如下内容,这里反编译可以直接将class文件拖入即可这个想法。////Sourcecoderecreatedfroma.classfilebyIntelliJIDEA//(poweredbyFernFlowerdecompiler)//packageorg.fenixsoft.clazz;publicclassSwitchTest{publicSwitchTest(){}publicstaticvoidmain(String[]var0){testSwitch((String)null);}publicstaticvoidtestSwitch(Stringvar0){bytevar2=-1;switch(var0.hashCode()){case-1889329924:if(var0.equals("Python")){var2=2;}break;case65763:if(var0.equals("C++")){var2=0;}break;case2301506:if(var0.equals("Java")){var2=1;}}switch(var2){case0:System.out.println("C++");break;case1:System.out.println("Java");break;case2:System.out.println("Python");default:System.out.println("default");}}}到这里相信大家就知道为什么了,显然,Switch支持String的底层原理是利用String的hashcode和equals方法。通过获取输入字符串的哈希码来确定进入哪个分支。大家都知道hasecode的返回值是int类型,所以即使输入的参数类型是字符串,底层还是用整型来判断。而到这里,大家也知道为什么问题1的答案是会出现空指针了,因为这里调用hasecode的时候,很明显会出现空指针异常。这就告诉我们,在使用switch字符串的时候,必须对入参进行非NULL检查,这在阿里巴巴的手册中也有明确的强制要求。同时,通过上面的反编译代码,我们也可以看出参数String是区分大小写的,因为使用equals进行判断,所以我们也要注意字符串的大小写,以免出现问题。为了验证是否真的使用了hashcode,我们可以输出上面代码中涉及到几个字符串的hashcode来进行验证。publicstaticvoidmain(String[]args){testSwitch(null);System.out.println("C++".hashCode());System.out.println("Java".hashCode());System.out.println("Python".hashCode());}可以看到输出的hashcode和反编译后的hashcode是一致的。看到这里的小伙伴们,再延伸一下吧。由于hashcode是在编译时生成的,也就是说我们不能传入一个动态生成的字符串,即下面的写法是不会通过编译的。虽然看起来是字符串,但是很明显这种形式是不行的,因为编译时没有办法得到hasecode,自然不可能写出这些。相信小伙伴们之前在写代码的时候也遇到过问题。我也遇到过这种情况,但当时我可能不知道为什么,我只知道定义一个常量或者字符串字面量,相信看完这篇文章你就知道为什么了。综上所述,今天阿粉就带大家看看一个SwitchString类型参数的实现原理。虽然有些知识点在日常工作中经常会用到,但是我们不会深入研究其中的原理。