0


大数据必学Java基础(五十五):泛型深入了解

泛型深入了解

一、引入

1、什么是泛型(Generic)

泛型就相当于标签

形式:<>

集合容器类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的对象,所以在JDK1.5之前只能把元素类型设计为Object,

JDK1.5之 后使用泛型来解决。因为这个时候除了元素的类型不确定,其他的部分是确定的,例如关于这个元素如何保存,如何管理等是确定的,因此此时把元素的类型设计成一个参数,这个类型参数叫做泛型。

Collection<E>, List<E>, ArrayList<E> 这个<E>就是类型参数,即泛型。

2、没有泛型的时候使用集合

  1. package com.lanson.test01;
  2. import java.util.ArrayList;
  3. /**
  4. * @author : lanson
  5. */
  6. public class Test01 {
  7. //这是main方法,程序的入口
  8. public static void main(String[] args) {
  9. //创建一个ArrayList集合,向这个集合中存入学生的成绩:
  10. ArrayList al = new ArrayList();
  11. al.add(98);
  12. al.add(18);
  13. al.add(39);
  14. al.add(60);
  15. al.add(83);
  16. al.add("lili");
  17. //对集合遍历查看:
  18. for(Object obj:al){
  19. System.out.println(obj);
  20. }
  21. }
  22. }

如果不使用泛型的话,有缺点

一般我们在使用的时候基本上往集合中存入的都是相同类型的数据 --》便于管理,所以现在什么引用数据类型都可以存入集合,不方便!

3、JDK1.5以后开始使用泛型,集合中使用泛型

  1. package com.lanson.test01;
  2. import java.util.ArrayList;
  3. /**
  4. * @author : lanson
  5. */
  6. public class Test01 {
  7. //这是main方法,程序的入口
  8. public static void main(String[] args) {
  9. //创建一个ArrayList集合,向这个集合中存入学生的成绩:
  10. //加入泛型的优点:在编译时期就会对类型进行检查,不是泛型对应的类型就不可以添加入这个集合。
  11. ArrayList<Integer> al = new ArrayList<Integer>();
  12. al.add(98);
  13. al.add(18);
  14. al.add(39);
  15. al.add(60);
  16. al.add(83);
  17. /*al.add("lili");
  18. al.add(9.8);*/
  19. //对集合遍历查看:
  20. /*for(Object obj:al){
  21. System.out.println(obj);
  22. }*/
  23. for(Integer i:al){
  24. System.out.println(i);
  25. }
  26. }
  27. }

4、泛型总结

1、JDK1.5以后泛型实际就是 一个<>引起来的 参数类型,这个参数类型具体在使用的时候才会确定具体的类型。

2、使用了泛型以后,可以确定集合中存放数据的类型,在编译时期就可以检查出来。

3、使用泛型你可能觉得麻烦,实际使用了泛型才会简单,后续的遍历等操作简单。

4、泛型的类型:都是引用数据类型,不能是基本数据类型。

5、ArrayList<Integer> al = new ArrayList<Integer>();在JDK1.7以后可以写为:

  1. ArrayList<Integer> al = new ArrayList<>(); --<> ---钻石运算符

二、自定义泛型结构

1、泛型类,泛型接口

1.1、泛型类的定义和实例化

  1. package com.lanson.test02;
  2. /**
  3. * @author : lanson
  4. * GenericTes就是一个普通的类
  5. * GenericTest<E> 就是一个泛型类
  6. * <>里面就是一个参数类型,但是这个类型是什么呢?这个类型现在是不确定的,相当于一个占位
  7. * 但是现在确定的是这个类型一定是一个引用数据类型,而不是基本数据类型
  8. */
  9. public class GenericTest<E> {
  10. int age;
  11. String name;
  12. E sex;
  13. public void a(E n){
  14. }
  15. public void b(E[] m){
  16. }
  17. }
  18. class Test{
  19. //这是main方法,程序的入口
  20. public static void main(String[] args) {
  21. //GenericTest进行实例化:
  22. //(1)实例化的时候不指定泛型:如果实例化的时候不明确的指定类的泛型,那么认为此泛型为Object类型
  23. GenericTest gt1 = new GenericTest();
  24. gt1.a("abc");
  25. gt1.a(17);
  26. gt1.a(9.8);
  27. gt1.b(new String[]{"a","b","c"});
  28. //(2)实例化的时候指定泛型:---》推荐方式
  29. GenericTest<String> gt2 = new GenericTest<>();
  30. gt2.sex = "男";
  31. gt2.a("abc");
  32. gt2.b(new String[]{"a","b","c"});
  33. }
  34. }

1.2、继承情况

1.2.1、父类指定泛型

  1. class SubGenericTest extends GenericTest<Integer>{
  2. }
  3. class Demo{
  4. //这是main方法,程序的入口
  5. public static void main(String[] args) {
  6. //指定父类泛型,那么子类就不需要再指定泛型了,可以直接使用
  7. SubGenericTest sgt = new SubGenericTest();
  8. sgt.a(19);
  9. }
  10. }

1.2.2、父类不指定泛型

如果父类不指定泛型,那么子类也会变成一个泛型类,那这个E的类型可以在创建子类对象的时候确定:

  1. class SubGenericTest2<E> extends GenericTest<E>{
  2. }
  3. class Demo2{
  4. //这是main方法,程序的入口
  5. public static void main(String[] args) {
  6. SubGenericTest2<String> s = new SubGenericTest2<>();
  7. s.a("abc");
  8. s.sex = "女";
  9. }
  10. }

1.3、应用场合

1.4、细节

1.4.1、泛型类可以定义多个参数类型

1.4.2、泛型类的构造器的写法

