Java泛型和模板

Java泛型和模板,java,templates,generics,types,wildcard,Java,Templates,Generics,Types,Wildcard,我有以下Java类定义: import java.util.*; public class Test { static public void copyTo(Iterator<? extends Number> it, List<? extends Number> out) { while(it.hasNext()) out.add(it.next()); } public static void main(String[] args) {

我有以下
Java
类定义:

import java.util.*;

public class Test {

static public void copyTo(Iterator<? extends Number> it, List<? extends Number> out) {
    while(it.hasNext())
        out.add(it.next());
}
public static void main(String[] args) {
    List<Integer> in = new ArrayList<Integer>();
    for (int i = 1; i <= 3; i++) {
        in.add(i);
    }
    Iterator<Integer> it = in.iterator();
    List<Number> out = new ArrayList<Number>();
    copyTo(it, out);
    System.out.println(out.size());
}
因此,我继续为
copyTo
方法定义了另一个定义:

static public void copyTo(Iterator<? super Integer> it, List<? super Integer> out) {
        while(it.hasNext())
            out.add(it.next());
    }

static public void copyTo(迭代器如果方法签名包含两个或多个通配符,并且方法的逻辑要求它们相同,则需要使用泛型类型参数而不是通配符

static public <T extends Number> void copyTo(Iterator<? extends T> it, List<? super T> out) {
    while(it.hasNext())
        out.add(it.next());
}
这些签名实际上是等价的,因为
Integer
是最终的,所以任何扩展
Integer
的类的超类都必须是
Integer
的超类

但是,就编译器而言,这两个签名并不相等

static <T extends Number> void copyTo1(Iterator<? extends T> it, List<? super T> out) {
    copyTo2(it, out); // doesn't compile
}

static void copyTo2(Iterator<? extends Integer> it, List<? super Integer> out) {
   copyTo1(it, out);
}

static void copyTo1(迭代器如果方法签名包含两个或多个通配符,并且方法的逻辑要求它们相同,则需要使用泛型类型参数而不是通配符

static public <T extends Number> void copyTo(Iterator<? extends T> it, List<? super T> out) {
    while(it.hasNext())
        out.add(it.next());
}
这些签名实际上是等价的,因为
Integer
是最终的,所以任何扩展
Integer
的类的超类都必须是
Integer
的超类

但是,就编译器而言,这两个签名并不相等

static <T extends Number> void copyTo1(Iterator<? extends T> it, List<? super T> out) {
    copyTo2(it, out); // doesn't compile
}

static void copyTo2(Iterator<? extends Integer> it, List<? super Integer> out) {
   copyTo1(it, out);
}

static void copyto(迭代器首先,您希望通过向方法本身添加类型变量来施加约束,因为使用通配符无法在两个参数之间施加约束,因此必须考虑方法中涉及的类型的差异:

  • 您需要一个
    迭代器作为输入,其中
    X
    至少是您要复制的数值类型(或子类型)的类型
  • 您希望输出一个列表,其中
    Y
    最多是数字类型(或超级类型)的类型
这些约束是不同的,必须以不同的方式表达:

static public <T> void copyTo(Iterator<? extends T> it, List<? super T> out) {
while(it.hasNext())
    out.add(it.next());
}

static public void copyTo(迭代器首先,您希望通过向方法本身添加类型变量来施加约束,因为使用通配符无法在两个参数之间施加约束,那么您必须考虑方法中涉及的类型的差异:

  • 您需要一个
    迭代器作为输入,其中
    X
    至少是您要复制的数值类型(或子类型)的类型
  • 您希望输出一个列表,其中
    Y
    最多是数字类型(或超级类型)的类型
这些约束是不同的,必须以不同的方式表达:

static public <T> void copyTo(Iterator<? extends T> it, List<? super T> out) {
while(it.hasNext())
    out.add(it.next());
}

static public void copyTo(迭代器)如果是
void copyTo,那还不够吗(Iterator@Cinnam是的,你说得对。这是一个更好的解决方案。如果它是
void copyTo,难道还不够吗(Iterator@Cinnam是的,你说得对。这是一个更好的解决办法。