0
点赞
收藏
分享

微信扫一扫

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

hoohack 2022-02-14 阅读 44


大家都知道当我们在进行条件判断的时候除了可以使用 ​​if-else​​​ 之外,还可以是用 ​​switch​​​,而且在 ​​JDK 7​​​ 之后在 ​​switch​​​ 中还增加了 ​​String​​ 类型的支持,如下代码所示。

public static void testSwitch(String language) {
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;
}
}

如果还不知道可以这样用的小伙伴,那你今天知道了,不过阿粉相信小伙伴都知道这个特性,但是这里阿粉提两个问题,看看聪明的你能不能答出来。


  1. 如果 ​​language​​​ 为 ​​null​​​,即 ​​testSwitch(null)​​ 会输出什么?
  2. ​swtich()​​​ 支持​​String​​ 的原理是什么?

看到这里请停下来,思考五秒钟

5

4

3

2

1

好,我们来看下上面两个问题,首先如果对于问题一你要是回答会输出​​default​​ 那么阿粉告诉你,这是错误的。不信的话,我们实践一下,毕竟实践是检验真理的唯一标准。

Java 中 又一个你天天使用,但是不一定知道的知识点_c++

从上面的输出我们可以看到,已经报了空指针的异常了,到这里可能有些小伙伴就疑惑了,上面的代码看起来没什么特别的啊,​​null​​​ 传进去应该走到 ​​default​​ 分支才对啊,为什么会报空指针呢?有这个疑问的小伙伴也不要捉急,看完第二个问题的答案,你就知道为什么了。

同样的要搞清楚为什么问题一的答案是空指针,我们就需要知道 ​​switch​​​ 中支持 ​​String​​​ 的原理是什么。下面我们来看看第二个问题。首先我们将这个代码通过 ​​Javac​​​ 编译一下,执行命令:​​javac SwitchTest.java​​​,我们就可以得到编译后的 ​​SwitchTest.class​​​ 文件,再通过反编译我们可以得到下面的内容,这里反编译可以直接将 ​​class​​​ 文件拖进 ​​idea​​ 中即可。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package org.fenixsoft.clazz;
public class SwitchTest {
public SwitchTest() {
}
public static void main(String[] var0) {
testSwitch((String)null);
}
public static void testSwitch(String var0) {
byte var2 = -1;
switch(var0.hashCode()) {
case -1889329924:
if (var0.equals("Python")) {
var2 = 2;
}
break;
case 65763:
if (var0.equals("C++")) {
var2 = 0;
}
break;
case 2301506:
if (var0.equals("Java")) {
var2 = 1;
}
}
switch(var2) {
case 0:
System.out.println("C++");
break;
case 1:
System.out.println("Java");
break;
case 2:
System.out.println("Python");
default:
System.out.println("default");
}
}
}

到这里相信大家就知道为什么了,很显然 ​​Switch​​​ 支持 ​​String​​​ 底层的原理是使用了 ​​String​​​ 的 ​​hasecode​​​ 和 ​​equals​​​ 方法。通过得到入参字符串的 ​​hasecode​​​ 来决定进入哪个分支。大家都知道 ​​hasecode​​​ 的返回值是 ​​int​​ 类型,所以说即使传入的参数类型的字符串,底层还是使用的整型来进行判断的。

而且到这里,大家也知道了为什么问题一的答案是会出现空指针了,因为这里在调用 ​​hasecode​​ 的时候,很明显会出现空指针异常

这就告诉我们在进行 ​​switch string​​​ 的使用的时候,一定要进行入参的非 ​​NULL​​ 校验,这一点在阿里巴巴的手册中也有明确的强制要求。

Java 中 又一个你天天使用,但是不一定知道的知识点_字符串_02

公众号回复【Java】获取阿里巴巴 Java 开发手册——华山版。

同时通过上面反编译后的代码,我们也可以看到,参数 ​​String​​​ 是区分大小写的,因为里面使用了 ​​equals​​ 进行判断,所以我们也要注意字符串的大小写,避免出现问题。

为了验证是真的是采用 ​​hasecode​​​ ,我们可以将上面代码中涉及到了几个字符串的 ​​hasecode​​ 输出出来验证一下。

public static void main(String[] args) {
// testSwitch(null);
System.out.println("C++".hashCode());
System.out.println("Java".hashCode());
System.out.println("Python".hashCode());
}

Java 中 又一个你天天使用,但是不一定知道的知识点_c++_03

可以看到输出的 ​​hasecode​​ 和反编译后的 ​​hasecode​​ 是一致的。

看到这里的小伙伴我们再延伸一下,既然这里是在编译时期就生成了 ​​hasecode​​ ,那说明我们不能传入一个动态生成的字符串,也就是下面的写法会无法通过编译。

Java 中 又一个你天天使用,但是不一定知道的知识点_字符串_04

虽然看上去都是一个字符串,但是明显这种形式是不行的,因为没办法在编译的时候就获得 ​​hasecode​​,自然也就不可以这些写了,相信小伙伴们在之前写代码的时候也遇到过这种情况,但是当时可能并不知道是为什么,只知道要定义个常量或者字符串字面量,相信看完这篇文章的你,就知道是为什么了。

总结一下今天阿粉带大家看了一个 Switch String 类型参数的实现原理,有些知识点在我们平时工作中虽然会经常用到,但是并不会深入去研究原理,相信通过今天阿粉的这篇文章,会对大家有所帮助,如果觉得文章有帮助的话,请大家点赞,分享,评论,在看,不要怕被其他小伙伴看到,更多优质的原创文章欢迎关注我们 Java 极客技术。


号外!号外!

Java 极客技术微信群中有很多优秀的小伙伴在讨论技术,偶尔还有不定期的资料分享和红包发放!如果你想提升自己,并且想和优秀的人一起进步,请添加下方微信,阿粉会迅速拉你进群。


举报

相关推荐

0 条评论