Having the following example:
public class Test {
public static class A {}
public static void main(String[] args) {
A a = new A();
m1(a);
}
public static <T> void m1(T t) {
// t.getClass().getSimpleName() is A
// t instanceof A is true
m2(t);
}
/* Not called */
public static void m2(A a) {
System.out.println("A");
}
public static void m2(Object o) {
// o.getClass().getSimpleName() is A
// o instanceof A is true
System.out.println("O");
}
}
I don't understand why m2(Object o) is chosen instead of m2(A a). As you can see, when m2(t) is called, t "is an A".
Output:
actual
O
expected
A
How can I use generics for the situation above so that m2(A a) is chosen?
Edit:
I'd like to have a general solution that will work even if I add a type B (similar to A).
...
public static void main(String[] args) {
A a = new A();
m1(a);
B b = new B();
m1(b);
}
...
public static void m2(B b) {
System.out.println("B");
}
...
Output:
actual
O
O
expected
A
B
You have to do:
public static <T extends A> void m1(T t) {
m2(t);
}
Otherwise the compiler cannot infer that the passed parameter is compliant with m2(A a) and with pick m2(Object o) instead.
You are looking for double dispatch which Java does not support. I do not think that generics can help here, but there's the visitor design pattern with which you can emulate it:
public class Test {
public static interface Visitable {
void accept(Visitor visitor);
}
public static class A implements Visitable {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public static class B implements Visitable {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
public static interface Visitor {
void visit(A a);
void visit(B b);
}
public static class PrintingVisitor implements Visitor {
@Override
public void visit(A a) {
System.out.println("A");
}
@Override
public void visit(B b) {
System.out.println("B");
}
}
public static void main(String[] args) {
Visitable visitable = new A();
m(visitable);
visitable = new B();
m(visitable);
}
public static void m(Visitable visitable) {
visitable.accept(new PrintingVisitor());
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With