未能为从泛型方法调用的方法选择正确的重载
Failure to choose a right overload for method called from a generic method
我有以下代码:
class A{}
class B{}
class StuffDoer {
public void doStuff(A a) { System.out.println("A"); }
public void doStuff(B b) { System.out.println("B"); }
public void doStuff(Object o) { System.out.println("Object"); }
}
class Test {
private final StuffDoer stuffDoer;
public <T> void foo(T t) {
stuffDoer.doStuff(t)
}
}
执行后
Test test = new Test();
A a = new A();
B b = new B();
test.foo(a);
test.foo(b);
两次打印“Object”,而不是之后预期的“A”和“B”。
如果我显式传递一个 Class 对象也不起作用
class Test {
private final StuffDoer stuffDoer;
public <T> void foo(T t) { //doesnt work
stuffDoer.doStuff(t.getClass().cast(t))
}
public <T> void foo(T t, Class<T> tClass) { //doesnt work either
stuffDoer.doStuff(tClass.cast(t))
}
}
只有当我像这样在 foo 方法中将它们显式转换为适当的对象时它才有效
class Test {
private final StuffDoer stuffDoer;
public <T> void foo(T t) {
if ( t instanceof A )
stuffDoer.doStuff((A) t) // Prints "A"
else if ( t instance of B )
stuffDoer.doStuff((B) t) // Prints "B"
else
stuffDoer.doStuff(t) // Prints "Object"
}
}
这是为什么?我怎样才能从泛型类型获得正确的方法重载?在 Java 中甚至可能吗?
在 Java 中,只有 method receiver
是在运行时动态选择的,而方法的签名是在编译时使用提供的参数类型确定的,因此 doStuff(Object o)
方法被选为唯一可能的方法(将其注释掉会导致 compile-time 错误)。
没有太多选项可以按照您想要的方式“模拟”多重分派:
你已经提到的instanceof
链
一个Visitor/Strategy模式
通过反射或MethodHandle
的动态方法查找
模式匹配(自 Java 17):
public <T> void foo(T t) {
switch (t) {
case A a -> stuffDoer.doStuff(a);
case B b -> stuffDoer.doStuff(b);
case null -> System.out.println("OOPS :(");
default -> stuffDoer.doStuff(t);
}
}
我有以下代码:
class A{}
class B{}
class StuffDoer {
public void doStuff(A a) { System.out.println("A"); }
public void doStuff(B b) { System.out.println("B"); }
public void doStuff(Object o) { System.out.println("Object"); }
}
class Test {
private final StuffDoer stuffDoer;
public <T> void foo(T t) {
stuffDoer.doStuff(t)
}
}
执行后
Test test = new Test();
A a = new A();
B b = new B();
test.foo(a);
test.foo(b);
两次打印“Object”,而不是之后预期的“A”和“B”。
如果我显式传递一个 Class 对象也不起作用
class Test {
private final StuffDoer stuffDoer;
public <T> void foo(T t) { //doesnt work
stuffDoer.doStuff(t.getClass().cast(t))
}
public <T> void foo(T t, Class<T> tClass) { //doesnt work either
stuffDoer.doStuff(tClass.cast(t))
}
}
只有当我像这样在 foo 方法中将它们显式转换为适当的对象时它才有效
class Test {
private final StuffDoer stuffDoer;
public <T> void foo(T t) {
if ( t instanceof A )
stuffDoer.doStuff((A) t) // Prints "A"
else if ( t instance of B )
stuffDoer.doStuff((B) t) // Prints "B"
else
stuffDoer.doStuff(t) // Prints "Object"
}
}
这是为什么?我怎样才能从泛型类型获得正确的方法重载?在 Java 中甚至可能吗?
在 Java 中,只有 method receiver
是在运行时动态选择的,而方法的签名是在编译时使用提供的参数类型确定的,因此 doStuff(Object o)
方法被选为唯一可能的方法(将其注释掉会导致 compile-time 错误)。
没有太多选项可以按照您想要的方式“模拟”多重分派:
你已经提到的
instanceof
链一个Visitor/Strategy模式
通过反射或
的动态方法查找MethodHandle
模式匹配(自 Java 17):
public <T> void foo(T t) { switch (t) { case A a -> stuffDoer.doStuff(a); case B b -> stuffDoer.doStuff(b); case null -> System.out.println("OOPS :("); default -> stuffDoer.doStuff(t); } }