2015-04-22 2 views
4

Имея следующий пример:Как я могу назвать наиболее специфический метод с помощью дженериков?

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

} 

Я не понимаю, почему m2(Object o) выбран вместо m2(A a). Как вы можете видеть, когда вызывается m2(t), t «является A».

Выход:

  • фактической

    O 
    
  • ожидается

    A 
    

Как я могу использовать генерики ситуации выше, так т шляпа m2(A a) выбрано?


Edit:

Я хотел бы иметь общее решение, которое будет работать, даже если добавить тип B (по аналогии с 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"); 
} 
... 

Выход:

  • фактической

    O 
    O 
    
  • ожидается

    A 
    B 
    
+3

Слово, которое вы ищете, [ «стиранием»] (https://docs.oracle.com /javase/tutorial/java/generics/erasure.html). – Tom

+0

Java generics не являются шаблонами. То, что вы просите в редактировании, невозможно. – Radiodef

ответ

4

Вы должны сделать:

public static <T extends A> void m1(T t) { 
    m2(t); 
} 

В противном случае компилятор не может сделать вывод, что передаваемый параметр соответствует m2(A a) и киркой m2(Object o) вместо этого.

+0

Это исправляет конкретную проблему, но я ищу более общее решение, которое позволяет мне добавить 'B' (аналогично' A'), который не расширяет 'A'. Я отредактирую свой вопрос. Это частично решает проблему. Спасибо! –

3

Вы ищете double dispatch, который Java не поддерживает. Я не думаю, что дженерики могут помочь здесь, но это visitor design pattern, с которой вы можете эмулировать:

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()); 
    } 
} 
Смежные вопросы