Java泛型和接口,使用类型作为方法参数

时间:2012-05-17 01:14:37

标签: java oop generics

我有以下代码:

public interface IDoWork<K extends AbstractKey,V extends AbstractClass> {
    V obtain(K key, V value);
}

public class AbstractKey {
    String id;
}

public class AbstractClass {
    String name;
}

public class ConcreteA extends AbstractClass {
    String attributeA;
}

public class DoWorkA implements IDoWork<KeyA, ConcreteA> {

    private static final DoWorkA INSTANCE = new DoWorkA();

    public static DoWorkA getInstance() {
        return INSTANCE;
    }

    @Override
    public ConcreteA obtain(KeyA k, ConcreteA v) {
        //do something in real life
        return null;
    }

}

public class Main {

    public static void main(String[] args){
        KeyA a = new KeyA();
        ConcreteA c = new ConcreteA();
        IDoWork<? extends AbstractKey, ? extends AbstractClass> instance =
                WorkFactory.getInstance().obtainInstance(a);
        instance.obtain(a, c);
    }
}

public class WorkFactory {

    private static final WorkFactory INSTANCE = new WorkFactory();

    public static WorkFactory getInstance() {
        return INSTANCE;
    }

    public IDoWork<? extends AbstractKey, ? extends AbstractClass> obtainInstance(AbstractKey key){
        if(key instanceof KeyA){
            return DoWorkA.getInstance();
        }
        throw new IllegalArgumentException("Case not handled");
    }

}

在以下代码中:

KeyA a = new KeyA();
ConcreteA c = new ConcreteA();
IDoWork<? extends AbstractKey, ? extends AbstractClass> instance = WorkFactory.getInstance().obtainInstance(a);
instance.obtain(a, c);

此行无法编译:

instance.obtain(a, c);

由于Java泛型的性质。我收到以下错误:

  

在IDoWork类型中获取(捕获#3-of?extends AbstractKey,捕获#4-of?extends AbstractClass)的方法不适用于参数(KeyA,ConcreteA)

还有其他办法吗?如果省略

中的类型参数
IDoWork<? extends AbstractKey, ? extends AbstractClass> instance =...

如果我从IDoWork删除类型参数...它可以工作,但我收到警告。有没有办法解决这个问题。?我知道我可以从界面中删除类型参数,这将解决问题,但我觉得使用泛型以便不必进行投射很方便+它为代码带来了清晰度,因为它清楚地看到每个类的内容使用。 Depencendy注入是不可能的,因为它在我所在的代码库中不可用。

1 个答案:

答案 0 :(得分:0)

我有一些有用的东西,但不是很优秀:

如果您以这种方式定义WorkFactory:

public class WorkFactory {
    private static final WorkFactory INSTANCE = new WorkFactory();
    public static WorkFactory getInstance() {
        return INSTANCE;
    }

    @SuppressWarnings("unchecked")
    public <K extends AbstractKey, V extends AbstractClass> IDoWork<K, V> obtainInstance(K key, V val) {
        if (key instanceof KeyA) {
            return (IDoWork<K, V>) DoWorkA.getInstance();
        }
        throw new IllegalArgumentException("Case not handled");
    }

}

那么你的主要方法应该干净利落:

public static void main(String[] args){
        KeyA a = new KeyA();
        ConcreteA c = new ConcreteA();
        IDoWork<KeyA, ConcreteA> instance = WorkFactory.getInstance().obtainInstance(a, c);
        instance.obtain(a, c);
}

我已更改obtainInstance以获取密钥和val,以正确推断类型。