我在阅读泛型时遇到了PECS(制片extends人和消费者的super简称).
能否给我一个人解释如何使用佩奇之间解决困惑extends和super?
我有一个List,声明如下:
List<? extends Number> foo3 = new ArrayList<Integer>();
Run Code Online (Sandbox Code Playgroud)
我试图将3添加到foo3.但是我收到如下错误消息:
The method add(capture#1-of ? extends Number) in the type List<capture#1-of ?
extends Number> is not applicable for the arguments (ExtendsNumber)
Run Code Online (Sandbox Code Playgroud) 我正在尝试学习Java泛型.我不清楚你什么时候使用<T extends Foo>以及何时使用<T super Foo>.这些事情中的每一个对T意味着什么?可以说我有<T extends Comparable>和<T super Comparable>,什么每个这些是什么意思?
我在sun.com上看过几个教程,但我还是迷路了.有人能举例说明吗?
谢谢!
我经历了这些话题
但是,我似乎仍然丢失了super关键字:
当我们声明一个这样的集合时:
List<? super Number> list = null;
list.add(new Integer(0));//this compiles
list.add(new Object());//this doesn't compile
Run Code Online (Sandbox Code Playgroud)
不应该是相反的 - 我们有一个列表,其中包含一些父母的对象(未知类型)Number.所以Object应该适合(因为它是父的Number),Integer不应该.出于某种原因,情况正好相反.
只要我们有以下代码
static void test(List<? super Number> param) {
param.add(new Integer(2));
}
public static void main(String[] args) {
ArrayList<String> sList = new ArrayList<String>();
test(sList); //will never compile, however...
}
Run Code Online (Sandbox Code Playgroud)
编译上面的代码是不可能的(我的理智表明这是正确的行为),但基本逻辑可能证明相反:
String is Object, Object is superclass of Number. So String should work.
我知道这很疯狂,但这不是他们不允许<S super T>构造的原因吗?如果是,那么为什么<? super T> …
这个方法声明有什么区别:
public static <E extends Number> List<E> process(List<E> nums){
Run Code Online (Sandbox Code Playgroud)
和
public static List<Number> process(List<Number> nums){
Run Code Online (Sandbox Code Playgroud)
你会在哪里使用前者?
我只是看看List界面中定义的方法:<T> T[] toArray(T[] a)
我有一个问题.为什么它是通用的?因此,方法不完全是类型安全的.以下代码片段编译但导致ArrayStoreException:
List<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
String[] stringArray = list.toArray(new String[]{});
Run Code Online (Sandbox Code Playgroud)
在我看来,如果toArray不是通用的并采用List类型参数,那就更好了.
我已经写过玩具示例,它可以通用:
package test;
import java.util.Arrays;
public class TestGenerics<E> {
private Object[] elementData = new Object[10];
private int size = 0;
public void add(E e) {
elementData[size++] = e;
}
@SuppressWarnings("unchecked")
//I took this code from ArrayList but it is not generic
public E[] toArray(E[] a) {
if (a.length < size)
// Make a new array of a's runtime type, …Run Code Online (Sandbox Code Playgroud) 我知道为什么不应该这样做.但有没有办法向外行人解释为什么这是不可能的.你可以轻松地向外行解释:Animal animal = new Dog();.狗是一种动物,但是一系列的狗并不是动物的清单.
我无法理解以下文章:http: //www.ibm.com/developerworks/java/library/j-jtp01255.html
下,
泛型不是协变的
作者说,
因为ln是一个List,所以添加一个Float似乎是完全合法的.但是如果ln与li混淆,那么它将破坏li定义中隐含的类型安全承诺 - 它是一个整数列表,这就是泛型类型不能协变的原因.
我无法理解它所说的"如果ln与li混淆"的部分.作者对别名的含义是什么?(参考?).引用行上方的代码片段似乎说明了什么在java中是非法的而不是为什么.如果有人能用一个例子来解释,对我来说会很有帮助.提前致谢.
假设我有一个方法"mix",它采用两个可能不同类型的T和S列表,并返回一个包含两者元素的List.对于类型安全,我想指定返回的List是R类型,其中R是T和S共有的超类型.例如:
List<Number> foo = mix(
Arrays.asList<Integer>(1, 2, 3),
Arrays.asList<Double>(1.0, 2.0, 3.0)
);
Run Code Online (Sandbox Code Playgroud)
为了指定这个,我可以将方法声明为
static <R, T extends R, S extends R> List<R> mix(List<T> ts, List<S> ss)
Run Code Online (Sandbox Code Playgroud)
但是如果我想在类上创建mix一个实例方法而不是静态List2<T>呢?
<R, T extends R, S extends R> List<R> mix ...
Run Code Online (Sandbox Code Playgroud)
阴影<T>在实例上List2,所以没有好处.
<R, T extends S&T, S extends R> List<R> mix ...
Run Code Online (Sandbox Code Playgroud)
解决了阴影问题,但编译器不接受
<R super T, S extends R> List<R> mix ...
Run Code Online (Sandbox Code Playgroud)
被编译器拒绝,因为下限通配符不能存储在命名变量中(仅用于? super X表达式)
我可以将参数移动到类本身,例如List2<R, T extends R, S extends R>,但类型信息实际上没有业务存在于实例级别,因为它仅用于一个方法调用,并且您每次需要时都必须重新构建对象在不同的参数上调用该方法. …