首页 > 解决方案 > 扩展另一个泛型类的泛型类的泛型类型参数的绑定不匹配错误

问题描述

我在java中遇到泛型和继承问题。

我想从“createManager”方法实例化一个“ObjectManager”类,该方法可以从给定类型创建实例。这个“ObjectManager”有一些实用方法(例如:“getDescription”)。

这个方法允许我从一个类型中实例化一个“ObjectManager”,然后得到它的描述(这里的哈希)。

如果输入类型可分配给类型“Foo”,我还想为“FooManager”专门化“ObjectManager”,以便我可以覆盖“getDescription”方法。因此,我在“createManager”方法中测试输入的类型,以了解我是创建“ObjectManager”还是“FooManager”。

该代码有效,但我不知道与“new FooManager(type)”对应的输出的泛型类型。在我看来,对于 Eclipse 快速修复,类型应该是 <T> 但这会导致错误:

绑定不匹配:类型 T 不是 FooManager<T> 类型的有界参数 <T extends Foo> 的有效替代品

我的代码:

import java.lang.reflect.InvocationTargetException;
import java.util.Objects;

public class GenericBug {
    private GenericBug() {}
    
    public static void main(String[] args) {
        ObjectManager<Foo> objectManager1 = createManager(Foo.class);
        System.out.println(objectManager1.getDescription());
        
        ObjectManager<Object> objectManager2 = createManager(Object.class);
        System.out.println(objectManager2.getDescription());
    }
    
    private static <T> ObjectManager<T> createManager(Class<T> type) {
        if(Foo.class.isAssignableFrom(type))
            return new FooManager<T>(type);   //Error: Bound mismatch
        return new ObjectManager<T>(type);
    }
}

class ObjectManager<T>{
    public T val;
    public ObjectManager(Class<T> type) {
        try {
            val = type.getConstructor().newInstance();
        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) {
            e.printStackTrace();
        }
    }
    
    public String getDescription() {
        return "Hash: " + Objects.hash(val);
    }
}

class FooManager<T extends Foo> extends ObjectManager<T>{

    public FooManager(Class<T> type) {
        super(type);
    }
    
    @Override
    public String getDescription() {
        return super.getDescription() + " value: " + val.getVal();
    }
}

class Foo{
    private double val = Math.random();
    public Foo() {}

    public double getVal() {
        return val;
    }
}

所以我的问题是:为什么会出现这个错误?如何在没有警告的情况下修复它?而且,作为奖励,为什么 Eclipse 提供了一个无法编译的解决方案?这是 Eclipse 错误吗?

预先感谢您的回答。

标签: javagenericsinheritance

解决方案


问题是您正在混合泛型的编译时安全性和运行时检查isAssignableFrom

我不知道更好的方法:

private static <T> ObjectManager<T> createFooManager(Class<T> type) {
    if (Foo.class.isAssignableFrom(type)) {
        return (ObjectManager<T>) getIt((Class<? extends Foo>) type);
    }
    return new ObjectManager<>(type);

}

private static <R extends Foo> ObjectManager<R> getIt(Class<R> cls) {
    return new FooManager<>(cls);
}

不过,这会引发unchecked warning


推荐阅读