当通配符?
与extends
或super
一起使用时,我没有得到它在Java中的实际使用情况。
Oracle Java官方文档展示了一个将数字添加到列表中并对其进行汇总的示例:
private static double sumOfList(List<? extends Number> list) {
double sum = 0.0;
for (Number number : list) {
sum += number.doubleValue();
}
return sum;
}
根据我的理解,List<? extends Number> list
并不意味着";Number对象的实例和Number"的可能子类的对象的列表;而是";单个类型的对象的列表,其必须是或扩展类型"数字";。没关系。
直到我尝试了这个代码:
List<Number> numberList = new ArrayList<Number>();
numberList.add(Integer.valueOf(123));
numberList.add(Double.valueOf(2.34));
numberList.add(Float.valueOf(3.45f));
实例可以通过隐式向上转换到数字引用添加到"数字"列表中。然后,这个数字列表可以与sumOfList方法一起使用,如上所示。但这些元素不会是单一类型的。那么,为什么有人会把extends
和?
一起使用呢?
我没有得到的另一件事是将通配符与super一起使用。可以定义一个类型的下界。Oracle的官方文档显示了这个例子:
public static void addNumbers(List<? super Integer> list) {
for (int i = 1; i <= 10; i++) {
list.add(i);
}
}
问题是,这对于像向列表中添加数字这样的简单事情来说非常有效。但是显示的代码也适用于这样的列表:
List<Object> list = new ArrayList<Object>();
list.add(Integer.valueOf(123));
list.add(Double.valueOf(2.34));
list.add(new Person("John", "Doe"));
因此,只要调用方法,就可以对实际数字做任何有用的事情,比如——我不知道——算术运算——代码可能会很好地工作。但当涉及到John Doe条目时,用于数字的代码会失败。
那么,有人能澄清extends
和super
关键字与?
运算符结合的实际应用吗?
那么,为什么有人会将
extends
与?
一起使用呢?
因为您可能没有要传递给它的List<Number>
。例如,您可以将List<Integer>
、List<BigInteger>
等传递给sumOfList
。
如果您没有声明它接受List<? extends Number>
,而是声明它接受了List<Number>
,那么您只能将List<Number>
传递给它——List<Integer>
不是List<Number>
的子类型。
就addNumbers
方法而言:您只需要某种List
,可以安全地向其添加Integer
的实例(或子类型[因为它是最终的,所以没有子类型]或null
(。
这就是List<? super Integer>
的全部含义:向其中添加Integer
的实例是安全的。
将List<Object>
传递给该方法是安全的,因为所有Integer
都是Object
,所以将Integer
添加到该列表是安全的。
同样,如果您已将该方法声明为接受List<Object>
(或List<Integer>
(,那么您可以传递给它的就只有这些:List<Object>
(或分别为List<Integer>
(。比如说,你不能通过List<Number>
。
那么,有人能澄清
extends
和super
关键字与?
运算符结合使用的实际用途吗?
通配符的实际使用是以增加API方法的灵活性,如上所示:它允许您声明一个将一系列相关类型作为输入的方法。
您也可以在输出中使用通配符,但应该避免这样做,因为通配符最终出现在调用站点的值类型中,并且通常看起来很混乱。
1。那么,为什么有人会使用extends with呢?不管怎样
当通配符被用作"Unbounded like"时,我们不能执行写入或删除操作;列出<gt&";,因为编译器不知道它是什么类型,比如:
// not allowed
public static void displayList(List<?> list) {
list.add(1);
}
// allowed
public static void displayList(List<? super Integer> list) {
list.add(1);
}
2.那么,有人能澄清extends和super关键字与的实际实际应用吗?操作员
它是使用一些设计模式和原则的一个很好的组合,我想到的最简单的一个是将它与接口分离原则一起使用。
interface Worker {
void work();
}
interface Sleeping {
void sleep();
}
class Human implements Worker, Sleeping {
@Override
public void work() {}
@Override
public void sleep() {}
}
class Robot implements Worker {
@Override
public void work() {}
}
public static void main(String[] args) {
Human human1 = new Human();
Human human2 = new Human();
List<Human> humans = List.of(human1, human2);
displayIfSleeping(humans);
Robot robot1 = new Robot();
Robot robot2 = new Robot();
List<Robot> robots = List.of(robot1, robot2);
displayIfSleeping(robots); // error
}
public static void displayIfSleeping(List<? extends Sleeping> workers) {
// display only workers who are sleeping
}
这是一个很好的方式,可以明确地表明,如果你必须迭代员工,你只希望他们是可以睡觉的人。