var test = "Hello World!";
在Java 10+中,上面的代码片段编译,并且test
在编译时被推断为String
。
但是,我们可以使用条件(三元)运算符返回不同的类型,例如:
var test = new Random().nextBoolean() ? "Hello World!" : 123;
如果我们要在运行时打印test.getClass()
,它会输出:
- class java.lang.String
- class java.lang.Integer
这是有道理的,但test
的类型在编译时会是什么?它会是Object
,还是其他什么?
有趣的是,Intellij告诉我,test
的类型不是Object
,而是这个野兽:
java.io.Serializable & Comparable<? extends java.io.Serializable & Comparable<?> & constant.Constable & constant.ConstantDesc> & constant.Constable & constant.ConstantDesc
这种情况的原因是因为编译器推断变量的类型是String
和Integer
之间最接近的公共超类,它们实际上是Java 12中的Serializable
,Comparable
,Constable
和ConstantDesc
。
有一篇有趣的文章详细阐述了不可能的类型,这些类型被称为(因为它们只能由编译器推断):Representing the Impractical and Impossible with JDK 10 “var”
如果我们要返回完全不相关的对象,例如Integer
和ByteArrayOutputStream
,那么我们会看到Java会将test
的编译时类型推断为Object
:
var test = new Random().nextBoolean() ? 123 : new ByteArrayOutputStream();