2

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

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

我还想将一组参数传递给可以剥离的计算。我可以解决这个问题,但我想知道是否有一个优雅的解决方案genericsand var 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
    }


}
4

2 回答 2

3

正如AmitD 在评论中提到的,您应该创建Computable一个参数化类型:

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

然后一个实现将解析K并且V类型将是已知的:

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) {
        ...
    }
}

请注意,可变参数不能很好地与泛型配合使用,并且在调用compute. 相反,请考虑让该方法采用Iterable<Parameter<K, V>>.

于 2012-11-08T05:57:04.063 回答
1

如果您对不同的参数或不同的值类型有不同的键类型,那么您可能无法使用简单的泛型 varargs 函数定义来解决这个问题。您唯一的类型安全选项将是这样的:

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

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

.

但是,如果您需要灵活,并且可以通过探测 Parameter 的其他一些属性来确定要处理的键和值类型,我有时会使用一个技巧来简化类型转换:更改类getKey()中的函数Parameter对此:

@SuppressWarnings("unchecked")
public <KeyType> KeyType getKey() {
    return (KeyType) this.key;
}

(对于 getValue() 函数也是如此)

这样,您可以简单地将结果分配给getKey()任何(非原始)类型的变量,如下所示:

Integer key = parameter.getKey();

或者

String key = parameter.getKey();

而且您不必在计算函数中进行任何类型转换,也不会出现任何警告。

但是:您将失去编译时类型检查!因此,您必须确保在运行时(无论如何您可能都必须这样做)您不会将键分配给类型错误的变量。或者至少优雅地处理生成的 ClassCastException。

于 2012-11-08T06:54:40.033 回答