从JDK7开始,可以简化用于创建泛型类型示例的语法.在我们继续讨论之前,先回想一下本章前面介绍的TwoGen类.下面显示了他的一部分代码以方便讨论.注意他使用了两个泛型类型.
class TwoGen<T,V> { T ob1; V ob2; TwoGen(T o1,V o2) { ob1 = o1; ob2 = o2; } }
在JDK7以前的Java版本中,要创建TwoGen的实例,必须使用如下所示的语句:
TwoGen<Integer,String> tgOb = new TwoGen<Integer,String>(42,"test");
这里两次指定了类型实参(即Integer和String):第一次在声明tgOb时,第二次是在通过new创建TwoGen的实例时.因为泛型是在JDK5中引入的,所以在JDK7之前的所有版本都必须使用这种形式.虽然这种形式本身没有错,但是却没有必要这么冗长.因为在new子句中,类型实参的类型很容易推断出来,所以没有必要第二次指定他们,为了应对这种情况,JDK7添加了一个语法元素,用于避免第二次指定.
从JDK7开始,可以把前面的声明重写为下面的形式:
TwoGen<Integer,String> tgOb = new TwoGen<>(42,"test");
注意该实例的创建部分简单的使用了<>,即一个空的类型实参列表.这被称作菱形运算符,他告诉编译器推断new表达式中的构造函数所需的类型实参.这种类型推断语法的优势是缩短了相当长的声明语句.对于指定约束的泛型类型,他特别有帮助.
可以把前面的示例加以推广,当使用类型推断时,泛型引用和示例创建的声明语法的基本形式如下:
class-name <type-arg-list> var-name = new class-name<>(cons-arg-list);
这里,new子句的类型实参列表是空的.
虽然类型推断主要用于声明语句中,但是也可以用于形参传递,例如,如果把下面的方法添加到TwoGen中:
boolea isSame(TwoGen<T,V> o ) { if(ob1 == o.ob1 && ob2 == o.ob2) return true; return false; }
那么下面的调用是合法的
if(tgOb.isSame(new TwoGen<>(42,"test"))) System.out.println("same");
在本例中,传递给isSame()的实参的类型可以从形参的类型推断出来,所以不需要再次指定.
因为菱形运算符是在JDK7中新引入的,在较早的编译器中不能工作.