如何对可能实现接口的对象正确调用带接口约束的泛型方法?
解决泛型方法
test的调用问题 没问题,咱们来搞定这个调用问题~首先得明白你原来的代码为什么报错:beeA.getClass()返回的是Class<? extends a>,而你的泛型方法test要求第一个参数是Class<T>(其中T extends a),编译器没法自动把通配符类型和T匹配起来,所以会抛出编译错误。
下面给你几种可行的实现方式,都能正确调用test方法:
方法一:强制类型转换+抑制警告
既然你已经通过instanceof确定了beeA是a的实例,那可以安全地把beeA.getClass()强制转换成Class<? extends a>,然后调用test。因为这种转换是unchecked的,需要加注解抑制警告:
if (bee instanceof a) { a beeA = (a) bee; @SuppressWarnings("unchecked") Class<? extends a> clazz = (Class<? extends a>) beeA.getClass(); test(clazz, beeA); }
或者直接在调用时内联转换:
if (bee instanceof a) { a beeA = (a) bee; @SuppressWarnings("unchecked") test((Class<? extends a>) beeA.getClass(), beeA); }
这种方式不用修改test方法的签名,只是需要处理一下编译器警告,这里的警告是安全的,因为我们已经做了类型检查。
方法二:修改test方法的参数类型
如果你可以调整test方法的定义,把第一个参数改成Class<? extends a>,这样就能直接调用,不用任何转换:
public void test(Class<? extends a> classType, a concrete) { }
这样做最简洁,但会去掉原来的泛型T约束,如果你的方法内部不需要依赖T的具体类型,这种方式最省心。
方法三:用辅助泛型方法捕获类型
可以写一个小型的辅助方法来帮编译器推断泛型类型,这样代码更优雅:
class e{ public void makeItWork(){ b[] bees = new b[] {new c(), new d()}; for (b bee: bees){ if (bee instanceof a) { callTest((a) bee); } } } @SuppressWarnings("unchecked") private <T extends a> void callTest(T instance) { test((Class<T>) instance.getClass(), instance); } public <T extends a> void test(Class<T> classType, T concrete){ } }
辅助方法callTest会捕获T的具体类型,编译器能正确推断,同样需要加注解抑制unchecked转换的警告,这里也是安全的。
以上几种方式都能满足你的需求,根据你的实际代码场景选择就行~
内容的提问来源于stack exchange,提问作者J. Doe
相关产品推荐
相关产品推荐

