Java 11泛型类构造器重载调用逻辑疑问咨询
Java泛型构造器重载疑问解析
定义的泛型类
class CardboardContainer<T> { T myField; CardboardContainer(T myField) { System.out.println("In T constructor"); this.myField = myField; } <T extends Number> CardboardContainer(T myField) { System.out.println("In T2 constructor"); // this.myField = myField; } }
实例化操作
CardboardContainer<String> n1 = new CardboardContainer<String>("Hello"); // 调用T构造器 CardboardContainer<String> n2 = new CardboardContainer<String>(3); // 调用T2构造器 CardboardContainer<Integer> n22 = new CardboardContainer<Integer>(3); // 调用T构造器 CardboardContainer<String> n3 = new <Integer>CardboardContainer<String>(3); // 调用T2构造器
疑问解答
1. 为什么n1会调用第一个构造器而非第二个?
第一个构造器的参数类型是类的泛型T,这里实例化时T被指定为String,传入的"Hello"是String类型,完全匹配第一个构造器的参数要求。而第二个构造器的泛型T是构造器自身的泛型(和类的泛型T重名但属于不同作用域),它要求参数必须是Number的子类,String不满足这个约束,因此编译器只能选择第一个构造器。
2. 将类型从String改为Integer后,n22为何调用第一个构造器?n2与n22的构造器选择由什么决定?
- 对于
n22:实例化时类的泛型T是Integer,第一个构造器的参数类型就是Integer,传入的3自动装箱为Integer,完全匹配第一个构造器的参数;而第二个构造器虽然也接受Integer(因为Integer extends Number),但编译器会优先选择参数类型与类泛型完全匹配的构造器,而非带有额外泛型约束的构造器,所以最终调用第一个。 - 对于
n2:类的泛型T是String,第一个构造器需要String类型参数,但传入的3是Integer,无法匹配第一个构造器;此时编译器会寻找其他匹配的构造器,第二个构造器的泛型可以绑定为Integer,满足extends Number的约束,参数类型匹配,因此调用第二个构造器。
核心逻辑是:优先匹配参数类型与类泛型一致的构造器,若不匹配,再检查是否符合带额外泛型约束的构造器的参数要求。
3. 我原本认为n3会调用第一个构造器,为何实际调用了第二个?
new <Integer>CardboardContainer<String>(3)中的<Integer>是显式指定了构造器自身的泛型参数,这会强制编译器使用第二个带<T extends Number>泛型约束的构造器。即便你期望使用类泛型String对应的第一个构造器,但显式指定构造器泛型的操作,直接告诉编译器要调用带有该泛型约束的构造器,因此最终调用第二个。
内容的提问来源于stack exchange,提问作者summerisbetterthanwinter
相关产品推荐
相关产品推荐

