我知道当我读到这个答案时,我会发现我忽略了一些在我眼前的东西.但我花了最后30分钟试图弄清楚自己没有结果.
所以,我在Java 6中编写了一个程序,并发现了一些(对我来说)奇怪的功能.为了尝试隔离它,我做了两个小例子.我首先尝试了以下方法:
private static int foo()
{
return null;
}
Run Code Online (Sandbox Code Playgroud)
并且编译器拒绝它:类型不匹配:无法从null转换为int.
这对我很好,它尊重我熟悉的Java语义.然后我尝试了以下内容:
private static Integer foo(int x)
{
if (x < 0)
{
return null;
}
else
{
return new Integer(x);
}
}
private static int bar(int x)
{
Integer y = foo(x);
return y == null ? null : y.intValue();
}
private static void runTest()
{
for (int index = 2; index > -2; index--)
{
System.out.println("bar(" + index + ") = " + bar(index));
}
}
Run Code Online (Sandbox Code Playgroud)
编译没有错误!但是,在我看来,行中应该存在类型转换错误
return y == null ? null : y.intValue();
Run Code Online (Sandbox Code Playgroud)
如果我运行程序,我得到以下输出:
bar(2) = 2
bar(1) = 1
bar(0) = 0
Exception in thread "main" java.lang.NullPointerException
at Test.bar(Test.java:23)
at Test.runTest(Test.java:30)
at Test.main(Test.java:36)
Run Code Online (Sandbox Code Playgroud)
你能解释一下这种行为吗?
更新
非常感谢您提供的许多澄清答案.我有点担心,因为这个例子不符合我的直觉.令我不安的一件事是null被转换为int并且我想知道结果会是什么:0喜欢在C++中?那会很奇怪.很好,在运行时无法进行转换(空指针异常).
Jes*_*per 61
我们来看看这一行:
return y == null ? null : y.intValue();
Run Code Online (Sandbox Code Playgroud)
在? :声明中,两者:必须具有相同的类型.在这种情况下,Java将使其具有类型Integer.一种Integer可能是null,所以左侧是确定的.表达式y.intValue()是类型的int,但是Java会自动将其设置为Integer(注意,您也可以编写y一个可以保存此autobox的文件).
现在,结果必须再次取消装箱int,因为方法的返回类型是int.如果你打开Integer那个null,你会得到一个NullPointerException.
注意:Java语言规范的第15.25段解释了关于? :条件运算符的类型转换的确切规则.
mic*_*lak 17
Guava有一个非常优雅的解决方案MoreObjects.firstNonNull:
Integer someNullInt = null;
int myInt = MoreObjects.firstNonNull(someNullInt, 0);
Run Code Online (Sandbox Code Playgroud)
返回类型的类型由Java在这里推断.那就是问题..
http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.25
这是实际问题 -
如果第二个和第三个操作数之一是null类型而另一个操作数的类型是引用类型,则条件表达式的类型是该引用类型.
所以,基本上编译器会将条件表达式的返回类型推断为Integer,这就是为什么它允许您成功编译.
编辑:请参阅评论中的规则
如果您的项目中没有Guava,但已经使用了Apache Commons,则可以将Apache Lang3与其ObjectUtils类一起使用.
用法与番石榴基本相同:
Integer number = null;
int notNull = ObjectUtils.firstNonNull(number, 0);
Run Code Online (Sandbox Code Playgroud)
请注意,Guava库中的此方法比Apache中的方法更快.这是我刚在笔记本电脑(Core i7-7500U 2.7 GHz),Oracle Java 8,多次运行,JVM预热,结果平均的简短比较:
??????????????????????????????????????????????
? Library/Runs ? 1000 ? 1mln ? 100mln ? 1bln ?
??????????????????????????????????????????????
? Apache ? 1 ? 30 ? 782 ? 9981 ?
? Guava ? 1 ? 22 ? 120 ? 828 ?
??????????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)
结果以毫秒为单位.我不认为你经常需要运行这种方法数十亿次,但是,进行性能比较总是好的