调用泛型构造函数
这是不寻常的,但完全有效的Java。要理解,我们需要知道一个类可能有一个泛型构造函数,例如:
public class TypeWithGenericConstructor {
public <T> TypeWithGenericConstructor(T arg) {
// TODO Auto-generated constructor stub
}
}
我认为,在通过泛型构造函数实例化类时,我们通常不需要使类型参数显式化。例如:
new TypeWithGenericConstructor(LocalDate.now(ZoneId.systemDefault()));
现在显然是.但是,在某些情况下,Java 可能无法推断(推断)类型参数。然后,我们使用您的问题中的语法显式提供它:T
LocalDate
new <LocalDate>TypeWithGenericConstructor(null);
当然,我们也可以提供它,即使我们认为它有助于可读性或出于任何原因,这是不必要的:
new <LocalDate>TypeWithGenericConstructor(LocalDate.now(ZoneId.systemDefault()));
在你的问题中,你似乎在调用构造函数。该构造函数不是泛型的(只有整个类才是,这是别的什么)。有关为什么Java允许您在不使用时在调用中提供类型参数,请参阅下面的编辑。我的 Eclipse 给了我一个警告:java.util.ArrayList
ArrayList
ArrayList 类型的非泛型构造函数 ArrayList() 的未使用类型参数;它不应该用参数<字符串,长>
但这不是一个错误,程序运行良好(我另外收到有关缺少 和 的类型参数的警告,但这又是另一回事)。List
ArrayList
泛型类与泛型构造函数
类型参数的定位是否与将它们放在类型之后具有相同的含义?如果不是,不同的定位意味着什么?
不,这是不同的。类型 () 后面的常用类型参数用于泛型类。前面的类型参数用于构造函数。ArrayList<Integer>()
这两种形式也可以组合:
List<Integer> list = new <String, Long>ArrayList<Integer>();
我认为这更正确一些,因为我们现在可以看到列表存储对象(当然,我仍然宁愿省略无意义的对象)。Integer
<String, Long>
为什么当 ArrayList 只有 1 个类型参数时,有 2 个类型参数是合法的?
首先,如果在类型之前提供类型参数,则应为构造函数而不是类提供正确的数字,因此它与类已获得的类型参数数没有任何关系。这实际上意味着在这种情况下,您不应该提供任何东西,因为构造函数不采用类型参数(它不是泛型的)。当你提供一些时,它们会被忽略,这就是为什么你提供多少或多少并不重要。ArrayList
为什么允许无意义的类型参数?
感谢链接的@Slaw进行编辑:Java允许对所有方法调用使用类型参数。如果被调用的方法是泛型的,则使用类型参数;如果没有,它们将被忽略。例如:
int length = "My string".<List>length();
是的,这很荒谬。Java 语言规范 (JLS) 在小节 15.12.2.1 中给出了这个理由:
这一规则源于兼容性问题和可替代性原则。由于接口或超类可以独立于其子类型进行生成,因此我们可以用非泛型方法覆盖泛型方法。但是,重写(非泛型)方法必须适用于对泛型方法的调用,包括显式传递类型参数的调用。否则,子类型将无法替代其生成的超类型。
该参数不适用于构造函数,因为它们不能被直接覆盖。但我想他们希望有相同的规则,以免使已经复杂的规则过于复杂。无论如何,关于实例化的第 15.9.3 节以及不止一次地引用了 15.12.2。new
链接