简体   繁体   中英

Calling ungeneric methods from generic method in java

Consider the following:

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

Where B extends A

And a generic class like this:

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

If I call this method as follows it prints "a"

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

How do I get it to print "b" ?

Thanks in advance

Edit: A dirty solution is to change

Doer.doStuff(entity);

to

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

But I'm looking for a solution that does not use instanceof and so that I don't have to add an extra if (C intance of A) ... to NewClass when I make a new Class extending A

See these questions for answers: Java Generic / Type Dispatch Question , How does Java method dispatch work with Generics and abstract classes?

Basically, you have these options:

  • define doStuff as an abstract method on A
  • try the Visitor pattern
  • if possible, use a language (eg Xtend) that supports dynamic dispatch

Java doesn't do dynamic binding based on the argument type. The actual method that is invoked is determined at compile time. So in case of a generic type, the method with Object as the parameter type will be invoked.

You could work around this by checking the type with instanceof, but the puristic way of handling this is to leverage polymorphism and using Double Dispatch . But that is not always an option, since it tightly couples your calling class and your argument class together.

NewClass would have to have two methods also, or you could do something like this:

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);
        }
    }
}

I think that in that case you're forced to actually determine entity's type and cast it, as your function doSomething just infers that entity inherits from A. Basically you could do:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM