java11-泛型及其使用(代码片段)

xiaobai1202 xiaobai1202     2022-12-09     253

关键词:

1.概述

    就本质而言 “泛型”的意思就是参数化类型。参数化类型很重要,因为使用该特性创建的类、接口以及方法可以以参数的形式指定操作的数据类型。

    泛型通俗的说就是方法的返回值或参数是不确定的,可以随创建该类对象时改变而改变。

    泛型提供了以前缺失的类安全性,并且还可以简化处理过程(例如避免进行强制类型转换等),提高了代码的可重用性。

2.一段简单的代码理解泛型

    对于下面这段代码我们定义了一个泛型类,类中有一个私有的泛型成员变量和几个泛型方法。从中我们可以看出,成员变量或者方法的参数或者返回值可能不是肯定的而是T,并且T是可变的,我们称这个T为泛型。

    main方法中分别使用这个泛型类操作了String 和 Integer 。如果没有泛型的支持,我们就只能写两个逻辑相同而参数不同的类或者进行强制转换,大大降低了代码重用和安全性。

 1 class MyGeneric<T> //声明一个泛型类
 2     private T obj;//可以使用泛型指定变量
 3     public MyGeneric() ; //无参构造
 4     public MyGeneric(T val)  //泛型构造
 5         this.obj = val;
 6     
 7     public T getObj()  //返回值
 8         return this.obj;
 9     
10     public String getName()  //得到确切类型
11         return this.obj.getClass().getName();
12     
13     
14 
15 
16 public class TestGeneric 
17     public static void main(String[] args) 
18         MyGeneric<String> str = new MyGeneric<String>("xiaobai"); //操作String 
19         System.out.println(str.getObj());
20         System.out.println(str.getName());
21         
22         MyGeneric<Integer> integer = new MyGeneric<Integer>(5); //操作Integer 
23         System.out.println(integer.getObj());
24         System.out.println(integer.getName());
25     
26 

3.几点注意

    1.泛型只是一个占位符,并没有实际意义,对于上面的例子,实际上操作的还是相应的数据类型(String和Integer)

    2.泛型只能使用引用类型,不支持基本数据类型(至于上面第22行可以直接写5是因为自动装箱)

    3.泛型引用之间是不兼容的,比如上面例子中的代码 str和integer两个实例对象是不兼容的(这是废话,泛型的目的就是提高通用性并限制操作类型)

4.多个泛型

    java中允许一个类有多个泛型,泛型之间使用逗号隔开即可(参看Map<K,V>)。并且泛型只是一个占位符,可以用任何字符表示

    

 1 class ManyGeneric<T,V,W>
 2     private T obj1;
 3     private V obj2;
 4     private W obj3;
 5     public T getObj1() 
 6         return obj1;
 7     
 8     public void setObj1(T obj1) 
 9         this.obj1 = obj1;
10     
11     public V getObj2() 
12         return obj2;
13     
14     public void setObj2(V obj2) 
15         this.obj2 = obj2;
16     
17     public W getObj3() 
18         return obj3;
19     
20     public void setObj3(W obj3) 
21         this.obj3 = obj3;
22     
23     
24 

5.泛型有界类型及泛型通配

  5.1 泛型通配

    不显式第指定泛型类型,而是使用 ?来表示泛型。当我们无法立即确定该类引用使用哪一个泛型(或至少可以确定他与某一个类的关系时)就使用这种形式。该通配一共有三种形式

      1.  <?> 形式: 不知道泛型到底是何形式·:使用这种方式时  就相当一  <? extends  Object  >  引用的实际对象只要是Object的子类就可以 

      

ArrayList<?> list = new ArrayList<String> (); //正确  
ArrayList<?> list = new ArrayList<Integer> (); //正确  

      2. <? extends xxx> 不知道具体是哪一种形式,但一定是xxx的子类  :引用的实际对象只能是 xxx类或xxx类的子类

ArrayList<? extends Number> list = new ArrayList<String> (); //错误 不是Number子类
ArrayList<? extends Number> list = new ArrayList<Integer> (); //正确  

      3. <? super xxx> 不确定哪一种形式,但一定是xxx的父类:引用的实际对象只能是  xxx 或 xxx的父类

ArrayList<? super Integer> list = new ArrayList<Number> (); //正确  
ArrayList<? super Integer> list = new ArrayList<Object> (); //正确 
ArrayList<? super Integer> list = new ArrayList<String> (); //错误 不是Integer的父类 

 

  5.2 有界类型

    可以使用任意参数来替换泛型类型是很好的,但是有一些时候我们可能希望对泛型类型进行一些限制。例如我们想在泛型中取得每一个值得double值,这个只有在类继承Number类才可以实现,否则就会编译错误。

    那么这个时候我们就可以使用有界类型进行限定,要求泛型类型必须是Number类或其子类。

    语法: T extends superClass  意思是说只允许superClass或者其子类的泛型。

见如下例子:

    错误的代码:

 1 class MyMathClass<T>
 2     T[] nums;
 3     public MyMathClass(T[] o) 
 4         this.nums = o;
 5     
 6     public double avg() 
 7         double sum = 0.0;
 8         for(int i=0;i<nums.length;i++) 
 9             sum += nums[i].doubleValue();  //报错误
10         
11         return sum/nums.length;
12     
13 
14 
15 public class TestGeneric 
16     public static void main(String[] args) 
17         Integer[] nums = new Integer[10];
18         for(int i=0;i<10;i++) 
19             nums[i] = (int)(Math.random()*100);
20         
21         MyMathClass<Integer> test = new MyMathClass<Integer>(nums);
22         test.avg();
23     
24 

    这里的代码第9行报错,因为不是所有的类型都有doubleValue方法。但是只要是继承了Number类就会有这个方法,所以我们使用有界类型进行限定

    限定方式  T extends Number

 1 class MyMathClass<T extends Number>
 2     T[] nums;
 3     public MyMathClass(T[] o) 
 4         this.nums = o;
 5     
 6     public double avg() 
 7         double sum = 0.0;
 8         for(int i=0;i<nums.length;i++) 
 9             sum += nums[i].doubleValue();  //报错误
10         
11         return sum/nums.length;
12     
13 
14 
15 public class TestGeneric 
16     public static void main(String[] args) 
17         Integer[] nums = new Integer[10];
18         for(int i=0;i<10;i++) 
19             nums[i] = (int)(Math.random()*100);
20         
21         MyMathClass<Integer> test = new MyMathClass<Integer>(nums);
22         System.out.println(test.avg());
23     
24 

    同理还可以使用多边界限定,当有多个边界的时候 使用&进行连接 :class MyMathClass<T extends Number & Serializable> 意思就是说只允许Number或其子类类型并且必须实现Serializable接口。

    注意有界类型与泛型通配的区别 (有界类型是声明泛型类指定泛型范围,而泛型通配是泛型引用指向泛型对象时的限制)

6.泛型擦除

    由于要与以前的代码相兼容,java中的泛型是伪泛型,在编译器编译过程中将会擦除泛型的所有信息,使用确切的引用类型将其代替。这就意味着如果没有显示的确定类型,就将使用Object代替,然后进行强制转换来保证类型的匹配

    这里就会发生一个模糊性问题,当有两个重载方法时,并且该方法唯一区别就是参数类型不同,则可能造成错误:

  技术图片

7. 使用泛型的一些限制

    7.1 不能实例化泛型参数

         T  obj = new T(); 是不合法的,因为编译器不知道要创建哪一种类型的对象,T只是一个占位符。

    7.2 静态成员限制

        静态成员不能使用泛型声明参数,同时,静态方法也不能操作泛型参数,因为静态属性需要随类加载,无法判断当前泛型的类型。

    7.3 数组的限制

        1.不能实例化泛型数组  原因参考7.1  

        2.不能声明指向特定泛型类型的数组

        技术图片

 

8.泛型对异常的限制

    泛型类不能继承Throwable类,这就意味着不能创建泛型异常类(也就是说泛型不支持异常,但是泛型类中依旧支持其他类型的异常)

    当然,泛型支持异常也没有什么意义。

 

java基础11:java泛型详解(代码片段)

Java基础11:Java泛型详解 泛型概述泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用。什么是泛型?为什么要使用泛型?泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形... 查看详情

java泛型详解(代码片段)

