使用泛型创建Parameters类

时间:2012-11-08 05:33:11

标签: java generics parameters variadic-functions

我有一个接口,定义了一个执行某些计算的方法

public interface Computable { 
    public Result compute(Foo foo);
}

我还希望将一组参数传递给可以剥离的计算。我可以解决这个问题,但我想知道是否有genericsvar args的优雅解决方案。有点像...

 public class Parameter<K,V> {

    private final K key;
    private final V value;

    public Parameter(K key, V value) {
        this.key = key;
        this.value = value;
    }

    public K getKey() {
        return this.key;
    }

    public V getValue() {
        return value;
    }    
}

但是我失去了如何从参数列表中查看每个参数,我可以简单地获得其推断类型的键值对。有人能帮我吗?这还没有内置到JDK中吗?

使用示例编辑:

在具体实施中,我们有......

public Result compute(Foo foo,
                      Parameter ...parameters) {

    // Here I'd like to get each parameter, and have it know it's key type and value type
    for(Parameter p : parameters) {
        p.getKey();
        p.getValue()
        //implementers know what to do with their parameters
    }


}

2 个答案:

答案 0 :(得分:3)

作为AmitD mentioned in the comments,您应该使Computable成为参数化类型:

public interface Computable<K, V> { 
    public Result compute(Foo foo, Parameter<K, V>... parameters);
}

然后,实施将解析KV,并且会知道类型:

public class BarBazComputable implements Computable<Bar, Baz> {
    @Override
    public Result compute(Foo foo, Parameter<Bar, Baz>... parameters) {
        ...
    }
}

编辑:是的,正如AmitD再次提到的那样,您无需解析其中一个或所有类型参数:

public class WithStringComputable<K> implements Computable<K, String> {
    @Override
    public Result compute(Foo foo, Parameter<K, String>... parameters) {
        ...
    }
}

public class OhJustACoupleObjectsComputable<K, V> implements Computable<K, V> {
    @Override
    public Result compute(Foo foo, Parameter<K, V>... parameters) {
        ...
    }
}

public class NumbersComputable<N1 extends Number, N2 extends Number> implements Computable<N1, N2> {
    @Override
    public Result compute(Foo foo, Parameter<N1, N2>... parameters) {
        ...
    }
}

请注意,varargs与泛型不匹配,并且在调用compute时,您将在调用点获得类型安全警告。相反,请考虑让方法采用Iterable<Parameter<K, V>>

答案 1 :(得分:1)

如果您对不同参数或不同值类型使用不同的键类型,则可能无法使用简单的通用varargs函数定义来解决此问题。你唯一的类型安全选项就是这样:

public Result compute(Foo foo, Parameter<Byte, Byte> p1, Parameter<Byte, Float> p2, ...)

(这里“......”表示以相同方式添加的其他参数,而不是varargs省略号)

如果你需要灵活,并且你可以通过探测参数的其他属性来确定你正在处理哪个键和值类型,我有时会使用一种技巧来简化类型转换:更改你的{ {1}} getKey()类中的函数:

Parameter

(类似于getValue()函数)

这样,您可以简单地将@SuppressWarnings("unchecked") public <KeyType> KeyType getKey() { return (KeyType) this.key; } 的结果分配给任何(非原始)类型的变量,如下所示:

getKey()

Integer key = parameter.getKey();

并且您不必在计算功能中进行任何类型转换,也不会有任何警告。

但是:你将失去编译时类型检查!所以,你必须确保在运行时(无论如何你可能不得不)将一个键分配给一个变量类型错误。或者至少优雅地处理生成的ClassCastException。