java泛型和通配符的使用

泛型机制

本质是参数化类型(与方法的形式参数比较,方法是参数化对象)。
优势:将类型检查由运行期提前到编译期。减少了很多错误。
泛型是jdk5.0的新特性。

集合中使用泛型

总结:

  • ① 集合接口或集合类在jdk5.0时都修改为带泛型的结构
  • ② 在实例化集合类时,可以指明具体的泛型类型
  • ③ 指明完以后,在集合类或接口中凡是定义类或接口时,内部结构(比如:方法、构造器、属性)使用到类的泛型的位置,都指定为实例化的泛型类型。
  • 比如:add(E e) ---->实例化以后:add(Integer e)
  • ④ 注意点:泛型的类型必须是类,不能是基本数据类型。需要用到基本数据类型的位置,拿包装类替换。
  • ⑤ 如果实例化时,没有指明泛型的类型。默认类型为java.lang.Object类型。
public class GenericTest {@Testpublic void test(){//没有使用泛型机制ArrayList list = new ArrayList();list.add(111);list.add(112);//问题一:类型不安全list.add("tom");for (Object score : list){//问题二:强制转换时,可能会报java.lang.ClassCastExceptionint sc = (int) score;System.out.println(sc);}}@Testpublic void test1(){//使用泛型,以ArrayList为例ArrayList<Integer> list = new ArrayList<Integer>();list.add(122);list.add(44);//编译时,会进行类型检查,保证数据的安全//list.add("tom");//方式一:for (Integer score:list) {//避免了强制转换操作System.out.println(score);}//方式二:IteratorIterator<Integer> iterator = list.iterator();while (iterator.hasNext()){int score = iterator.next();System.out.println(score);}//使用泛型,以HashMap为例Map<String, Integer> map = new HashMap<>();//jdk7新特性:类型推断HashMap<String, Integer> map1 = new HashMap<>();map.put("tom",111);map.put("jerry",25);//泛型的嵌套Set<Map.Entry<String, Integer>> entries = map.entrySet();Iterator<Map.Entry<String, Integer>> iterator1 = entries.iterator();while (iterator1.hasNext()){Map.Entry<String, Integer> next = iterator1.next();System.out.println(next);}}
}

自定义泛型结构

泛型类

public class Order<T> {String orderName;int orderId;//类的内部结构就可以使用类的泛型,可以把它看作是一个类型。T orderT;public Order(){}public Order(String orderName,int orderId,T orderT){this.orderName = orderName;this.orderId = orderId;this.orderT = orderT;}public T getOrderT() {return orderT;}public void setOrderT(T orderT) {this.orderT = orderT;}@Overridepublic String toString() {return "Order{" +"orderName='" + orderName + '\'' +", orderId=" + orderId +", orderT=" + orderT +'}';}
}

测试

public void test(){//如果定义了泛型类,实例化没有指明类的泛型,则认为此类型为Object类型。//要求:如果大家定义了类时带泛型的,建议在实例化时要指明类的泛型。Order order = new Order();order.setOrderT(123);order.setOrderT("aaa");//建议实例化时指明类的泛型Order<String> order1 = new Order<String>("aaa",101,"AA");order1.setOrderT("AA:hello");System.out.println(order.toString());}

自定义泛型类、泛型接口注意点补充

1、泛型类可能有多个参数,此时应将多个参数一起放在尖括号内。比如:<E1,E2,E3>
2、泛型类的构造器如下:public GenericClass(){},而下面的是错误的:public GenericClass(){}
3、实例化后,操作原来的泛型位置的结构必须与指定的泛型类型一致。
4、泛型不同的引用不能相互赋值。(尽管在编译时ArrayList 和 ArrayList 是两种类型,但是,在运行时只有一个ArrayList被加载到JVM中。)
5、泛型如果不指定,将被擦除,泛型对应的类型均按照Object处理,但不等价与Object。经验:泛型要使用一路都用。要不用,一路都不用。
6、如果泛型类是一个接口或抽象类,则不能创建泛型对象。
7、jdk1.7,泛型的简化操作:ArrayList flist = new ArrayList<>();
8、泛型的指定中不能使用基本数据类型,可以使用包装类替换。
9、在类/接口上声明的泛型,在本类或本接口中即代表某种类型,可以作为非静态属性的类型、非静态方法的参数类型、非静态方法的返回值类型。但在静态方法中不能使用类的泛型。
10、异常类不能是泛型的。
11、不能使用new E[]。但是可以:E[] elements = (E[]) new Object[capacity];参考:ArrayList源码中声明:Object[] elementData,而非泛型参数类型数组。
12、父类有泛型,子类可以选择保留泛型也可以选择指定泛型类型:

  • 子类不保留父类的泛型:按需实现
    没有类型 擦除
    具体类型
  • 子类保留父类的泛型:泛型子类
    全部保留
    部分保留
  • 结论:子类必须是“富二代”,子类出了指定或保留父类的泛型,还可以增加自已的泛型
    在这里插入图片描述
    静态方法中不能使用泛型说明
 //静态方法中不能使用泛型
//    public static void show(T orderT){
//        System.out.println(orderT);
//

在程序运行时,首先加载静态变量和静态方法,而参数T orderT的泛型定义时在加载静态变量和方法之后的

泛型方法

//泛型方法:在方法中出现了泛型结构,泛型方法与类的泛型参数没有任何关系。//换句话说,泛型方法所属类是不是泛型类没有任何关系。//泛型方法,可以声明为静态的。原因:泛型参数时在调用方法时确定的,并不是在实例化类时确定。public static <E> List<E> copyFromArrayToList(E[] arr){ArrayList<E> list = new ArrayList<>();for(E e: arr){list.add(e);}return list;}

泛型在继承方面的体现

 类A是类B的父类,G<A> 和  G<B>不具备子父类,关系,是并列关系。
public void test1(){Object obj = null;String str = null;obj = str;List<Object> list1 = null;List<String> list2 = null;//此时的List1和List2类型不具有子父类关系。//编译不通过
//        list1 = list2;}
 扩展:类A是类B的父类,A<G>是B<G>的父类。
 public void test2(){List<String> list1 = null;ArrayList<String> list2 = null;list1 = list2;}

通配符的使用

 类A是类B的父类,G<A> 和 G<B>是没有关系的,二者的共同父类是:G<?>
public class Test1 {@Testpublic void test1(){List<Object> list1 = null;List<String> list2 = null;List<?> list = null;list = list1;list = list2;print(list1);print(list2);}public void print(List<?> list){Iterator<?> iterator = list.iterator();while (iterator.hasNext()){Object obj = iterator.next();System.out.println(obj);}}
}

使用通配符后读取写入的要求

List<?> list = null;
List<String> list3 = new ArrayList<>();list3.add("aa");list3.add("bb");list = list3;//添加(写入):对于List<?>就不能向其内部添加数据。//出了添加NULL之外。//List.add("DD");编译器异常list.add(null);//获取(读取):允许读取数据,读取的数据类型为ObjectObject o = list.get(0);

有限制条件的通配符使用

通配符指定上限:extends,使用时指定的类型必须是继承某个类,或者实现某个接口,即<= 。
通配符指定下限:super,使用时指定的类型不能小于操作的类,即>= 。
举例:

<? extends Number> (无穷小,Number]:只允许泛型为Number即Number子类的引用调用。 <? super Number> [Number,无穷大):只允许泛型为Number即Number父类的引用调用。 <? extends Comparable>:只允许泛型为实现Comparable接口的实现类的引用调用。

测试
创建了两个类,Student,Person,Person是Student的父类

 /*? extends Person:G<? extends Person>可以作为G<A>和G<B>的父类,其中B是A的子类。? super Person:G<? super Person>可以作为G<A>和G<B>的父类,其中B是A的父类。*/
public void test2(){List<? extends Person> list1 = null;List<? super Person> list2 = null;List<Student> list3 = null;List<Person> list4 = null;List<Object> list5 = null;list1 = list3;list1 = list4;//list1 = list5;编译期异常//list2 = list3;编译期异常list2 = list4;list2 = list5;//读取数据list1 = list4;Person person = list1.get(0);//编译不通过//Student s = list1.get(0);list2 = list4;Object obj = list2.get(0);//编译不通过//Person p = list2.get(0);//写入数据//list1.add(new Student());编译不通过,list1   ?可能是比Student还要小的类,故不能添加。//编译通过list2.add(new Person());list2.add(new Student());}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/82203.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023河南萌新联赛第(五)场:郑州轻工业大学--买爱心气球

题目链接&#xff1a;A-买爱心气球_2023河南萌新联赛第&#xff08;五&#xff09;场&#xff1a;郑州轻工业大学 (nowcoder.com) 题目描述 Alice 和 Bob 是一对竞技编程选手&#xff0c;他们路过了一家气球店&#xff0c;发现有 m 个大爱心气球和 n 个小爱心气球。他们决定玩…

SSM个人博客项目

文章目录 SSM个人博客系统实现项目介绍 一、准备工作0. 创建项目添加对应依赖1. 数据库设计2. 定时实体类 二、功能实现1.统一功能处理统一返回格式统一异常处理定义登录拦截器 2. 注册登录实现生成获取验证码密码加盐实现注册功能登录功能注销功能 3.登录用户博客列表获取登录…

clickhouse断电重启故障解决方案

业务场景 公司的一个日志系统用到了clickhouse。一线运维反映说有个生产环境因为异常断电造成服务器重启。在执行日志系统的启动脚本时&#xff0c;一直报clickhouse启动不起来&#xff0c;日志系统无法使用。 问题排查 通过阅读启动脚本代码&#xff0c;以及启动日志系统&a…

Android 项目导入高德SDK初次上手

文章目录 一、前置知识&#xff1a;二、学习目标三、学习资料四、操作过程1、创建空项目2、高德 SDK 环境接入2.1 获取高德 key2.2下载 SDK 并导入2.2.1、下载SDK 文件2.2.2、SDK 导入项目2.2.3、清单文件配置2.2.4、隐私权限 3、显示地图 一、前置知识&#xff1a; 1、Java 基…

关于在c++中使用数组名作为函数参数,或者使用数组名的地址作为函数参数问题的一些研究

前言 使用数组名作为函数参数&#xff0c;或者使用数组名的地址作为函数参数&#xff0c;常常出现于对于字符串的读入问题之中。 常有以下两种写法&#xff1a; 这是使用数组名作为函数参数 #include<cstdio> char s[100]; int main() {scanf("%s",s); }在…

【如何构建自己的基于Arduino的Scara 机器人】

【如何构建自己的基于Arduino的Scara 机器人】 1. 概述2. Scara机器人3D模型3. 3D打印机器人零件4. 组装机器人5. SCARA机器人电路图6. 完成装配7. SCARA机器人的工作原理8. 对 SCARA 机器人进行编程 – Arduino 和处理代码9. 总结在本教程中,我们将学习如何构建基于 Arduino …

导出LLaMA ChatGlm2等LLM模型为onnx

通过onnx模型可以在支持onnx推理的推理引擎上进行推理&#xff0c;从而可以将LLM部署在更加广泛的平台上面。此外还可以具有避免pytorch依赖&#xff0c;获得更好的性能等优势。 这篇博客&#xff08;大模型LLaMa及周边项目&#xff08;二&#xff09; - 知乎&#xff09;进行…

leetcode 399-除法求值

法一&#xff1a;并查集 分析示例1&#xff1a; a / b 2.0 a/ b 2.0 a/b2.0&#xff0c;说明 a 2 b a2b a2b&#xff0c; a a a和 b b b在同一个集合中 b / c 3.0 b/c3.0 b/c3.0&#xff0c;说明 b 3 c b3c b3c&#xff0c; b b b和 c c c在同一个集合中 求 a / c a/…

微服务——ES实现自动补全

效果展示 在搜索框根据拼音首字母进行提示 拼音分词器 和IK中文分词器一样的用法&#xff0c;按照下面的顺序执行。 # 进入容器内部 docker exec -it elasticsearch /bin/bash# 在线下载并安装 ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch…

【C++】红黑树的原理与实现

文章目录 一、引言 二、红黑树的概念与性质 2、1 红黑树的概念 2、2 红黑树的性质 三、红黑树的定义与实现 3、1 红黑树的定义 3、2 插入新节点 3、2、1 默认插入红色节点 3、3 插入情况分类 3、3、1 情况一&#xff08;根据颜色向上调整&#xff09; 3、3、2 情况二&#xff0…

AIGC技术到底是什么?为什么这么火热?

AIGC技术到底是什么&#xff1f;为什么这么火热&#xff1f; ALCG技术到底是什么&#xff1f;AIGC技术的发展史AIGC技术特点AIGC技术主要用途ALGC技术未来发展 ALCG技术到底是什么&#xff1f; AIGC&#xff08;Artificial Intelligence in Game Creation&#xff09;技术是指…

OpenLayers实战,OpenLayers实现气象台风飓风运动轨迹运动动画,可调台风旋转速度和运动速度,静态图片旋转动画

专栏目录: OpenLayers实战进阶专栏目录 前言 本章使用OpenLayers实现气象中常用的台风或者飓风运动轨迹动画,支持调整台风图标旋转速度和运动速度。 不同的台风可以设置不同的运动速度和旋转速度,也可以通过变量控制图片不旋转。 本章图片使用静态png图片,并非gif动态图。…

中间件多版本冲突的4种解决方案和我们的选择

背景 在小小的公司里面&#xff0c;挖呀挖呀挖。最近又挖到坑里去了。一个稳定运行多年的应用&#xff0c;需要在里面支持多个版本的中间件客户端&#xff1b;而多个版本的客户端在一个应用里运行时会有同名类冲突的矛盾。在经过询问chatGPT&#xff0c;百度&#xff0c;googl…

在Python中定义Main函数

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 许多编程语言都有一个特殊的函数&#xff0c;当操作系统开始运行程序时会自动执行该函数。 这个函数通常被命名为main()&#xff0c;并且依据语言标准具有特定的返回类型和参数。 另一方面&#xff0c;Python解释器从文件…

SQL-每日一题【1179. 重新格式化部门表】

题目 部门表 Department&#xff1a; 编写一个 SQL 查询来重新格式化表&#xff0c;使得新的表中有一个部门 id 列和一些对应 每个月 的收入&#xff08;revenue&#xff09;列。 查询结果格式如下面的示例所示&#xff1a; 解题思路 1.题目要求我们重新格式化表&#xff0c;…

Sentieon | 应用教程: 关于读段组的建议

介绍 本文档描述了使用Sentieon Genomics软件时&#xff0c;推荐使用RGID字段以最小化潜在问题的用法。 本文档能帮助您确定设置所使用的bam文件中RG标签的不同字段的最佳实践方法。 RG字段及其用法的详细描述 RG字段的详细描述 SAM格式规范http://samtools.github.io/hts-…

Android Studio实现刮刮卡效果

代码和刮刮乐图片参考网络 实现效果 MainActivity import android.app.Activity; import android.os.Bundle;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentV…

教雅川学缠论06-中枢

本系列文章之前讲的内容都只有上升和下降两类趋势&#xff0c;并没有提及盘整&#xff0c;在缠论中&#xff0c;中枢这个新词汇用来定义盘整&#xff0c;中枢&#xff1a; 1.至少由5条线段&#xff08;或笔&#xff09;组成 2.中枢是有方向的&#xff0c;中枢左右两侧外面的线&…

【locust】使用locust + boomer实现对接口的压测

目录 背景 环境安装 脚本编写 master slave节点&#xff08;golang/boomer&#xff09; 问题 资料获取方法 背景 很早之前&#xff0c;考虑单机执行能力&#xff0c;使用locust做过公司短信网关的压测工作&#xff0c;后来发现了一个golang版本的locust&#xff0c;性能…

替换开源LDAP,某科技企业用宁盾目录统一身份,为业务敏捷提供支撑

客户介绍 某高科技企业成立于2015年&#xff0c;是一家深耕于大物流领域的人工智能公司&#xff0c;迄今为止已为全球16个国家和地区&#xff0c;120余家客户打造智能化升级体验&#xff0c;场景覆盖海陆空铁、工厂等货运物流领域。 该公司使用开源LDAP面临的挑战 挑战1 开源…