0

应该在哪里使用extends,应该在哪里使用super,以及在哪里不适合使用通配符?

是他们的任何原则或规则,还是都与自己的理解和适用范围有关。

就像目前我只需要两个数字就可以添加到列表中,所以我将使用,

 public List<Integer> addToNewList(integerList  , Integer element){
   integerList.add(element);
   return integerList;
}

但是后来我的应用程序范围增加了,现在它需要所有数字,所以让它通用以获得最大的支持。前任 :

public <T extends Number> List<T> addToList(List<? extends T> genericList , T element){
   genericList.add(element);
   return genericList;
}

简而言之,我只想知道,什么时候应该使用这些通配符,什么时候不应该?

4

2 回答 2

4

我了解何时使用和何时不使用,我在一本书中发现了一个很棒的原则:

Get and Put 原则:当你只从结构中获取值时使用扩展通配符,当你只将值放入结构时使用超级通配符,当你同时获取和放置时不要使用通配符。

这是一个方法,它接受一组数字,将每个数字转换为双精度数,然后将它们相加:

public static double sum(Collection<? extends Number> nums) {
    double s = 0.0;
    for (Number num : nums) s += num.doubleValue();
    return s;
}

由于这使用了extends,因此以下所有调用都是合法的:

List<Integer>ints = Arrays.asList(1,2,3);
assert sum(ints) == 6.0;
List<Double>doubles = Arrays.asList(2.78,3.14);
assert sum(doubles) == 5.92;
List<Number>nums = Arrays.<Number>asList(1,2,2.78,3.14);
assert sum(nums) == 8.92;

如果不使用extends,前两个调用将是不合法的。

例外:您不能将任何内容放入使用扩展通配符声明的类型中——除了值 null,它属于每个引用类型。

每当您使用 add 方法时,都会将值放入结构中,因此请使用超级通配符。这是一个方法,它接受一个数字集合和一个整数 n,并将从零开始的前 n 个整数放入集合中:

public static void count(Collection<? super Integer> ints, int n) {
    for (int i = 0; i < n; i++) ints.add(i);
}

由于这使用了 super,以下所有调用都是合法的:

List<Integer>ints = new ArrayList<Integer>();
count(ints, 5);
assert ints.toString().equals("[0, 1, 2, 3, 4]");
List<Number>nums = new ArrayList<Number>();
count(nums, 5); nums.add(5.0);
assert nums.toString().equals("[0, 1, 2, 3, 4, 5.0]");
List<Object>objs = new ArrayList<Object>();
count(objs, 5); objs.add("five");
assert objs.toString().equals("[0, 1, 2, 3, 4, five]");

如果不使用 super,最后两个调用将不合法。

例外:你不能从用超级通配符声明的类型中得到任何东西——除了 Object 类型的值,它是每个引用类型的超级类型。

这个原理也在下面的问题Get and Put rule中解释

于 2013-09-03T07:12:25.197 回答
2

当它们有意义时,你应该使用它们......

在您的实例中,您说由于应用程序的发展,您必须重构代码以将泛型类型从整数更改为数字。这对我来说完全没问题。几乎不可能期望应用程序会以所有方式发展。编写代码来处理“未来可能”的场景是徒劳的,直到它接近未来的那个时间,因为它可能根本不会到达那里。

话虽如此,您应该尝试将您的 API 设计为限制最少的类型,以使您的函数的功能可以很好地执行。当然,除非它需要更多的努力,并且当前的功能对所提供的灵活性没有用处。

于 2013-09-03T06:25:53.983 回答