考虑以下计划:
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 <T extends TypeTest> void print(List<T> t) {
for (T tt : t) {
print(normalize(tt.getClass(), tt));
}
}
private static <T> T normalize(Class<T> 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<TypeTestB> tb1 = new ArrayList<TypeTestB>();
tb1.add(t3);
printer.print(tb1);
}
}
主要方法现在打印:
T
A
B
....................
T
如何打印以下内容?
T
A
B
....................
B
我想避免为每种可以打印的类型编写如下的循环:
public void printTypeTestB(List<TypeTestB> t) {
for (TypeTestB tt : t) {
print(tt);
}
}
答案 0 :(得分:5)
问题的根源是Java方法重载在编译时根据方法参数表达式的声明类型得到解决。您的程序似乎试图使用运行时调度到不同的方法重载。这根本不适用于Java。
你在你的例子中使用泛型的事实是一个红色的鲱鱼。如果您将类型参数<T>
替换为TypeTest
,则会遇到同样的问题。
答案 1 :(得分:2)
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<TypeTestB> tb1 = new ArrayList<TypeTestB>();
tb1.add(t3);
for (TypeTestB each : tb1) {
each.accept(printer);
}
}
}
这应该打印出你想要的东西:
T
A
B
....................
B
接口中列出了允许编译时重载的类型。另一方面,这是一个单点,您已经放置了您不想参数化行为的子类型。 Java不是一种非常动态的语言...... :)
答案 2 :(得分:0)
复杂的“访客模式”的候选人。
或简单地将print()方法从Printer
移至TypeTest