Java泛型详解泛型类及其方法普通类中的泛型方法泛型的范围限定1.用泛型限定T只能是某个类的子类2.限定下限3.无限定通配符泛型类及其方法泛型定义在类名上,,T可以是任意字符如A、B、C。类中的方法(普通方法、静态... 查看详情

#day11-java基础(代码片段)

...1可变参数2.2foreach输出2.3静态导入3、JDK三大主要特性——泛型3.1泛型的引出3.2泛型实现3.3通配符3.4泛型接口3.5泛型方法4、JDK三大主要特性——枚举4.1多例与枚举4.2Enum类面试题&# 查看详情

java基础知识点笔记总结(代码片段)

文章目录1.泛型定义2.泛型的小细节3.泛型自定义泛型4.泛型自定义泛型注意点5.泛型方法6.泛型继承注意点7.泛型通配符?8.泛型有限制条件的通配符?9.File类9.1File类的使用9.2file类的常用方法9.3file类总结10.IO流11.IO流体系对... 查看详情

java11泛型(代码片段)

https://blog.csdn.net/ChenRui_yz/article/details/1229356211泛型引子直接使用ArrayList不添加任何限制,则可以添加任意类型如下面,本来只能保存dog类型,添加cat类型就应该报错,但是这里没有,还是添加成功了importjava.util... 查看详情

java重点--泛型(代码片段)

文章目录💖泛型的概念✨使用泛型的好处与弊端✨定义和使用含有泛型的类✨定义和使用含有泛型的方法✨定义和使用含有泛型的接口✨泛型的通配符✨通配符的高级使用--受限泛型✨斗地主小案例💖泛型的概念泛型是... 查看详情

常用集合及其主要方法(代码片段)

C#中集合主要有泛型集合和非泛型集合。主要非泛型集合:ArrayList:动态数组,能够自动增长。常用方法:Add(objectvalue);Remove(objectvalue);RemoveAt(intindex);RemoveRange(intindex,intcount);Insert(intindex,objectvalue);Sort();Reverse();IndexOf(objec 查看详情

201771010102常惠琢《2018面向对象程序设计(java)》第10周学习总结(代码片段)

实验十  泛型程序设计技术实验时间 2018-11-11、实验目的与要求(1) 理解泛型概念;(2) 掌握泛型类的定义与使用;(3) 掌握泛型方法的声明与使用;(4) 掌握泛型接口的定义与实现;(5)了解泛型程序设计,... 查看详情

java泛型总结(代码片段)

一:什么是泛型?泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的... 查看详情

java_泛型笔记(代码片段)

文章目录Java_泛型简介Java_泛型的概念Java_为什么存在泛型Java_自定义泛型结构Java_泛型的声明Java_泛型的实例化Java_泛型类Java_泛型方法Java_泛型在继承上的体现Java_通配符的使用Java_泛型简介集合容器类在设计阶段/声明阶段不能确... 查看详情

详解java泛型(代码片段)

目录1为什么使用泛型2泛型的语法3.泛型的编译步骤3.1擦除机制3.2不可以实例化泛型类型数组4.了解裸类型5.泛型的上界6.泛型方法7.通配符(?)7.1理解通配符7.2通配符上界7.3通配符下界 8.包装类8.1基本数据类型对应包装类... 查看详情

java基础之泛型(代码片段)

泛型genericity格式:<自定义泛型无意义大写英文字母占位符>例:<T>Type<E>Element<K>Key<V>value泛型可以在方法,类,接口中使用泛型在方法中使用使用静态方法的泛型格式:publicstatic<T>返回值类型[自定义... 查看详情

初识java集合及包装类和泛型的基本使用(代码片段)

....Collection接口说明2.Collection示例3.Map接口说明4.Map实例三、泛型1.泛型的分类2.泛型的定义3.泛型背后作用时期和背后的简单原理4.泛型的使用5.泛型总结四、包装类1.基本数据类型和包装类直接的对应关系2.包装类的使用,装箱(b 查看详情

java泛型使用上下边界通配符解决泛型擦除问题(代码片段)

...符示例二、分析字节码的附加信息前言上一篇博客【Java泛型】泛型用法(泛型编译期擦除|上界通配符<?extendsT>|下界通配符<?superT>)一、泛型擦除章节中,讲到了泛型擦除问题,泛型只保留到了编译阶段,运行时就... 查看详情

c#11新特性:泛型attribute(代码片段)

之前使用JsonConverterAttribute,我们可以为任意类型自定义Json序列化。例如:[JsonConverter(typeof(UserJsonConverter))]public class User    public string Name  get; set;     public override string ToString()       查看详情

java泛型定义和基本使用笔记(代码片段)

1、泛型的作用以及定义1.概述 在我的理解中,泛型主要面向程序封装和架构设计的使用,在面向对象编程及各种设计模式中有非常广泛的应用。 为什么这么说呢,首先我们要理解什么是泛型,为什么要使用泛型&#... 查看详情

大数据必学java基础(五十五):泛型深入了解(代码片段)

文章目录泛型深入了解一、引入1、什么是泛型(Generic)2、没有泛型的时候使用集合3、JDK1.5以后开始使用泛型,集合中使用泛型4、泛型总结二、自定义泛型结构1、泛型类,泛型接口2、泛型方法3、泛型参数存在... 查看详情

十分钟深刻理解java高级——泛型(代码片段)

文章目录【1】什么是泛型?【2】为什么需要泛型?【3】如何使用泛型?一、泛型类和泛型接口二、一个类如何实现使用泛型接口的类?三、泛型方法的使用①什么是泛型方法?②普通方法:③泛型方法&#x... 查看详情