Java中的嵌套类型参数 [英] Nested Type Parameters in Java

查看:136
本文介绍了Java中的嵌套类型参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我为了简化我的真实代码而编写的一个例子,所以我很抱歉,如果它有点做作。我想要做的是有效地从单个嵌套类型参数中获取两个类型参数。我非常肯定这是不可能的,但我认为我会给它一个。

  //不合法的java代码
public class Foo< C扩展Collection< T>> {//其中T是另一个类型参数
private C coll;

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

public void add(T elem){
this.coll.add(elem);
}
//更新为添加GETTER
/ **
*我可能需要再次检索集合,或者将
*传递给另一个需要的函数具体的C类型
* /
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> 

但我必须添加冗余:

 富<列表与LT;字符串>,字符串> foo = new Foo< List< String>,String>(strings); 

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

  public class Bar implements Baz< String> 

不得不指定第二个类型参数更加痛苦,因为它感觉像是抛出了实现我脸上的细节。不得不说

  Foo< Bar,String> 

当String和Bar之间已经存在关系时,看起来不够好看。我得到的是它的Java,因此与领土一致,但只是好奇,是否有解决这个问题的解决方案。

这是不可能的,我不认为它是理想的,因为你现有的课程中没有什么需要不变的。

  Foo   

通常可以是

  Foo   

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



请注意,如果您担心必须频繁指定两个类型参数,则可以创建一个浅层子类:

  class DerivedFoo< T>延伸Foo< Collection< T>,T> 

,您可以使用工厂方法避免在创建时双重指定

  public static< T> FOO<收集和LT; T>,T> fromCollection(Collection< T> c)

您也可以将接口抽象为 interface 以获得您通过 DerivedFoo 获得的简洁类型的好处。


This is an example which I made up to be a simplification of my real code, so I apologize if it is a little contrived. What I would like to do is to effectively get two type parameters out of a single nested type argument. I'm pretty sure this is impossible, but I thought I'd give it a shot.

//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");

I know that I could do it by adding another type parameter:

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

but then I have to add the redundant:

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

And in my real world case, my generics can sometimes be specified in the implements clause like

public class Bar implements Baz<String>

Having to specify that second type parameter is even more painful then, because it feels like it throws the implementation details in my face. Having to say

Foo<Bar,String>

when there is a relationship between String and Bar already, just seems inelegant. I get that its Java, so that goes with the territory, but just curious if there was a solution for this.

解决方案

It's not possible and I don't think it's ideal anyway because there is nothing in your existing class that requires invariance.

Foo<T,C extends Collection<T>>

could more generally be

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

if the only reason to have T is to allow mutation of the collection.

Note, if you're concerned about having to specify two type parameters frequently, you can create a shallow subclass:

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

and you can use factory methods to avoid having to double-specify at creation time

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

You can also abstract the interface into an interface to get the benefits of concise types that you get with DerivedFoo above.

这篇关于Java中的嵌套类型参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