服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Java教程 - Java 中又一个你天天使用,但是不一定知道的知识点

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

2021-11-17 23:37Java极客技术鸭血粉丝Tang Java教程

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

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

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

  1. public static void testSwitch(String language) {
  2. switch (language) {
  3. case "C++":
  4. System.out.println("C++");
  5. break;
  6. case "Java":
  7. System.out.println("Java");
  8. break;
  9. case "Python":
  10. System.out.println("Python");
  11. default:
  12. System.out.println("default");
  13. break;
  14. }
  15. }

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

如果 language 为 null,即 testSwitch(null) 会输出什么?

swtich() 支持String 的原理是什么?

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

  1. 5
  2. 4
  3. 3
  4. 2
  5. 1

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

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

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

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

  1. //
  2. // Source code recreated from a .class file by IntelliJ IDEA
  3. // (powered by FernFlower decompiler)
  4. //
  5. package org.fenixsoft.clazz;
  6. public class SwitchTest {
  7. public SwitchTest() {
  8. }
  9. public static void main(String[] var0) {
  10. testSwitch((String)null);
  11. }
  12. public static void testSwitch(String var0) {
  13. byte var2 = -1;
  14. switch(var0.hashCode()) {
  15. case -1889329924:
  16. if (var0.equals("Python")) {
  17. var2 = 2;
  18. }
  19. break;
  20. case 65763:
  21. if (var0.equals("C++")) {
  22. var2 = 0;
  23. }
  24. break;
  25. case 2301506:
  26. if (var0.equals("Java")) {
  27. var2 = 1;
  28. }
  29. }
  30. switch(var2) {
  31. case 0:
  32. System.out.println("C++");
  33. break;
  34. case 1:
  35. System.out.println("Java");
  36. break;
  37. case 2:
  38. System.out.println("Python");
  39. default:
  40. System.out.println("default");
  41. }
  42. }
  43. }

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

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

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

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

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

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

  1. public static void main(String[] args) {
  2. testSwitch(null);
  3. System.out.println("C++".hashCode());
  4. System.out.println("Java".hashCode());
  5. System.out.println("Python".hashCode());
  6. }

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

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

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

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

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

总结一下今天阿粉带大家看了一个 Switch String 类型参数的实现原理,有些知识点在我们平时工作中虽然会经常用到,但是并不会深入去研究原理。

原文链接:https://mp.weixin.qq.com/s/WR4hUvGzMDApjQ7XN5qxaw

延伸 · 阅读

精彩推荐
  • Java教程20个非常实用的Java程序代码片段

    20个非常实用的Java程序代码片段

    这篇文章主要为大家分享了20个非常实用的Java程序片段,对java开发项目有所帮助,感兴趣的小伙伴们可以参考一下 ...

    lijiao5352020-04-06
  • Java教程Java BufferWriter写文件写不进去或缺失数据的解决

    Java BufferWriter写文件写不进去或缺失数据的解决

    这篇文章主要介绍了Java BufferWriter写文件写不进去或缺失数据的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望...

    spcoder14552021-10-18
  • Java教程升级IDEA后Lombok不能使用的解决方法

    升级IDEA后Lombok不能使用的解决方法

    最近看到提示IDEA提示升级,寻思已经有好久没有升过级了。升级完毕重启之后,突然发现好多错误,本文就来介绍一下如何解决,感兴趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java实现抢红包功能

    Java实现抢红包功能

    这篇文章主要为大家详细介绍了Java实现抢红包功能,采用多线程模拟多人同时抢红包,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙...

    littleschemer13532021-05-16
  • Java教程Java8中Stream使用的一个注意事项

    Java8中Stream使用的一个注意事项

    最近在工作中发现了对于集合操作转换的神器,java8新特性 stream,但在使用中遇到了一个非常重要的注意点,所以这篇文章主要给大家介绍了关于Java8中S...

    阿杜7482021-02-04
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    这篇文章主要介绍了Java使用SAX解析xml的示例,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程xml与Java对象的转换详解

    xml与Java对象的转换详解

    这篇文章主要介绍了xml与Java对象的转换详解的相关资料,需要的朋友可以参考下...

    Java教程网2942020-09-17
  • Java教程小米推送Java代码

    小米推送Java代码

    今天小编就为大家分享一篇关于小米推送Java代码,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧...

    富贵稳中求8032021-07-12