Java中泛型的?和T的区别

news/2025/2/9 8:05:32/

文章目录

  • 1、前言
    • 2、java中泛型?、T
      • 2.1、?、T的概念
      • 2.2、?、T的用法
        • 2.1.1、T用法
        • 2.1.2、?用法
      • 2.3、T、?在继承上的体现
      • 2.4、有限制通配符
        • 2.4.1、? extends A:
        • 2.4.2、? super A:
      • 2.5、无限制通配符和有限制通配符的数据读写问题
        • 2.5.1、无限制通配符读写
        • 2.5.2、有限制通配符读写
        • 1、? extends A:
        • 2、? super A:
    • 3、看下一些开源工具类中是如何使用

1、前言

关于java泛型中的T的区别之前一直停留在一些概念上,而并没有真正明白到底什么时候用,什么时候用T
并且之前虽然有写过抽象类,但一直用的是T、Q,没有用过,所以一直不明白到底怎么个用法,什么时候用。
但在这里还是得再提下T的概念。

2、java中泛型?、T

2.1、?、T的概念

T:代表一种类型。
:通配符,泛指所有的类型,是所有类型的父类。

2.2、?、T的用法

2.1.1、T用法

T:主要用于泛型类的定义泛型方法的定义,还有具体的变量的类型定义上。

  • 定义泛型类
//定一个动物类
class Animal<T>{}
  • 定义泛型方法
public <T> void eat(T[] a, Collection<T> c)
  • 修饰泛型类的属性成员:
class Animal<T>{T temp;
}

以上三种情况,在实际应用中,都指明了T,是一个具体的泛型类,都不能用代替。
因为?表示统配符,代表不是确定的类,表示任意类。

2.1.2、?用法

:一般是用于定义一个引用变量,以便实现“多态”调用(非真正意义上的多态)。

  • 定义为引用变量,可指向不同类型的变量

比如定义一个Animal的引用变量,不指定具体的泛型类型,而用通配符表示。如下:

//定义引用变量
List<> l1 = new ArrayList<String>();
l1 = new ArrayList<Integer>();

或者方法形参用于接收不同参数,实际也是一个引用变量,如下:

List<String> l1 = new ArrayList<String>();
List<Integer> l2 = new ArrayList<Integer>();
l1.add("AAA");
l1.add("BBB");
l2.add(111);
l2.add(222);public static void test1(List<?> l1){String join = Joiner.on(",").join(l1);System.out.println(join);
}

上面这个例子,感受到的力量没有。

2.3、T、?在继承上的体现

同一个类,如果泛型的具体类型不同,定义引用变量在不使用通配符的情况下,需要为每一个具体的实例创建对应的引用变量:

Animal<Cat> catA = new Animal<Cat>;
Animal<Dog> dogA = new Animal<Dog>;

如果用统配符:

Animal<> animal= new Animal<Cat>;
animal= new Animal<Dog>;

2.4、有限制通配符

2.4.1、? extends A:

? extends A:
G<? extends A> 可以作为G< A >和G< B >的父类,其中B是A的子类

注意: 这里同样? 只能是引用变量。