1.4.3、不同的泛型的引用类型不可以相互赋值

1.4.4、泛型如果不指定,那么就会被擦除,反应对应的类型为Object类型

1.4.5、反省类中的静态方法不能使用类的泛型

1.4.6、不能直接使用E[]的创建

2、泛型方法

  1. package com.lanson.test04;
  2. /**
  3. * @author : lanson
  4. * 1.什么是泛型方法:
  5. * 不是带泛型的方法就是泛型方法
  6. * 泛型方法有要求:这个方法的泛型的参数类型要和当前的类的泛型无关
  7. * 换个角度:
  8. * 泛型方法对应的那个泛型参数类型 和 当前所在的这个类 是否是泛型类,泛型是啥 无关
  9. * 2.泛型方法定义的时候,前面要加上<T>
  10. * 原因:如果不加的话,会把T当做一种数据类型,然而代码中没有T类型那么就会报错
  11. * 3.T的类型是在调用方法的时候确定的
  12. * 4.泛型方法可否是静态方法?可以是静态方法
  13. */
  14. public class TestGeneric<E> {
  15. //不是泛型方法 (不能是静态方法)
  16. public static void a(E e){
  17. }
  18. //是泛型方法
  19. public static <T> void b(T t){
  20. }
  21. }
  22. class Demo{
  23. //这是main方法,程序的入口
  24. public static void main(String[] args) {
  25. TestGeneric<String> tg = new TestGeneric<>();
  26. tg.a("abc");
  27. tg.b("abc");
  28. tg.b(19);
  29. tg.b(true);
  30. }
  31. }

3、泛型参数存在继承关系的情况

4、通配符

4.1、在没有通配符的时候

下面的a方法,相当于方法的重复定义,报错

  1. public class Test {
  2. /*public void a(List<Object> list){
  3. }
  4. public void a(List<String> list){
  5. }
  6. public void a(List<Integer> list){
  7. }*/
  8. }

4.2、引入通配符

  1. public class Demo {
  2. //这是main方法,程序的入口
  3. public static void main(String[] args) {
  4. List<Object> list1 = new ArrayList<>();
  5. List<String> list2 = new ArrayList<>();
  6. List<Integer> list3 = new ArrayList<>();
  7. List<?> list = null;
  8. list = list1;
  9. list = list2;
  10. list = list3;
  11. }
  12. }

发现: A 和 B是子类父类的关系,G和G不存在子类父类关系,是并列的

加入通配符?后,G<?>就变成了 G和G的父类

4.3、使用通配符

  1. package com.lanson.test06;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. /**
  5. * @author : lanson
  6. */
  7. public class Test {
  8. /*public void a(List<Object> list){
  9. }
  10. public void a(List<String> list){
  11. }
  12. public void a(List<Integer> list){
  13. }*/
  14. public void a(List<?> list){
  15. //内部遍历的时候用Object即可,不用?
  16. for(Object a:list){
  17. System.out.println(a);
  18. }
  19. }
  20. }
  21. class T{
  22. //这是main方法,程序的入口
  23. public static void main(String[] args) {
  24. Test t = new Test();
  25. t.a(new ArrayList<Integer>());
  26. t.a(new ArrayList<String>());
  27. t.a(new ArrayList<Object>());
  28. }
  29. }

4.4、查看API中应用位置

5、使用通配符后的细节

  1. public class Test {
  2. public void a(List<?> list){
  3. //1.遍历:
  4. for(Object a:list){
  5. System.out.println(a);
  6. }
  7. //2.数据的写入操作 :
  8. //list.add("abc");-->出错,不能随意的添加数据
  9. list.add(null);
  10. //3.数据的读取操作:
  11. Object s = list.get(0);
  12. }
  13. }
  14. class T{
  15. //这是main方法,程序的入口
  16. public static void main(String[] args) {
  17. Test t = new Test();
  18. t.a(new ArrayList<Integer>());
  19. t.a(new ArrayList<String>());
  20. t.a(new ArrayList<Object>());
  21. }
  22. }

6、泛型受限

  1. package com.lanson.test07;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. /**
  5. * @author : lanson
  6. */
  7. public class Test {
  8. //这是main方法,程序的入口
  9. public static void main(String[] args) {
  10. //a,b,c三个集合是并列的关系:
  11. List<Object> a = new ArrayList<>();
  12. List<Person> b = new ArrayList<>();
  13. List<Student> c = new ArrayList<>();
  14. /*开始使用泛型受限:泛型的上限
  15. List<? extends Person>:
  16. 就相当于:
  17. List<? extends Person>是List<Person>的父类,是List<Person的子类>的父类
  18. */
  19. List<? extends Person> list1 = null;
  20. /*list1 = a;
  21. list1 = b;
  22. list1 = c;*/
  23. /*开始使用泛型受限:泛型的下限
  24. List<? super Person>
  25. 就相当于:
  26. List<? super Person>是List<Person>的父类,是List<Person的父类>的父类
  27. */
  28. List<? super Person> list2 = null;
  29. list2 = a;
  30. list2 = b;
  31. list3 = c;
  32. }
  33. }

  • 📢博客主页:https://lansonli.blog.csdn.net
  • 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
  • 📢本文由 Lansonli 原创,首发于 CSDN博客🙉
  • 📢停下休息的时候不要忘了别人还在奔跑,希望大家抓紧时间学习,全力奔赴更美好的生活✨
标签: java jvm servlet

本文转载自: https://blog.csdn.net/xiaoweite1/article/details/126493246
版权归原作者 Lansonli 所有, 如有侵权,请联系我们删除。

“大数据必学Java基础(五十五):泛型深入了解”的评论:

还没有评论