建设银行 福州招聘网站,官网网站怎么创建,长链接在线转化短链接,免费推广软件工具注#xff1a;以下内容基于Java 8#xff0c;所有代码都已在Java 8环境下测试通过 目录#xff1a;
Java泛型1——概述Java泛型2——泛型类Java泛型3——泛型接口Java泛型4——泛型方法Java泛型5——泛型通配符Java泛型6——类型擦除
什么是通配符
在Java中#xff0c;类… 注以下内容基于Java 8所有代码都已在Java 8环境下测试通过 目录
Java泛型1——概述Java泛型2——泛型类Java泛型3——泛型接口Java泛型4——泛型方法Java泛型5——泛型通配符Java泛型6——类型擦除
什么是通配符
在Java中类与类之间是有继承关系的。例如Integer 类继承自 Number 类因此Integer 类的对象可以赋值给 Number 类的引用即向上转型这是可以实现多态性的一个重要因素。但集合之间没有这种关系也就是 LinkedListInteger 和 LinkedListNumber之间并没有继承关系它们都是LinkedList 类。因此 LinkedListNumber 的集合并不能存放Integer 类型的变量虽然Integer 类继承自 Number 类。
比如下面这段代码
public class Main {private static void dealTest(TestFather test) {System.out.println(test.getClass());}public static void main(String[] args) {TestFather tesF new Test();TestChild testC new Test();Main.dealTest(tesF);Main.dealTest(testC);//编译器报错}
}class Father {}class Child extends Father {}class TestT {}这段代码定义了一个泛型类 Test 并定义了一个处理该类的静态方法 dealTest()该类接受一个 TestFather 对象作为参数。根据上面的介绍可以知道虽然Child 是 Father 的子类但TestChild 和 TestFather 之间并没有继承关系因此静态方法 dealTest()不能接受一个 TestSon 对象。因此若想让静态方法 dealTest()处理TestSon 对象还需对其进行重载
private static void dealTest(TestChild test) {}但这显然违背了多态性的设计理念而且这是编译器不允许的做法。如果能让 dealTest()方法不只接受TestFather对象而是让其接受TestXXX对象其中XXX代表某一类型内的类型参数那么上面这个问题就可以解决了。
这就是泛型通配符的作用泛型通配符用于限制类型参数的范围。
泛型通配符有 3 种形式 ? 无界通配符 ? extends T 有上界的通配符 ? super T 有下界的通配符
无界通配符
无界通配符?其中 ? 代表了任意一种数据类型。比如下面这段代码
public class Main {private static void dealTest(Test? test) {//?代表可以使用任意一种数据类型System.out.println(test.getClass());}public static void main(String[] args) {TestFather tesF new Test();TestChild testC new Test();TestInteger testI new Test();Main.dealTest(tesF);Main.dealTest(testC);Main.dealTest(testI);}
}class Father {}class Child extends Father {}class TestT {}由于使用了无界通配符dealTest()方法可以接受具有不同泛型参数的泛型类 Test的对象。
需要注意 不要混淆 TestObject 和 Test? Object 也是一种数据类型因此 TestObject 代表参数类型只能为Object的Test类 Test?代表参数类型可以是任意数据类型的Test类 最后不要在实例化泛型类的时候使用无界通配符? 集合的数据类型是不确定的因此我们只能往集合中添加null而且从其中取出的元素也只能赋值给Object对象。 import java.util.LinkedList;public class Main {public static void main(String[] args) {LinkedList? list new LinkedList();list.add(null);list.add(1);//编译器报错只能放入null}
}上界通配符
上界通配符? extends T其中T 代表了类型参数的上界。上界通配符将类型参数限制为特定类型T及其子类型。比如? extends Number表示类型参数可以是Number以及Number的子类。
可以使用上界通配符对上面的代码进行改写
public class Main {private static void dealTest(Test? extends Father test) {//? extends Father 代表可以使用 Father 及其子类作为类型参数System.out.println(test.getClass());}public static void main(String[] args) {TestFather fatherTest new Test();TestChild childTest new Test();Main.dealTest(fatherTest);Main.dealTest(childTest);}
}class Father {}class Child extends Father {}class TestT {}以 LinkedList? extends Number 为例在使用上界通配符的时候需要注意
LinkedList? extends Number 可以代表 LinkedList? extends Interger、 LinkedList? extends Double……但是不能指定 LinkedList? extends Number的数据类型。如下
import java.util.LinkedList;public class Main {public static void main(String[] args) {LinkedList? extends Number list1 new LinkedListInteger();//编译正确LinkedList? extends Number list2 new LinkedListDouble();//编译正确LinkedList? extends Number list3 new LinkedListObject();//编译器报错超出上界LinkedListNumber list4 new LinkedListInteger();//编译器报错list1.add(1);//编译器报错list1.add(2.3);//编译器报错list1.add(null);//编译正确}
}在看上面的代码之前需要明确一个概念那就是 LinkedList? extends Number表示这个集合可能是 LinkedList? extends Interger也可能是 LinkedList? extends Double但它什么都可能是的后果就是它什么也不是也就是说不能确定它到底是 LinkedList? extends Interger还是 LinkedList? extends Double或者其他什么集合所以也就不能往里面添加具体类型的元素因为不能确定它是什么类型的。但和无界通配符类似可以往里面添加null。
下界通配符
下界通配符? super T与上界通配符刚好相反T代表了类型参数的下界。类似地下界通配符将类型参数限制为特定类型T及其超类。比如? extends Integer表示类型参数可以是Integer以及Integer的超类。
可以使用下界通配符对上面的代码进行改写
public class Main {private static void dealTest(Test? super Child test) {//? super Child 代表可以使用 Child 及其超类作为类型参数System.out.println(test.getClass());}public static void main(String[] args) {TestFather fatherTest new Test();TestChild childTest new Test();Main.dealTest(fatherTest);Main.dealTest(childTest);}
}class Father {}class Child extends Father {}class TestT {}带有上界统配符的集合LinkedList? extends Number不能添加具体类型的元素但是带有下界通配符的集合LinkedList? super Number可以添加Number类及其子类的对象但是不能添加Number类的父类对象。因为LinkedList? extends Number最低也是个LinkedListNumber extends Number集合因此至少也能存放Number类对象所以也可以存放Number子类对象。但是LinkedList? extends Number的上限不知道所以类似于带有上界通配符的集合不能存放具体的数据类型LinkedList? extends Number也不能存放Number父类的对象。
import java.util.LinkedList;public class Main {public static void main(String[] args) {LinkedList? super Number list1 new LinkedListObject();//编译正确LinkedList? super Number list2 new LinkedListInteger();//编译器报错超出下界list1.add(1);//编译正确list1.add((Object) 2.5);//编译器报错不能存放 Number 类的父类对象}
}