如:

 class A{}class B extends A{}class G<T>{}public void test3(){//G<? extends A> 是G<A>()、new G<B>()G<? extends A>  g = new G<A>();g = new G<B>();}

而如果用泛型来接收,那么只能是这样:

//需要定义2个变量
G<A> aa = new G<A>();
G<B> bb = new G<B>();

2.4.2、? super A:

? super A:
G<? super A> 可以作为G< A >和G< B >的父类,其中B是A的父类。

  class AA extends BB{}class BB{}public void test4(){G<? super AA>  g = new G<AA>();g = new G<BB>();}

同理,用泛型只能是这样:

G<AA> aa = new G<AA>();
G<BB> bb = new G<BB>();

2.5、无限制通配符和有限制通配符的数据读写问题

2.5.1、无限制通配符读写

读:可以读,尽管被无限制通配符修饰,但不管如何,容器里的元素永远是一个对象,也就是一个Object,所以可以用Object o这个引用变量来读取容器元素,即利用对象多态性。

写:不可以往容器里写入元素,因为写入的元素与容器的具体类型的关系不明确。比如:
可以定义成接收变量,但无法向里面添另数据。
在这里插入图片描述
list可以指向不同的具体容器,相对应的能接收的元素类型也跟着改变。因此往容器里添加数据时,会因为无法确定所能添加的具体元素类型为何,导致的类型不安全而编译不通过。

注意:可以添加null,因为null是所有类型的成员。

2.5.2、有限制通配符读写

1、? extends A:

读:往容器中添加的元素类型,一定是A或A的子类(如果是接口,则为实现类),因此读取出来的数据,一定可以用A类型来做引用(当然Object也可以)。

写:由于容器的具体类型未知,如果往容器添加元素,无法确保添加进去的具体数据是该容器具体类型的子类还是父类,因此存在类型不安全问题,所以是不允许往里添加数据的。

null可以添加

public static void test2(){List<String> l1 = new ArrayList<String>();l1.add("AAA");l1.add("BBB");read(l1);//这里我们传入格挡string类型的list,read_confirm方法中强制转换时,也要转成string,否则报错read_confirm(l1);
}
public static void read_confirm(List<?> list){//如果读的类型确认,也可以强制转换成 知道的类型List<String> str = (List<String>)list;//如果转成Integer会报错,则在遍历这个integers时会报错List<Integer> integers = (List<Integer>)list;for (String eachs : str) {System.out.print(eachs);}
}

2、? super A:

读:不管容器里添加的元素是A还是A的父类的实例对象,它们始终都是Object对象,因此可以读取,用Object类型来做引用(不能用A类型来做引用)。

写:只能写入A类型及其子类的实例对象。因为具体容器的类型最低等级是到A,所以不管容器具体类型为何,它都能保证>= A,所以A的实例化对象可以被写入(对象多态性),当然,既然作为父类的A可以被写入,那么A的子类自然而然也可以被写入容器里了。
注意:null仍然可以。

3、看下一些开源工具类中是如何使用

1、guava中的Joiner方法

List<String> l1 = new ArrayList<String>();
List<Integer> l2 = new ArrayList<Integer>();
l1.add("AAA");
l1.add("AAA");
l2.add(15);
l2.add(15);
//join方法的入参就是Iterable<?> ,因为list<Integer> list<String>都支持 
String join1 = Joiner.on(",").join(l1);
String join2 = Joiner.on(",").join(l2);

http://www.ppmy.cn/news/280686.html

相关文章

华硕rog魔霸新锐2022和联想拯救者Y9000P哪个好

ROG魔霸新锐其屏幕尺寸是15.6英寸&#xff0c;采用了2.5k的分辨率&#xff0c;165Hz的刷新率&#xff0c;300尼特的亮度&#xff0c;而拯救者y9000p的屏幕尺寸是16英寸&#xff0c;配备了16英寸的大屏幕&#xff0c;分辨率为2.5k&#xff0c;刷新率是165Hz&#xff0c;亮度是50…

联想电脑(win10)如何保存高清锁屏壁纸

和我一样用联想电脑的看过来了&#xff0c;每次打开电脑是不是都会有随机的好看的照片&#xff0c; 这些照片上现在还有一些励志的句子&#xff0c;反正就是让人看了就很想保存下来。 我记得以前的时候&#xff0c;在待机状态电脑屏幕的右上角就会有一个“照相机”的标志&…

网络安全怎么入行?有哪些误区需要避免?

目录 一、学习网络安全容易造成的误区 二、学习网络安全的基本准备与条件 三、网络安全学习路线 第一步&#xff1a;计算机基础 第二步&#xff1a;编程能力 第三步&#xff1a;安全初体验 第四步&#xff1a;分方向 怎么入门&#xff1f; 四、明确目标&#xff0c;定…

vue2vue3 el-table实现整行拖拽排序功能(使用sortablejs插件)

1、此功能已集成到[TTable组件中]—Vue2TTable组件 、Vue3TTable组件 2、最终效果 3、安装sortablejs npm install sortablejs --save4、Vue2实现方式 <template><el-tableref"el-table":data"tableData":class"{cursor:isCopy,row_sort:…

Django学习笔记-配置Docker、Git环境与项目创建

笔记内容转载自AcWing的Django框架课讲义&#xff0c;课程链接&#xff1a;AcWing Django框架课。 CONTENTS 1. 配置Docker环境2. Django项目创建3. Django App创建 1. 配置Docker环境 首先拉取一个 Ubuntu 镜像&#xff1a; docker pull ubuntu:20.04创建容器后进入容器配置…

第十七章:触发器

第十七章&#xff1a;触发器 17.1&#xff1a;触发器概述 ​ MySQL从5.0.2版本开始支持触发器。MySQL的触发器和存储过程一样&#xff0c;都是嵌入到MySQL服务器的一段程序。 ​ 触发器是由事件来触发某个操作&#xff0c;这些事件包括INSERT、UPDATE、DELETE事件。所谓事件…

安卓平板|markdown APP

想找一款安卓平板的markdown阅读器&#xff1f; 出发点错了&#xff0c;百度搜索一直是打markdown阅读器&#xff0c;一直找不到合适的&#xff1b;突然想到文本编辑器&#xff0c;于是就有了quickedict&#xff0c;可读可写&#xff0c;同时也说说其他。 MD阅读器&#xff1a…

微信怎么批量自动添加好友?

如何批量加客户资源到微信&#xff0c;怎么加微信好友&#xff0c;这个基本上熟悉的人都会知道。 实际上&#xff0c;你知道所有添加微信好友的方式吗&#xff1f;或者说&#xff0c;你知道如何批量加客户微信吗&#xff1f; 比如说在一定时间内&#xff0c;把你所有的客户资…