泛型定义中的通配符
含义是:变量foo3可以包含任何继承自Number的类型。
以下都是合法的定义:
因此,考虑到以上可能的定义,什么类型的对象可以被合法的添加到List<? extends Number> foo3中呢?
唯一可以确定的是你可以从List中读取一个Number类型的对象或一个Number类型的子类对象。
相反的逻辑也使用于super,如List<? super T>。一下定义都是合法的:
你不能从List<? super T>中读取一个特定类型的类(如Number),因为你不能确定List真正被定义成什么。(但是可以读取一个Object对象)
唯一可以确定的是你可以向List添加一个T类型的对象或T类型的超类对象。
一个很好的例子是Collection.copy()的定义:
注意src的定义,用extends允许接受任何值为T类型或T类型的子类型的List,并从中读取值,但你不能向src执行添加操作。
dest的定义,用super允许接受任何值为T类型或T类型的超类的List,并向其写入值,但你不能向dest执行读取操作。
由此,感谢泛型通配符,通过如上的一个定义,我们可以做以下这些调用。
下面做一些练习。被注释掉的代码是错误的
List<? extends Number> foo3
含义是:变量foo3可以包含任何继承自Number的类型。
以下都是合法的定义:
List<? extends Number> foo3 = new ArrayList<Number>(); //Number "extends" Number List<? extends Number> foo3 = new ArrayList<Integer>(); //Integer "extends" Number List<? extends Number> foo3 = new ArrayList<Double>(); //Double "extends" Number
因此,考虑到以上可能的定义,什么类型的对象可以被合法的添加到List<? extends Number> foo3中呢?
- 你不能添加Integer对象,因为foo3可能被定义为 List<Double>。
- 你不能添加Double对象,因为foo3可能被定义为 List<Integer>。
- 你不能添加Number对象,因为foo3可能被定义为 List<Integer>。
唯一可以确定的是你可以从List中读取一个Number类型的对象或一个Number类型的子类对象。
相反的逻辑也使用于super,如List<? super T>。一下定义都是合法的:
List<? super Number> foo3 = new ArrayList<Number>(); //Number is a "super" of Number List<? super Number> foo3 = new ArrayList<Object>(); //Object is a "super" of Number
你不能从List<? super T>中读取一个特定类型的类(如Number),因为你不能确定List真正被定义成什么。(但是可以读取一个Object对象)
唯一可以确定的是你可以向List添加一个T类型的对象或T类型的超类对象。
一个很好的例子是Collection.copy()的定义:
public static <T> void copy(List<? super T> dest, List<? extends T> src)
注意src的定义,用extends允许接受任何值为T类型或T类型的子类型的List,并从中读取值,但你不能向src执行添加操作。
dest的定义,用super允许接受任何值为T类型或T类型的超类的List,并向其写入值,但你不能向dest执行读取操作。
由此,感谢泛型通配符,通过如上的一个定义,我们可以做以下这些调用。
//copy(dest, src) Collection.copy(new ArrayList<Number>(), new ArrayList<Number()); Collection.copy(new ArrayList<Number>(), new ArrayList<Integer()); Collection.copy(new ArrayList<Object>(), new ArrayList<Number>()); Collection.copy(new ArrayList<Object>(), new ArrayList<Double());
下面做一些练习。被注释掉的代码是错误的
List<Number> listNumber_ListNumber = new ArrayList<Number>(); //List<Number> listNumber_ListInteger = new ArrayList<Integer>(); //错误 - 只能接受Number类型。 //List<Number> listNumber_ListDouble = new ArratList<Double>(); //错误 - 只能接受Number类型。 List<Integer> listInteger_ListInteger = new ArrayList<Integer>(); //List<Integer> listInteger_ListDouble = new ArrayList<Double>(); //错误 - 只能接受Integer类型 List<? extends Number> listExtendsNumber_ListNumber = new ArrayList<Number>(); List<? extends Number> listExtendsNumber_ListInteger = new ArrayList<Integer>(); List<? extends Number> listExtendsNumber_ListDouble = new ArrayList<Double>(); List<? extends Integer> listExtendsInteger_ListInteger = new ArrayList<Integer>(); //List<? extends Integer> listExtendsInteger_ListNumber = new ArrayList<Number>(); //错误 - Number不是Integer的子类 //List<? extends Integer> listExtendsInteger_ListDouble = new ArrayList<Double>(); //错误 - Double不是Integer的子类 List<? super Number> listSuperNumber_ListNumber = new ArrayList<Number>(); //List<? super Number> listSuperNumber_ListInteger = new ArrayList<Integer>(); //错误 - Integer不是Number的超类 //List<? super Number> listSuperNumber_ListDouble = new ArrayList<Double>(); //错误 - Double不是Number的超类 //List<Integer> listInteger_ListNumber = new ArrayList<Number>(); //错误 - 只能接受Integer类型 List<? super Integer> listSuperInteger_ListNumber = new ArrayList<Number>(); List<? super Integer> listSuperInteger_ListInteger = new ArrayList<Integer>(); //List<? super Integer> listSuperInteger_ListDouble = new ArrayList<Double>(); //错误 - Double is not a superclass of Integer listNumber_ListNumber.add(3); //正确 - 允许添加Integer对象到List<Number>中 //下面的代码将出现编译错误。 //他们有相同的原因:你不知道List<T>真正指向那个类,它也许不能处理Integer。 //所以你不能添加任何类(Object, Number, Integer, Double等)到List<? extends Number> //listExtendsNumber_ListNumber.add(3); //错误 - 不能添加Integer,list可能是List<Double>,即使List就是被定义为List<Number>也不行。 //listExtendsNumber_ListInteger.add(3); //错误 - 不能添加Integer,list可能是List<Double>,即使List就是被定义为List<Integer>也不行。 //listExtendsNumber_ListDouble.add(3); //错误 - 不能添加Integer,list可能是List<Double>, 特别是List真的是List<Double>。 //listExtendsInteger_ListInteger.add(3); //错误 - 不能添加Integer,list可能是List<X>,它只接受X类型的对象。 listSuperNumber_ListNumber.add(3); //正确 - 允许添加Integer到List<Number>或者List<Object> listInteger_ListInteger.add(3); //正确 - 允许添加Integer到List<Integer> listSuperInteger_ListNumber.add(3); //正确 - 允许添加Integer到List<Integer>, List<Number>或List<Object> listSuperInteger_ListInteger.add(3); //正确 - 允许添加Integer到List<Integer>, List<Number>或List<Object>
总结:
参数和返回类型是:List<Foo>
1、可以作为参数传递给List方法的类型:
1、可以作为参数传递给List方法的类型:
参数和返回类型是:List< ? super Foo>
1、可以作为参数传递给List方法的类型:
1、可以作为参数传递给List方法的类型:
- List< Foo>
- List< Foo>
- List< ? super Foo>
- List< ? super SubFoo>
- List< ? extends Foo>
- List< ? extends SuperFoo>
- Foo & subtypes
- Foo & supertypes (up to Object)
1、可以作为参数传递给List方法的类型:
- List< Foo>
- List< Subfoo>
- List< SubSubFoo>
- List< ? extends Foo>
- List< ? extends SubFoo>
- List< ? extends SubSubFoo>
- List< ? extends Foo>
- List< ? extends SuperFoo>
- List< ? extends SuperSuperFoo>
- None! Not possible to add.
- Foo & supertypes (up to Object)
参数和返回类型是:List< ? super Foo>
1、可以作为参数传递给List方法的类型:
- List< Foo>
- List< Superfoo>
- List< SuperSuperFoo>
- List< ? super Foo>
- List< ? super SuperFoo>
- List< ? super SuperSuperFoo>
- List< ? super Foo>
- List< ? super SubFoo>
- List< ? super SubSubFoo>
- Foo & supertypes
- Object
相关推荐
泛型是Java语言中的一种机制,它允许在定义类、接口时指定类型形参,这个类型形参将在声明变量、创建对象时确定。泛型的引入解决了Java集合的缺陷,即集合会“忘记”对象的类型,导致ClassCastException。 泛型的...
通过使用泛型,我们可以定义类型参数化的类或方法,从而避免了代码重复并且可以在运行时提供类型检查。 #### 2. 泛型类Stack 在这个实验中,我们需要实现一个泛型类`Stack<E>`。其中`E`表示任何类型的元素。为了...
Java泛型通配符是Java编程语言中一个重要的特性,它允许我们在定义泛型类型时使用问号(?)作为占位符,表示任意类型的参数。这种通配符的使用大大提高了代码的灵活性和可复用性,同时也帮助开发者遵循强类型检查的...
泛型定义是在类、接口或方法中声明类型参数,使用尖括号 `和 `>`括起来。例如,`public class Holder<T> { ... }` 声明了一个名为 `Holder` 的泛型类,类型参数为 `T`。在使用时,可以指定具体的类型,例如 `Holder...
泛型允许我们在类、接口和方法中使用类型参数,这样在编译时期就能检查类型匹配,减少运行时类型转换异常。 1. **泛型的基本概念** - 泛型的本质是在类、接口或方法中使用类型参数,让它们能够处理多种数据类型。...
泛型和通配符是Java编程中的重要概念,它们在处理类型安全和代码复用方面起着关键作用。本文将深入探讨这两个主题,并提供一些常见的面试题,帮助开发者理解和掌握这些知识点。 首先,我们来理解泛型。泛型是Java 5...
本节将深入探讨“集合进阶”中的泛型继承和通配符这两个关键概念。 首先,让我们了解泛型。泛型是Java 5引入的一项特性,它允许在类、接口和方法中使用类型参数,从而实现参数化类型。通过使用泛型,我们可以在编译...
泛型方法:演示如何在普通类中定义泛型方法,以及如何调用和使用泛型方法。 类型通配符:展示如何使用类型通配符来增加灵活性,以及如何进行类型边界约束。 泛型接口:演示如何定义和实现泛型接口,并通过示例代码...
在非泛型时代,从集合中获取元素后通常需要进行类型转换,否则会抛出`ClassCastException`。使用泛型后,编译器会在编译时检查类型一致性,从而消除运行时类型转换错误的风险。 ### 总结 Java泛型是一项强大的特性...
允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。将类型参数化以达到代码复用提高软件开发工作效率的一种...
本资源为 Java 1.5 泛型指南中文版的详细笔记,涵盖了泛型的基础知识、泛型类、泛型方法、通配符、擦除和翻译、类型安全、类型参数、实际类型参数、擦除、翻译、转型和 instanceof、数组、Class Literals as Run-...
#### 泛型定义 泛型是一种抽象概念,它允许你在定义类、接口或方法时使用类型参数。这些类型参数在编译时会被具体的实际类型替换。如果你定义了一个类`MyClass<T>`,这里的`T`就是一个类型参数。当你创建`MyClass`...
泛型是Java编程语言中的一个重要特性,它允许在定义类、接口和方法时指定类型参数,从而提高了代码的重用性和安全性。在这个“泛型实例详解”中,我们将通过7个具体的实例深入理解泛型的各种应用场景。 1. 普通泛型...
除了泛型类,我们还可以定义泛型方法。泛型方法的类型参数声明在方法签名中,例如: ```java public <T> void printList(List<T> list) { for (T item : list) { System.out.println(item); } } ``` 在这个例子...
Java泛型是Java编程语言中一个强大的特性,它允许在定义类、接口和方法时使用类型参数,从而实现参数化类型。泛型的主要目标是提高代码的类型安全性和重用性,减少类型转换的麻烦,并在编译时捕获可能的类型错误。...
泛型方法可以在非泛型类中定义,并且可以独立于类的其他部分使用泛型。例如: ```java public class Utility { public static <T> void swap(T[] array, int i, int j) { T temp = array[i]; array[i] = array[j]...
在Java编程语言中,泛型是一种强大的特性,它允许我们在定义类、接口和方法时,引入类型参数,从而实现参数化的类型。实例189 - 使用通配符增强泛型,着重探讨了如何通过通配符来提升泛型的灵活性和可复用性。这个...
在Java中,我们经常会看到一些通配符,例如T、E、K、V等,这些通配符都是Java泛型的通配符,它们的区别在于它们的名称和使用场景。 * T (type):表示不确定的Java类型,通常用作泛型类型参数。 * E (element):代表...