Java Generic / Type Dispatch Question

考虑以下程序:

import java.util.List; import java.util.ArrayList; public class TypeTest { public static class TypeTestA extends TypeTest { } public static class TypeTestB extends TypeTest { } public static final class Printer { public void print(TypeTest t) { System.out.println("T"); } public void print(TypeTestA t) { System.out.println("A"); } public void print(TypeTestB t) { System.out.println("B"); } public  void print(List t) { for (T tt : t) { print(normalize(tt.getClass(), tt)); } } private static  T normalize(Class clz, Object o) { return clz.cast(o); } } public static void main(String[] args) { Printer printer = new Printer(); TypeTest t1 = new TypeTest(); printer.print(t1); TypeTestA t2 = new TypeTestA(); printer.print(t2); TypeTestB t3 = new TypeTestB(); printer.print(t3); System.out.println("...................."); List tb1 = new ArrayList(); tb1.add(t3); printer.print(tb1); } } 

主要方法现在打印:

 TAB .................... T 

我该怎么做才能打印出以下内容?

 TAB .................... B 

我想避免为每种可打印的类型编写如下的循环:

  public void printTypeTestB(List t) { for (TypeTestB tt : t) { print(tt); } } 

您的问题的根源是Java方法重载在编译时根据方法参数表达式的声明类型进行解析。 您的程序似乎试图将运行时调度用于不同的方法重载。 这根本不适用于Java。

你在你的例子中使用generics的事实是一个红色的鲱鱼。 如果用TypeTest替换类型参数TypeTest同样的问题。

Concider创建一个知道所有相关子类型的访问者界面。

 public class TypeTestFoo { interface TypeTestVisitor { void visit(TypeTestA t); void visit(TypeTestB t); void visit(TypeTest t); } interface TypeTest { void accept(TypeTestVisitor visitor); } public static class TypeTestA implements TypeTest { public void accept(TypeTestVisitor visitor) { visitor.visit(this); } } public static class TypeTestB implements TypeTest { public void accept(TypeTestVisitor visitor) { visitor.visit(this); } } public static final class Printer implements TypeTestVisitor { public void visit(TypeTestA t) { System.out.println("A"); } public void visit(TypeTestB t) { System.out.println("B"); } public void visit(TypeTest t) { System.out.println("T"); } } public static void main(String[] args) { Printer printer = new Printer(); TypeTest t1 = new TypeTest() { public void accept(TypeTestVisitor visitor) { visitor.visit(this); }}; t1.accept(printer); TypeTestA t2 = new TypeTestA(); t2.accept(printer); TypeTestB t3 = new TypeTestB(); t3.accept(printer); System.out.println("...................."); List tb1 = new ArrayList(); tb1.add(t3); for (TypeTestB each : tb1) { each.accept(printer); } } 

}

这应该打印出你想要的东西:

 T A B .................... B 

接口中列出了允许编译时重载的类型。 另一方面,这是一个单点,您已经放置了您不想参数化行为的子类型。 Java不是一个非常动态的语言…… 🙂

复杂的“访客模式”的候选人。

或者只是将print()方法从Printer移动到TypeTest