从java中的泛型方法调用非泛型方法

时间:2013-07-26 08:50:56

标签: java generics downcast

请考虑以下事项:

public class Doer {
   public static void doStuff(A a) {
       System.out.println("a");
   }
   public static void doStuff(B b) {
    System.out.println("b");
   }
}

B延伸A

这样的通用类:

public class NewClass<T extends A> {
    public void doSomething(T entity) {
        Doer.doStuff(entity);
    }
}

如果我按如下方式调用此方法,则会打印“a”

new NewClass<B>().doSomething(new B());

如何打印“b”?

提前致谢

编辑:一个肮脏的解决方案是改变

Doer.doStuff(entity);

if(entity instanceof B){
    Doer.doStuff((B) entity);
}else {
    Doer.doStuff(entity);
}

但是我正在寻找一种不使用instanceof的解决方案,因此当我创建一个新的类扩展A时,我不需要为NewClass添加额外的if(C intance of A)...

4 个答案:

答案 0 :(得分:2)

请参阅以下问题以获取答案:Java Generic / Type Dispatch QuestionHow does Java method dispatch work with Generics and abstract classes?

基本上,您有以下选择:

  • doStuff定义为A
  • 上的抽象方法
  • 尝试访客模式
  • 如果可能,请使用支持dynamic dispatch
  • 的语言(例如Xtend)

答案 1 :(得分:1)

Java不根据参数类型进行动态绑定。调用的实际方法是在编译时确定的。因此,在泛型类型的情况下,将调用Object作为参数类型的方法。

您可以通过使用instanceof检查类型来解决此问题,但处理此问题的纯粹方法是利用多态并使用Double Dispatch。但这并不总是一种选择,因为它将你的调用类和你的参数类紧密地结合在一起。

答案 2 :(得分:0)

NewClass也必须有两种方法,或者你可以这样做:

public class NewClass<T extends A> {
    public void doSomething(T entity) {
        if(entity instanceof B){
            Doer.doStuff((B)entity);
        }else if(entity instanceof A){
            Doer.doStuff((A)entity);
        }
    }
}

答案 3 :(得分:0)

我认为在这种情况下,您被迫实际确定实体的类型并将其强制转换,因为您的函数doSomething只是推断实体继承自A. 基本上你可以这样做:

public void doSomething(T entity) {
    if (entity instanceof B) {
        Doer.doStuff((B) entity);
    }
    else {
        Doer.doStuff(entity);
    }
}