Java 多态泛型调用

标签 java generics inheritance polymorphism

我最近刚刚开始摆弄 Java 中的泛型,并且遇到了一些奇怪的行为。这是简化版本,但我有一个基类,该基类由传递到通用函数的多个类扩展。在这个函数中,我调用了一个具有多个版本的方法,这些版本采用不同的基类或派生类作为参数。

如果我有以下内容:

public class A{};
public class B extends A{};
public class C extends A{};
public class Runner
{
    public static void Run( ClassA a ){Do Something};
    public static void Run( ClassB b ){Do Something};
    public static void Run( ClassC c ){Do Something};
}
void SomeRandomCall<B extends ClassA>( B b )
{
     Runner.Run( b );
}
SomeRandomCall<ClassB>( new ClassB() );

我在调试中发现 Runner.Run 正在调用 Run( ClassA a ) 而不是 Run( ClassB b ) 函数。给定这两个函数,既然提供了类型特定的函数,难道不应该调用 Run( ClassB b ) 吗?

如果不是这种情况,我如何能够拥有一个通用函数来调用能够调用具有采用基类和派生类的签名的函数?

最佳答案

由于您的缩写对我来说有点令人困惑,因此我制作了一个可运行的小示例。我假设您的 SomeRandomCall 中的 B 是泛型类型,而不是类 B。

这里是:

public class Main {

    public static class A{};
    public static class B extends A{};
    public static class C extends A{};
    public static class Runner{
        public static void Run( A a ){System.out.println("A");};
        public static void Run( B b ){System.out.println("B");};
        public static void Run( C c ){System.out.println("C");};
    }

    static <T extends A> void SomeRandomCall( T x ){
         Runner.Run( x );
    }

    public static void main(String[] args) {
        B b = new B();
        new Runner().Run( b );
    }
}

输出为:B。

这正是您所期望的,这很好。在编译时,Java 编译器会选择方法的候选对象,即 Run( A a )Run( B b )。运行时,参数的类型为B,因此打印B。

但是,请注意以下示例:

    public static void main(String[] args) {
        A ab = new B();
        new Runner().Run( ab );
    }

现在会发生什么?现在输出是 A。原因是,在编译时,ab 的类型为 A,因此我们只有一个候选方法可以执行:Run(一个)。运行时 ab 的实际类型不再重要,因为我们只有一个可以执行的候选类型。无论 abAB 还是 C,输出都是 A .

关于Java 多态泛型调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22116010/

相关文章:

python - 如何基于父类(super class)更改子类的属性

java - 为什么我的 JButton 即使在第一次单击时也没有在单击时在 JTextFrame 上显示输出?

java - 扩展 ArrayList 的类无法正确序列化

c# - 如何限制树结构中节点的子节点

java - 泛型扩展

c++ - 对成员模板函数的访问控制

java - 子类可以修改 Java 中抽象父类(super class)中静态方法的行为吗?

java - ListIterator 交换当前和下一个

java - Java 左子树中最右边的节点

java - Function<T, R> 作为 Junit 5 中的附加参数