Squ*_*vin 5 java generics variadic-functions superclass
例如,如果我有一个方法,使用类型的varargs扩展超类,如下所示:
public static <E extends Example> void test(Class<E>... es){}
Run Code Online (Sandbox Code Playgroud)
然后我尝试使用Example的两个不同的子类调用该方法,我只能在其中创建一个包含两个类的数组.
//this does not work
test(E1.class,E2.class);
//this does work
test(new Class[]{E1.class,E2.class});
public class E1 extends Example {}
public class E2 extends Example {}
Run Code Online (Sandbox Code Playgroud)
为什么是这样?
这行不编译:
test(E1.class,E2.class);
Run Code Online (Sandbox Code Playgroud)
只有一个类型参数E,Java必须完全匹配参数的推断类型.它不能推断Example,因为对象是Class<E1>和Class<E2>,不是Class<Example>.Java泛型的不变性可以防止这种情况发生.
您可以通过在test泛型类型参数上引入上限通配符来解决此问题:
public static <E extends Example> void test(Class<? extends E>... es)
Run Code Online (Sandbox Code Playgroud)
这允许Java推断Example为E,通过满足上限通配符E1和E2.
第二行创建一个原始的Classes 数组,绕过泛型并生成"未经检查的调用"警告.
new Class[]{E1.class,E2.class}
Run Code Online (Sandbox Code Playgroud)
如果你试图在Class这里提供一个类型参数,你将得到任何中间合理类型参数的编译器错误:
// Needs Class<Example> but found Class<E1> and Class<E2>
test(new Class<Example>[]{E1.class,E2.class});
// Needs Class<E1> but found Class<E2>
test(new Class<E1>[]{E1.class,E2.class});
// Needs Class<E2> but found Class<E1>
test(new Class<E2>[]{E1.class,E2.class});
Run Code Online (Sandbox Code Playgroud)
通过在这里使用通配符来满足推理只是揭示了这里的真正问题 - 通用数组创建.
// Generic array creation
test(new Class<? extends Example>[]{E1.class,E2.class});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1136 次 |
| 最近记录: |