Java 如何让重载方法识别泛型类型的特定子类?

Java 如何让重载方法识别泛型类型的特定子类?,java,generics,erasure,Java,Generics,Erasure,我有一个方法,通常使用泛型类型的参数调用,我希望它根据参数的特定子类表现出不同的行为。例如,下面的代码: 公共类Foo{ 公共静态void方法(Foo-f){ System.out.println(“Foo方法Foo”); } 公共静态法(b栏){ System.out.println(“方法栏”); } 公共静态void main(字符串[]args){ Foo f=新的Foo(); 杆b=新杆(); Baz bz1=新的Baz(); bz1.setT(b); Baz bz2=新的Baz();

我有一个方法,通常使用泛型类型的参数调用,我希望它根据参数的特定子类表现出不同的行为。例如,下面的代码:

公共类Foo{
公共静态void方法(Foo-f){
System.out.println(“Foo方法Foo”);
}
公共静态法(b栏){
System.out.println(“方法栏”);
}
公共静态void main(字符串[]args){
Foo f=新的Foo();
杆b=新杆();
Baz bz1=新的Baz();
bz1.setT(b);
Baz bz2=新的Baz();
bz2.setT(f);
System.out.println(“用foo调用foo方法”);
方法(f);
System.out.println(“用bar调用foodmethod”);
方法(b);
System.out.println(“用foo调用方法”);
bz2.bazMethod();
System.out.println(“用bar调用方法”);
bz1.bazMethod();
}
私有静态类栏扩展了Foo{
}
私有静态类Baz{
私人T;
公共无效集合(T){
t=t;
}
公共方法(){
Foo.Foo方法(this.t);
}
}
}
结果如下:

calling fooMethod with foo
fooMethod Foo
calling fooMethod with bar
fooMethod Bar
calling bazMethod with foo
fooMethod Foo
calling bazMethod with bar
fooMethod Foo
我希望它在第4行调用bar方法,因为在这种情况下T是bar,但它总是将其识别为父类并给出默认行为


我曾经考虑过在方法中对instanceOf进行一系列调用,但这感觉有点粗糙。我想到的另一个解决方案是在调用正确方法的每个子类中重写一个抽象方法,但这似乎也很难。有没有正确的方法可以做到这一点?或者,如果我完全错了,有没有更好的方法来处理这种情况?

这里要处理的问题是类型擦除。你可以详细阅读

本质上,Baz对象必须将所有输入视为Foo变量,因为它不知道输入可能具有的任何附加功能。要解决这个问题,您可以使Foo和Bar拥有自己的非静态版本的
foometry()
,以便Bar的
foometry()
覆盖Foo类
foometry()


baz
创建适当的子类,或在构造函数中传递
使用者
。如果坚持命名转换,则更容易理解
public class Foo {

    public void fooMethod() {
        System.out.println("fooMethod Foo");
    }

    public static void main (String[] args) {

        Foo f = new Foo();
        Bar b = new Bar();

        Baz<Bar> bz1 = new Baz<>();
        bz1.setT(b);
        Baz<Foo> bz2 = new Baz<>();
        bz2.setT(f);

        System.out.println("calling fooMethod with foo");
        f.fooMethod();
        System.out.println("calling fooMethod with bar");
        b.fooMethod();
        System.out.println("calling bazMethod with foo");
        bz2.bazMethod();
        System.out.println("calling bazMethod with bar");
        bz1.bazMethod();
    }

    private static class Bar extends Foo {

        public void fooMethod() {
            System.out.println("fooMethod Bar");
        }
    }

    private static class Baz<T extends Foo> {

        private T t;

        public void setT(T t) {
            this.t = t;
        }

        public void bazMethod() {
            t.fooMethod();
        }
    }
}
calling fooMethod with foo
fooMethod Foo
calling fooMethod with bar
fooMethod Bar
calling bazMethod with foo
fooMethod Foo
calling bazMethod with bar
fooMethod Bar