IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 泛型T?KV -> 正文阅读

[Java知识库]泛型T?KV

为什么要使用泛型?

第一是泛化。可以用T代表任意类型Java语言中引入泛型是一个较大的功能增强不仅语言、类型系统和编译器有了较大的变化,以支持泛型,而且类库也进行了大翻修,所以许多重要的类,比如集合框架,都已经成为泛型化的了,这带来了很多好处。
第二是类型安全。泛型的一个主要目标就是提高Java程序的类型安全,使用泛型可以使编译器知道变量的类型限制,进而可以在更高程度上验证类型假设。如果不用泛型,则必须使用强制类型转换,而强制类型转换不安全,在运行期可能发生ClassCast
Exception异常,如果使用泛型,则会在编译期就能发现该错误。
第三是消除强制类型转换。泛型可以消除源代码中的许多强制类型转换,这样可以使代码更加可读,并减少出错的机会。
第四是向后兼容。支持泛型的Java编译器(例如JDK1.5中的Javac)可以用来编译经过泛型扩充的Java程序(Generics
Java程序),但是现有的没有使用泛型扩充的Java程序仍然可以用这些编译器来编译。

这里的T,?,K,V都是泛型,不特指某个类型,可以通过一些extends,super方式限定类型。

T泛型一般用于类的构造中。

//构造个Test类,T extends Colleciton表面使用构造方法传入的参数必须是Collection或者Collection的子类。
public  class Test <T extends Collection> {
    T t ;
    //获取传入的参数,并赋值给t
    public Test(T t){
        this.t = t;
    }
}

?泛型用于参数传递。

?? extends? super
说明?不指定默认是Object。extends用于表示数据类型是该类的子类或者该类。super用于表示数据类型是该类或者该类的父类。

配合extends用法:

//这里指定传入的List集合的元素必须是Integer的子类或者Integer;
  public static void  get(List<? extends Integer> test){
    }

调用

传入Integer,可以不指定Integer,默认Integer。
在这里插入图片描述
传入String,编译器不让通过
在这里插入图片描述
如果不用extends,super限定类型,那么默认是Object。因为Object是所有对象的父类。

    public static void  get(List<?> test){
    }

调用默认是Object
在这里插入图片描述
也可以传入其他类型,比如Integer
在这里插入图片描述
配合super的用法

//必须是Integer的父类或者Integer
 public static void  get(List<? super Integer> s){
    }

默认是Integer
在这里插入图片描述
可以传入Integer的父类,如Object
在这里插入图片描述
T和?的主要区别就是,T是用于类中的,因为它能当成给类对象进行修饰,用T来指代传入的数据类型。而?不能,他不能以?t的形式出现,它用来限定传入参数的数据类型,而T不能。

K,V用来指定键值对对象的泛型。如HashMap

	//前面的<K,V>用来指定数据类型,后面的<K,V>指代实际的HashMap的键值对的类型。
    public static   <K extends String,V extends Integer>HashMap<K,V> test()  {
        HashMap<String, Integer> stringIntegerHashMap =  new HashMap<>();
            stringIntegerHashMap.put("123",123);
            //由于实际是K,V类型,所以要强制转换。
        return (HashMap<K, V>) stringIntegerHashMap;
    }

接收如下,由于对K,V进行了限制,K是String或String的子类,V是Integer或Integer的子类,于是编译器能自动判别接收的类型。能够以String,Integer的类型接收HashMap。而不是以K,V接收。
在这里插入图片描述

那么可能有人有疑问了,这里的K,V能否用?,?来替代呢?
答案是肯定的,可以。因为?也是用来限定参数数据类型的。那么上面的写法可以用下面的写法来替代。

    public static   HashMap<? extends String,?extends Integer> test()  {
        HashMap<String, Integer> stringIntegerHashMap =  new HashMap<>();
            stringIntegerHashMap.put("123",123);
        return stringIntegerHashMap;
    }

接收如下
在这里插入图片描述

可以看到,明明我实际已经是传递String,Integer类型了,但是接收的时候它还是当做<?extends String,? extends Integer>接收。
直接使用String,Integer接收还需要强制转换如下
在这里插入图片描述
因此,在键值对中的写法,鼓励还是使用K,V代指泛型。
而以List<>的泛型写法如下

    public static <T extends String>ArrayList<T>   test()  {
        return (ArrayList<T>) new ArrayList<String>();
    }

接收如下
在这里插入图片描述
而以?的写法定义和接收如下

    public static ArrayList<? extends String>   test()  {
        return new ArrayList<String>();
    }

接收
在这里插入图片描述
可以看到,T,K,V泛型可以当做是已经确定的了的泛型,只要返回的参数符合其类型,那么编译器就正确识别并接收。而?是不确定的,只有在作为参数接收的时候,编译器能识别,而作为返回值时,编译器无法识别返回值的具体类型,需要进行强制转换。

总结:使用泛型是为了减少类型之间的强制转换,让编译器能够在未编译时就能知道用户的参数定义是否正确,而不是在运行阶段才能发现并运行异常。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-10-03 16:57:32  更:2021-10-03 16:59:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 19:22:59-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码