Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I call the most specific method using generics?

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
    
like image 431
ROMANIA_engineer Avatar asked Dec 02 '25 06:12

ROMANIA_engineer


2 Answers

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.

like image 89
Konstantin Yovkov Avatar answered Dec 03 '25 22:12

Konstantin Yovkov


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());
    }
}
like image 35
xehpuk Avatar answered Dec 03 '25 21:12

xehpuk



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!