11

这是我为了简化我的真实代码而编造的一个例子,所以如果它有点做作,我深表歉意。我想做的是从单个嵌套类型参数中有效地获取两个类型参数。我很确定这是不可能的,但我想我会试一试。

//Not legal java code
public class Foo<C extends Collection<T>> { //where T is another type parameter
    private C coll;

    public Foo(C coll) {
        this.coll = coll;
    }

    public void add(T elem){
        this.coll.add(elem);
    }
    //UPDATED TO ADD GETTER
    /**
     * I may need to retrieve the collection again, or pass it
     * on to another function that needs the specific C type
     */
    public C getColl(){
        return coll;
    }
}
...
List<String> strings = new ArrayList<String>();
Foo<List<String>> foo = new Foo<List<String>>(strings);
foo.add("hello");

我知道我可以通过添加另一个类型参数来做到这一点:

public class Foo<C extends Collection<T>,T>

但后来我必须添加多余的:

Foo<List<String>,String> foo = new Foo<List<String>,String>(strings);

在我的真实案例中,我的泛型有时可以在 implements 子句中指定,例如

public class Bar implements Baz<String>

那时必须指定第二个类型参数更加痛苦,因为感觉就像它把实现细节扔到了我的脸上。不得不说

Foo<Bar,String>

当 String 和 Bar 之间已经存在关系时,它看起来并不优雅。我知道它是 Java,所以这与领土有关,但只是好奇是否有解决方案。

4

3 回答 3

6

这是不可能的,我也不认为这是理想的,因为您现有的类中没有任何东西需要不变性。

Foo<T,C extends Collection<T>>

更普遍的是

Foo<T,C extends Collection<? super T>>

如果拥有 T 的唯一原因是允许集合的突变。

注意,如果您担心必须经常指定两个类型参数,您可以创建一个浅子类:

class DerivedFoo<T> extends Foo<Collection<T>,T>

并且您可以使用工厂方法来避免在创建时重复指定

public static <T> Foo<Collection<T>,T> fromCollection(Collection<T> c)

您还可以将接口抽象为 aninterface以获得上述简洁类型的好处DerivedFoo

于 2011-11-08T23:31:41.457 回答
2

在 Java7 之前,构造函数不进行类型推断,解决方法是使用静态工厂方法。这不再是必要的了。在 Java 7 中,您可以

Foo<List<String>,String> foo = new Foo<>(strings);

关于Tand C,如果我们有 2 个类型参数,它们之间有约束,那么一定会有一定程度的冗余。在您的示例中,由于一个参数C完全决定了另一个参数T,因此冗余似乎难以忍受。我没有看到解决方案。

但是如果重新排序类型参数,您可能会感觉更好

Foo<String,Bar> foo = new Foo<>(bar);

所以我们String先声明;然后进一步提供Baz<String>一个Bar

于 2011-11-09T02:01:43.260 回答
2

为什么不直接使用 T 作为唯一的类型参数,如下所示:

public class Foo<T> { //where T is another type parameter
private Collection<T> coll;

public Foo(Collection<T> coll) {
    this.coll = coll;
}

public void add(T elem){
    this.coll.add(elem);
}
于 2011-11-08T23:32:00.833 回答