在Java规范(http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.9)中,new具有以下形式:
ClassInstanceCreationExpression ::=
| new TypeArguments_opt TypeDeclSpecifier TypeArgumentsOrDiamond_opt
( ArgumentListopt ) ClassBodyopt
| Primary . new TypeArguments_opt Identifier TypeArgumentsOrDiamond_opt
( ArgumentListopt ) ClassBodyopt
新的第一个可选类型参数列表的目的是什么?我无法从我对15.9节的阅读中找到它(对类型参数列表的所有引用似乎都引用了类型/标识符之后的列表)。测试标准Java编译器上的随机位会产生令人困惑的结果:
public class Foo<T> { }
// ...
Foo<Integer> t1 = new <Integer> Foo<Integer>(); // works
Foo<Integer> t2 = new <Integer> Foo(); // works -- unchecked warning missing the type arg after Foo
Foo<Integer> t3 = new <Boolean> Foo<Integer>(); // works
Foo<Integer> t4 = new <Float, Boolean> Foo<Integer>(); // works
Foo<Integer> t5 = new <NotDefined> Foo<Integer>(); // fails -- NotDefined is undefined
在这些简单的例子中,虽然它解析并检查其参数的有效性,但似乎第一个参数列表没有任何意义。
答案 0 :(得分:13)
构造函数也可以声明类型参数
public class Main {
public static class Foo<T> {
public <E> Foo(T object, E object2) {
}
}
public static void main(String[] args) throws Exception {
Foo<Integer> foo = new <String> Foo<Integer>(1, "hello");
}
}
这就是构造函数调用之前的<String>
。它是构造函数的类型参数。
以下
Foo<Integer> foo = new <String> Foo<Integer>(1, new Object());
失败
类型的参数化构造函数Foo(Integer,String) Main.Foo不适用于参数(整数, 对象)
在你的上一次
Foo<Integer> t5 = new <NotDefined> Foo<Integer>(); // fails -- NotDefined is undefined
NotDefined
不是编译期间找到的类型。如果是,它只会给你一个警告:unused
。
答案 1 :(得分:3)
你可以为方法调用添加无用的类型参数,像
这样奇怪的东西Math.<Runnable>max(1,2);
System.out.<Button>println();
请参阅http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.12.2.1-200-E
非泛型方法可能适用于提供显式类型参数的调用。实际上,它可能会变得适用。在这种情况下,类型参数将被忽略。
此规则源于兼容性和可替代性原则的问题。由于接口或超类可以独立于其子类型进行泛化,因此我们可以使用非泛型方法覆盖泛型方法。但是,重写(非泛型)方法必须适用于对泛型方法的调用,包括显式传递类型参数的调用。否则,子类型不能替代其生成的超类型。