Java方法中的泛型与继承

编程语言 2026-07-10

我有一些方法:

public <T extends MyType> ReturnType method1(List<T> objects) {
    for(T obj: objects) process(obj);
}

public void process(MyType_1 obj) {
    doSomething(obj);
}

public void process(MyType_2 obj) {
    doOther(obj);
}

其中 MyType_1MyType_2 都继承自 MyType

问题出在类型擦除,JVM无法调用方法 process;它只能看到在 method1 中的 Object(而不是 MyType_1MyType_2)。

现在我通过额外的辅助方法来解决这个问题:

public void helpMethod(MyType obj) {
    if(obj instanceof MyType_1) processMyType_1(obj);
    if(obj instanceof MyType_2) processMyType_2(obj);
}

是否有更好的方法来解决我的问题?看起来使用 instanceof 似乎不是一个好决定。还是说可以呢?在我的情况下,我不想在 MyType 类中添加方法,因为它们是DTO(数据传输对象)。

解决方案

Spoiler: 它将找到每个子实例;报告:

MyType.p MyType
obj
MyType_1.p MyType_1
obj1
MyType_2.p MyType_2
obj2

有两种可行的方案。

拥有相同重写方法的不同继承结构:

public class MyType {

    public void p() {
        System.out.println("MyType.p " + getClass().getSimpleName());
    }

    public MyType copy() {
        return this;
    }
}
public class MyType_1 extends MyType {

    @Override
    void p() {
        System.out.println("MyType_1.p " + getClass().getSimpleName());
    }

    @Override
    public MyType_1 copy() {
        return this;
    }
}
public class MyType_2 extends MyType {

    @Override
    void p() {
        System.out.println("MyType_2.p " + getClass().getSimpleName());
    }

    @Override
    public MyType_2 copy() {
        return this;
    }
}

调用方法 p 时,将得到正确的运行时类型。我也演示了一个被重写的方法可以返回一个子类对象。

你也可以显式地分派到特定的 instanceof 类型

你正在处理 MyType 的子类。泛型类型 T extends MyType 并不真正需要。一旦调用了被重写的方法 p,随后也会调用一个分派方法 anypx

<T extends MyType> void process(T... objects) {
    for (var obj : objects) {
        obj.p();
        anypx(obj);
    }
}
void anypx(MyType obj) {
    if (obj instanceof MyType_1 obj1) {
        px(obj1);
    } else if (obj instanceof MyType_2 obj2) {
        px(obj2);
    } else {
        px(obj);
    }
}

void px(MyType_1 obj1) {
    System.out.println("obj1");
}

void px(MyType_2 obj2) {
    System.out.println("obj2");
}

void px(MyType obj) {
    System.out.println("obj");
}

其中 obj1obj2 使用正确的子类来覆盖 obj

用法

public static void main(String[] args) {
    new Workbench1().process(new MyType(), new MyType_1(), new MyType_2());
}
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章