2011-02-07 104 views
0

我有一个非通用这样的代码:泛型类型的参数,这也是一个返回值

class List { 
    List intersect(List out, List other) { 
    if (out == null) out = new List(); 
    // insert elements common to $this and $other into $out 
    return out; 
    } 
} 

这种方法安全地使用混合类型包含的对象的使用:

  1. other能含有较多的特定类型(子类)
  2. out可以包含少特定类型的(超)
的对象的对象3210

E.g. (而不是从真正的代码)

List<Number> my; 
List<Integer> other; 
List<Object> result = new(); 

result = my.intersect(result, other); 

我需要因此:

class List<T> { 
    <R super T> List<R> intersect(List<R> out, List<? extends T> other); 
} 

然而,这并不编译。泛型常见问题指出,类型参数的下限没有意义,但我无法看到它给出上面的例子。

我得到的最接近的是:

List<? super T> intersect(List<? super T> out, List<? extends T> other); 

但是这需要在调用点返回值的显式转换。

是否有可能以对所有现有用法都是安全的方式来生成此方法?

UPDATE: 在情况下,它并不明显:(这是一个接口顺便说一句),这不是一个java.util.List但自定义类。不相关的部分被省略,但方法签名完全如图所示(访问级别除外)。

UPDATE2: 通过类型安全我指的是尽可能限制。理想情况下,所有参数都应遵守上述两条规则。

+1

是'intersect`一个静态方法?如果没有,我有点困惑为什么有列表实例本身和2个列表参数? – 2011-02-07 00:45:17

+0

只是一个方面说明:你知道的方法List.retainAll:http://download.oracle.com/javase/6/docs/api/java/util/List.html#retainAll%28java.util.Collection% 29 ? – Puce 2011-02-07 02:36:56

+0

它不是静态的,它不是java.util.List – 2011-02-08 13:08:40

回答

0

你试图打破协变和逆变的规则。假设您期望List<Object>作为您的out参数,并且T是某个A类,并且还有一些B类扩展为A. intersect方法的实现者为out创建了List<A>,这看起来很好,因为A扩展了B.但是,来电者获得他认为是List<Object>的列表。现在调用者试图插入一堆C(与A和B无关,除了所有三个都从某个时刻从Object派生出来)并且整个事件都爆炸了。

换句话说,这是不可能的。

+0

尽管我觉得确实无法像我想要的那样限制类型,但我并不完全遵循您的示例。 将`out`的任何列表传递给`out`,其中`out.T`不如`T`具体,然后将符合(out.T的子类)的东西插入到结果列表中。 – 2011-02-08 14:06:10

0

编辑:由于我完全误解了这个问题,这里给出一个新的答案。

我首先想回答

class List<T> { 
     /** 
     * Creates the intersection of this list with a second list, 
     * adding the resulting elements to another list. 
     * @param out the List to which the output should be added. 
     *  If null, a new List will be created. 
     * @param second the second list to intersect with this list. 
     * @return out, with the intersection of left an right added 
     */ 
    <R super T, S extends R> 
     List<R> intersect(List<R> out, List<S> second); 
} 

但你发现,它并没有编译。 是的,我认为这将是super关键字的有效使用。 它看起来像没有办法做这样的编译。(我知道你说S应该是T的一个子类型,不仅是S的子类型,但我仍然没有认为这是必要的。事实上,S可能是任何东西,但将它留给子类型r可让更多的自由实现它并不真正的问题在这里)

有趣的是,有可能制定它作为一个静态方法:。

class List<T> { 
     /** 
     * Creates the intersection of two Lists, 
     * adding the resulting elements to another list. 
     * @param out the List to which the output should be added. 
     *  If null, a new List will be created. 
     * @param left the first list to intersect. 
     * @param right the second list to intersect 
     * @return out, with the intersection of left an right added 
     */ 
    static <R, T extends R, S extends R> 
     List<R> intersect(List<R> out, List<T> left, List<S> right) { 
     // TODO 
     return out; 
    } 
} 

或者,如果你不需要t和s内部方法:

class List<T> { 
     /** 
     * Creates the intersection of two Lists, 
     * adding the resulting elements to another list. 
     * @param out the List to which the output should be added. 
     *  If null, a new List will be created. 
     * @param left the first list to intersect. 
     * @param right the second list to intersect 
     * @return out, with the intersection of left an right added 
     */ 
    static <R> 
     List<R> intersect(List<R> out, List<? extends R> left, List<? extends R> right) { 
     // TODO 
     return out; 
    } 
} 

当然,当你想在子类中覆盖这个方法时,这种静态的方式来说这不起作用。

0
<R> List<R> intersect(List<R> out, List<? extends R> other) 
{ 
    for(R x : other) 
     if(this.contains(x)) 
      out.add(x); 
    return out; 
} 

boolean contains(Object x){ ... } 

通知,需要Object,而不是T

相关问题