Java中三目运算符之类型转换

文章目录

  • 1. 前言
  • 2. 三目运算符使用
  • 3. 类型转换
      • 3.1 尝试着分析一下
  • 4. 结论与思考
  • 5. 源码
  • 参考

1. 前言

相信各位 Javaer 对于三目运算符(三元运算符)都不陌生,较多情况下使用三目运算符即可节省一个 if-else 语句赋值的编写,笔者也是经常使用三目运算符,前段时间遇到了一点三目运算符的类型转换的坑,便在此记录一下。望更多的朋友能够避免,也加深我对三目运算符的理解。

2. 三目运算符使用

闲话不说,直接上代码。

/**
 * 三目运算符使用
 */
public void ternaryOperator() {
    boolean switchLog = true;
    // 基本类型
    int intValue = switchLog ? 1 : 0;
    // 引用类型
    String strValue = switchLog ? "true" : "false";
}

三目运算符可表达为:布尔表达式 ? 表达式1 : 表达式2

布尔表达式:其结果决定三目运算符的分支情况
表达式1:当布尔表达式为 true,则执行
表达式2:当布尔表达式为 false,则执行

3. 类型转换

在三目运算符的使用过程中,即支持基本类型,也支持引用类型。值得注意的一点是,引用类型为 null 时,也是支持给引用类型赋值的。

特别的,我们关注到了基本类型和其封装类型,于是有了下述代码。

@Test
public void intInteger() {
    boolean switchLog = true;
    Integer oneExpre = null
    Integer result = switchLog ? oneExpre : 0;
    System.out.println(result);
}

猜想下这个程序的 result 返回什么,是 null 么?为什么?

试着运行下测试,发现得到以下报错:

java.lang.NullPointerException
	at club.chenlinghong.demo.ternaryoperator.TernaryOperatorDemo.intInteger(TernaryOperatorDemo.java:28)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
	at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
	at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
	at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
	at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
	at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
	at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
	at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
	at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
	at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
	at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
	at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
	at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70

NPE,有意思,命名没有任何问题呀,就算是 switchLog 为 true 嘛,也就把 null 值赋给 result 嘛,这不科学。

我们再来尝试下另外一种写法:

@Test
public void intInteger() {
    boolean switchLog = true;
    Integer oneExpre = null;
    Integer result = switchLog ? oneExpre : new Integer(0);
    System.out.println(result);
}

再次执行,居然没报错。result 为 null。

Java中三目运算符之类型转换_第1张图片

3.1 尝试着分析一下

报错的情况:

这种情况下,“表达式1” 结果是 null,而“ 表达式2 ” 是基本类型。大胆猜想一下,当执行时,先执行 “表达式1” 的得到返回结果 null ,此时 null 是一个特殊的值,并不知道其“具体的类型”,然后尝试着和 “表达式2” 进行统一类型,发现 “表达式2” 是 int 类型,并进行强转或者封装类型转基本类型,报NPE。

未报错的情况:

和报错情况不同的是,“表达式2”本身就是 Integer 类型,封装类型本身支持 null 类型赋值,便省去了类型强转的步骤,则不报错。

4. 结论与思考

这是一个有趣的实验,同时也是一个很坑的点。对于这些细枝末节的知识点(坑点),可能在平时学习和编码中都很少遇到,但是在遇到的时候,可能需要查很久很久的代码才能找到。

注重知识点的累计,多一次在学习中踩坑,就少一次在生产上的事故,哈哈哈哈哈 ~ _ ~

5. 源码

Github链接,欢迎star,follow。

demo-springboot

参考

关于三元运算符的类型转换问题

你可能感兴趣的:(Java,Java,Engineer)