需要说明:java中的三元运算符

需要说明:java中的三元运算符,java,nullpointerexception,ternary-operator,Java,Nullpointerexception,Ternary Operator,有问题的行是return pFile.exists()?true:null。由于它不会引起任何编译错误,对此的解释是什么。它最终提高了NPE import java.io.File; public class Main { public static void main(String... args) { boolean accept = accept(new File("")); System.out.println("accept = " + accept); }

有问题的行是
return pFile.exists()?true:null。由于它不会引起任何编译错误,对此的解释是什么。它最终提高了NPE

import java.io.File;
public class Main {
  public static void main(String... args) {
    boolean accept = accept(new File(""));
    System.out.println("accept = " + accept);
  }
  public static boolean accept(File pFile) {
    System.out.println(pFile.exists()); // prints: false, so pFile is not null
    return pFile.exists() ? true : null; //this line should throw compilation error
  }
}

pFile
不是
null
;如您所见,
文件
被实例化。但显然文件不在那里。问题不是关于
pFile
。我感兴趣的是操作符如何处理
null

实际上,一个空字符串正被用来创建
文件。这将导致一个空的
抽象路径名
,没有前缀(或目录)和空名称序列。因此windows无法创建
文件
。这反过来会抛出一个
NPE

您从定义为返回
Boolean
的函数中返回
Boolean null
(一个基本类型;注意小
b
)。
null
值将自动取消绑定,并导致NPE。

您的代码相当于:

public static boolean accept(File pFile) {
    System.out.println(pFile.exists()); // prints: false, so pFile is not null
    Boolean tmp = pFile.exists() ? true : null;
    return (boolean) tmp;
}
换言之,在本例中,条件运算符的类型是
布尔
,然后该值被取消绑定以返回一个
布尔
。取消绑定
null
时,会出现异常

来自Java语言规范的以下部分:

否则,第二个和第三个操作数分别为S1和S2类型。设T1为将装箱转换应用于S1时产生的类型,设T2为将装箱转换应用于S2时产生的类型。条件表达式的类型是将捕获转换(§5.1.10)应用于lub(T1,T2)(§15.12.2.7)的结果


我相信这种情况在这里是适用的,尽管我承认它没有可能那么清楚。

为什么不直接返回
pFile.exists()
?将accept(File pFile)方法体替换为以下内容:
return(pFile==null)?false:pFile.exists()
或者不使用三元运算符,只需说
return(pFile!=null)&&pFile.exists()。请查看我的编辑。是的,我可以写
返回pFile.exists()
@Kowser:我刚刚意识到三元运算符的作用与只返回null不同,后者会在编译时给您一个不兼容的类型错误。你应该在问题中提到这一点。@styfle:我不知道:-S。这就是我不得不问的原因。所以它将表达式提升为键入
布尔值
,并将
空值
框起和取消框起。。。?只是糟糕。它转换
pFile.exists()的结果?true:使用自动取消装箱将null
(即
null
)转换为
布尔值
。自动取消装箱
null
会得到一个简洁的答案,这就是我一直在寻找的。@Jon,老实说,我发现你的答案是正确的,但过于冗长,不太切题。您引用了三元运算符规范,事实上,它与问题无关——这是一些表达式
pFile.exists()?true:null
@Piotr:但它依赖于该表达式的类型为
布尔值,然后将其取消装箱。因此,失败的不是条件运算符的执行,而是执行之后的转换步骤。我认为这是一个重要方面。@Jon,毫无疑问,条件(
?:
)运行顺利。这就是我的意思,一些
正在使用的事实并不重要。。。。无论如何,感谢您提供指向JLS的指针:)