Java泛型–通配符
在编写通用代码时,我们还可以使用问号(?)作为类型,该类型代表未知类型,在Java泛型中称为通配符。
Java泛型和类关系中的通配符
我们可以使用通配符在通用类或者接口之间创建关系。
如果是非通用类
class A { /* ... */ } class B extends A { /* ... */ }
我们可以将子类的引用分配给父类。
B b = new B(); A a = b;
但是,相同的分配不适用于泛型类型。
List<B> lb = new ArrayList<>(); List<A> la = lb; // compile-time error
因此,即使A是父类,List <B>也不是List <A>的子类型。
我们也可以使用整数列表(List <Integer>)和数字列表(List <Number>)来理解它,其中Number是Integer的父类,但List <Integer>实际上不是List <Number>的子类型。 ,这两种类型无关。 List <Number>和List <Integer>的公共父级是List <?>。未知类型的列表,可以是List <Integer>,List <A>,List <String>等。
利用对两个通用类的公共父级的了解,我们将了解如何使用三种通配符在两个通用类(或者接口)之间创建有限关系。
Java泛型中的通配符类型
根据要施加在两个通用类之间的关系的限制,存在三种类型的通配符。
上限通配符
下界通配符
无限通配符
上限通配符
要声明上限通配符,请使用通配符('?'),后接extends关键字,后跟充当上限的类型。上限通配符匹配上限类型或者其任何子类。
例如List <?扩展Number>匹配Number类型或者其任何子类的列表,即List <Integer>,List <Double>,List <Number>。
上限通配符Java示例
假设我们想编写一个可以添加传递的列表的所有元素的方法。由于必须添加元素,因此List应该具有Integer,Float,Double类型的元素,因为Number是所有这些包装器类的超类,因此我们可以使用Number类创建上限。
import java.util.Arrays; import java.util.List; public class WildCard { public static void main(String[] args) { List<Integer> li = Arrays.asList(1, 2, 3, 4); System.out.println("sum = " + addListElements(li)); //List<Double> List<Double> ld = Arrays.asList(1.1, 2.2, 3.3, 4.4); System.out.println("sum = " + addListElements(ld)); } public static double addListElements(List<? extends Number> list){ double s = 0.0; for (Number n : list) { s += n.doubleValue(); } return s; } }
输出:
sum = 10.0 sum = 11.0
下界通配符
下限通配符使用通配符('?')表示,后跟super关键字,后跟下限。例如
<?超级A>
下界通配符将未知类型限制为特定类型或者该类型的超类型。例如,我们要编写一种适用于Integer列表和Integer的超类型(例如Integer,Number和Object)的方法,然后我们可以指定一个下界通配符,例如:
列表<?超级整数>
下界通配符Java示例
假设我们要编写一种方法,该方法可以在列表的末尾插入整数,并且可以是"对象列表","数字列表"或者"整数列表",然后可以使用Integer类创建下限。
import java.util.ArrayList; import java.util.List; public class WildCard { public static void main(String[] args) { // with List<Object> List<Object> lo = new ArrayList<Object>(); insertNumbers(lo); // with List<Number> List<Number> ln = new ArrayList<Number>(); insertNumbers(ln); // with List<Integer> List<Integer> li = new ArrayList<Integer>(); insertNumbers(li); } public static void insertNumbers(List<? super Integer> list) { for (int i = 1; i <= 10; i++) { list.add(i); } System.out.println("Elements in List- " + list); } }
输出:
Elements in List- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Elements in List- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Elements in List- [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Java泛型中的无界通配符
使用通配符(?)指定无限制的通配符类型。
例如,List <?>代表未知类型的列表。
无限通配符Java示例
假设我们要编写一个可以打印任何类型的List元素的方法,则应使用List <?>作为方法参数。使用List <Object>不能用作List <Integer>,List <String>,List <Double>不是List <Object>的子类型。
import java.util.Arrays; import java.util.List; public class WildCard { public static void main(String[] args) { // With List<Integer> List<Integer> li = Arrays.asList(5, 6, 7); printListElements(li); // With List<Double> List<Double> ld = Arrays.asList(1.2, 3.8, 8.2); printListElements(ld); } public static void printListElements(List<?> list){ for (Object e : list){ System.out.print(e + " "); } System.out.println(); } }
输出:
5 6 7 1.2 3.8 8.2