也是重新温习了下泛型与反射,反射基本就是一些api理解即可,不过需要注意类加载器原理,而泛型则需要理解其设计思想,可以代替Object,更加灵活,可读性强。

泛型

泛型如果指定后,编译阶段就会检查,不让乱输其他类型,必须是引用类型; 如果不指定就默认Object

// 如果指定泛型, 就必须存指定的类型  Iterator<String> iterator = arrayList.iterator();
List<String> arrayList = new ArrayList<>();
​
/*** new 集合 如果没有指定泛型* 存放的类型是为Object类型*/
ArrayList arrayList = new ArrayList();
// Iterator iterator = arrayList.iterator();
//如果想要精确获取,则String str = (String)iterator.next; 需要强转,不过因为存放的不是一种类型,所以还要判断(instanceof),否则可能转换异常
1.Java 泛型 (generics) 是 JDK 5 中引入的一个新特性,泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型。
2. 早期的时候,使用 Object 来代表任意类型。但是这样在向上转型的是没有问题的,但是在向下转型的时候存在类型转换的问题,这样的程序其实是不安全的。所以 Java 在 JDK5 之后提供了泛型来解决这个问题
3. 泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。
4. 泛型是一种把类型的明确工作推迟到创建对象或者调用方法的时候才去明确的特殊类型。
注意:类型参数只能代表引用型类型,不能是原始类型 (像 int,double,char 的等)。
泛型可以使用在 方法、接口、类 分别称作为:泛型类、泛型方法、泛型接口。

泛型类

泛型类定义的格式: 格式:修饰符 class 类名 <类型>{} 范例:public class Student<T>{} 此处 T 可以随便写为任意标识,T、E、K、V 等型式的参数常用于表示泛型;

/*** 泛型类优化*/
public class Student<T> {private T number;public T show(T t) {return t;}
}

缺点就是: 如果想要传递不同类型的方法则需要创建指明多个对象; (Object强转就不考虑了,因为需要先instanceof判断类型)

泛型方法

可以优化掉方法重载

格式:修饰符 <类型> 返回值类型 方法名 (类型 变量名){...} 范例:public<T> void show(T t){...}

public class Student {public <T> T show(T t) {return t;}
}

优点: 可以只new一个对象,然后直接传递不同类型的方法,此时会正常获取,而且我们也不用手动<指定类型>,ctrl alt v 可以正常解析获取

泛型接口

格式:修饰符 interface 接口名 <类型>{...} 范例:public interface MayiktInterface <T>{...}

public interface Student<T> {T show(T t) {return t;} // 默认public
}
// 如果直接实现,还是Object
public class StudentImpl<T> implements Student<T> {@Overridepublic T show(T t) {return t; // 而且此时可以发现,创建后传参,前方会隐式显示参数的名字,t}
}
public class Test01 {public static void main(String[] args) {Student<String> stringMayikt = new StudentImpl<>();String show = stringMayikt.show("36");System.out.println(show);}
}

方法:

public interface Mayikt<T> {<M> T show(T t, M m); // 如果写成<T> T show (T t); 则这个T对应泛型方法,而不是类上的T,所以下方如果实现则变成T1好区分
}
public class MayiktImpl<T> implements MayiktInterface<T> {@Override public <M> T show(T t, M m) {System.out.println(m);return t;}
}

泛型通配符

  1. 类型通配符 一般用于接受使用,不能够做添加。

  2. List : 表示元素类型未知的 list,它的元素可以匹配任何类型。

  3. 带通配符的 List 仅表示它是各种泛型 List 的父类,并不能把元素添加到其中。 (而且也是需要判断类型的,否则此时获得的是Object)

  4. 也是可以遍历的,但是不能添加,比如 .add方法

  5. 类型通配符上限:<? extends 类型> List<? extends MayiktParent>: 它表示的类型是 MayiktParent 或者子类型。

  6. 类型通配符下限:<? super 类型> List<? super MayiktParent>: 它表示的类型是 MayiktParent 或者其父类型

/*** 定义的 printList方法 明确知道 接受具体 list泛型 是什么类型* List<?> 只能够用于接受 ?------- 可以接受所有的泛型类型 不能够用于添加* 是可以做get操作 获取到类型是为Object类型** @param stringList*/
public static void printList(List<?> stringList) { // List<? extends People> stringList 也可以这样传参Object o = stringList.get(0); // 直接获取到的是Object类型Iterator<?> iterator = stringList.iterator(); // 拿到的也是?while (iterator.hasNext()){System.out.println(iterator.next()); // 如果想要强转iterator.next()为指定的对象,则instanceof判断一下}
}

可变参数

  1. 可变参数 又称 参数个数可变,用作方法的形参出现,那么方法参数个数就是 可变 的了。 (底层基于数组实现)

  2. 书写格式: 2.1 格式:修饰符 返回值类型 方法名 (数据类型... 量名){} 2.2 范例:public static int sum (int... a) {}

  3. 可变参数 注意事项: 这里的 可变参数变量 其实是一个数组。 如果一个方法 有多个参数,包含可变参数,可变参数要放在最后

public static int sum(int... a) {int sum = 0;for (int i = 0; i < a.length; i++) {sum+=a[i];}return sum;
}

ArrayList中的asList就用到了可变参数 T...

public class Test04 {public static void main(String[] args) {/*** 使用 Arrays.asList 定义好的 元素个数 是不能够发生变化的*/List<String> strings = Arrays.asList("mayikt", "meite", "wangmazi");// 注意 如果使用Arrays.asList 方法 创建的 集合 不能够添加和删除strings.set(0, "6666"); // 可以修改,不能add和removeSystem.out.println(strings);}
}

擦除机制(底层)

说明:将一个 List 集合 泛型赋值给一个没有使用到泛型 List 集合 直接去除泛型 --- 擦除机制

反编译后可以发现运行阶段没有泛型

List<String> strs = new ArrayList<String>();
strs.add("mayikt");
//说明:将一个List集合 泛型赋值给一个未使用泛型的集合会直接去除掉
List list = strs; // 此时仍然可以添加Object类型变量

反射

1.Java 反射机制的核心是在程序运行时动态加载类并获取类的详细信息,从而操作类或对象的属性和方法。本质是 JVM 得到 class 对象之后,再通过 class 对象进行反编译,从而获取对象的各种信息。

2.Java 属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到 JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。

Java 反射机制可以动态方式获取到 class 相关信息 class 中成员方法、属性,反射技术灵活调用方法 或者给我们成员属性赋值,class.forName 初始化对象(创建我们的对象)

类加载器

xxx.getClass().getClassLoader().loadClass();
类加载器的主要作用:
类加载器(ClassLoader)是 Java 虚拟机中负责加载类的组件,它的核心职责是将类的字节码文件(.class文件)加载到 JVM 中,并生成对应的Class对象,以便 JVM 可以使用这些类进行实例化、方法调用等操作。具体过程如下:
​
加载:在这一阶段,类加载器会根据类的全限定名(包名 + 类名)找到对应的.class文件,通过 IO 操作读取其字节码数据,然后在 JVM 内存中创建一个对应的Class对象 。这就好比从磁盘这个 “仓库” 中把类的 “蓝图” 搬运到 JVM 的 “工作区”,并整理成 JVM 能识别的格式。
​
链接:包括验证(确保字节码符合 JVM 规范,如文件格式正确、字节码指令合法等)、准备(为类的静态变量分配内存并设置初始值,比如static int num = 10; 在准备阶段num会被初始化为 0 )、解析(将符号引用转换为直接引用,让 JVM 能准确找到要访问的类、方法、变量等)。
​
初始化:对类的静态变量进行赋值和执行静态代码块,使类进入可使用状态。
​
对于同一个类,类加载器不一定只会执行一次,这要分情况来看:
​
同一个类加载器:在 Java 中,为了提高性能和避免重复加载,JVM 会维护一个已加载类的缓存。当使用同一个类加载器尝试加载一个已经加载过的类时,类加载器会直接从缓存中返回已存在的Class对象,而不会再次执行完整的加载流程。 例如,在一个普通的 Java 应用中,自定义一个类加载器加载某个类,后续再次请求加载该类时,不会重复加载。
​
不同类加载器:如果使用不同的类加载器去加载同一个类(比如自定义了多个不同的类加载器,或者应用程序中同时存在系统类加载器和自定义类加载器 ),由于类加载器的命名空间相互隔离,每个类加载器都有自己独立的已加载类缓存,那么就会出现多次加载同一个类的情况,且不同类加载器加载出来的类,在 JVM 中被视为不同的类。例如,通过自定义类加载器加载一个User类,再通过系统类加载器加载User类,这两个User类的Class对象在 JVM 中是不同的,它们之间不能进行类型转换等操作。
​
不过,对于 Java 核心类库中的类(由启动类加载器加载),在 JVM 启动过程中会被加载一次,之后在整个应用运行期间,不会再重复加载 。但对于自定义类或其他非核心类,类加载器的加载次数取决于类加载器的使用方式和 JVM 的运行逻辑。

类加载器: 当我们new出自定义对象时,如果发现没有加载到程序内存中,此时就会开始执行类加载器将该对象加载,而项目刚开始运行的时候应该底层依赖了其他类,所以其他先进行加载

class不管什么方式获取到的,都是唯一的

public class Test13 {public static void main(String[] args) throws ClassNotFoundException {// 1.获取class方式 直接类名称.Class<MayiktUserEntity> mayiktUserEntityClass = MayiktUserEntity.class;// 2.new 对象 通过对象获取class  springioc容器 根据class获取对象MayiktUserEntity mayiktUserEntity = new MayiktUserEntity();Class<? extends MayiktUserEntity> aClass = mayiktUserEntity.getClass();// 类的完整路径地址 包的名称+类名称组合  第三种,企业使用最多,不过因为怕路径写错,所以也要抛异常Class<?> aClass1 = Class.forName("com.mayikt.entity.MayiktUserEntity");}
}

注意 : 上述三种获取到的class都是完全相同的,因为运行期间,一个类只会产生一个class

反射应用的几个常见场景:
1.JDBC 中 Class.forName ("com.mysql.jdbc.Driver")---- 反射技术加载 mysql 驱动
2.Spring 底层基于反射初始化对象
3.(写一套自己)第三方框架扩展功能 代理设计模式

初始化对象

注意: 上边俩个创建对象代码都是只能获取公有的,如果想获取全部方法,那么就Declared即可

(1)批量获取的方法:
public Constructor[] getConstructors():所有"公有的"构造方法
public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
(2)单个获取的方法,并调用:
public Constructor getConstructor(Class... parameterTypes):获取单个的"公有的"构造方法:
public Constructor getDeclaredConstructor(Class... parameterTypes):获取"某个构造方法"
(3) 调用构造方法:
Constructor-->newInstance(Object... initargs)
newInstance是 Constructor类的方法(管理构造函数的类)
api的解释为: newInstance(Object... initargs) ,使用此 Constructor 对象表示的构造方法来创建
它的返回值是T类型,所以newInstance是创建了一个构造方法的声明类的新实例对象,并为之调用。

获取成员属性

获取成员变量并调用:

  1. 批量的 1.1 Field[] getFields():获取所有的"公有字段" 1.2 Field[] getDeclaredFields():获取所有字段,包括: 私有、受保护、默认、公有;

  2. 获取单个的: 2.1.public Field getField(String fieldName):获取某个"公有的"字段; 2.2.public Field getDeclaredField(String fieldName):获取某个字段(可以是私有的)

  3. 设置字段的值 需要注意权限问题: 3.1.Field --> public void set(Object obj,Object value): 3.2.参数说明: 3.3.obj:要设置的字段所在的对象;

public class Test15 {public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {// 获取class成员属性(反射给成员属性赋值、反射调用我们方法)//1.java反射技术 创建对象Class<?> aClass = Class.forName("com.mayikt.entity.MayiktUserEntity");//Field[] fields = aClass.getFields();) // 获取所有的"公有字段"Field[] fields = aClass.getDeclaredFields(); // 获取所有字段//2.获取单个的:for (int i = 0; i < fields.length; i++) {System.out.println(fields[i]);}// 如何给成员属性赋值呢?MayiktUserEntity mayiktUserEntity = (MayiktUserEntity) aClass.newInstance();Field userNameField = aClass.getDeclaredField("userName");// 反射技术给私有成员属性赋值  参数1:传递对象  参数2:赋值的内容// 如果通过反射技术给私有成员属性赋值的情况下 设置下访问的权限userNameField.setAccessible(true); // 先设置权限才可赋值userNameField.set(mayiktUserEntity, "mayikt666"); // 这个也是获取到对象,然后再修改System.out.println(mayiktUserEntity.getUserName());}
}

调用方法

  1. 所有的方法: 1.1.public Method [] getMethods (): 获取所有 "公有方法";(包含了父类的方法也包含 Object 类) 1.2.public Method [] getDeclaredMethods (): 获取所有的成员方法,包括私有的 (不包括继承的)

  2. 获取单个的方法: 2.1.public Method getMethod (String name,Class... parameterTypes): 参数: name:方法名; Class ...:形参的Class类型对象 public Method getDeclaredMethod(String name,Class... parameterTypes)

  3. 调用方法: Method --> public Object invoke (Object obj,Object... args): 参数说明: obj: 要调用方法的对象;

注意 此时获取到的公有方法还包含了Object,这是和其他不同的地方

Method addUserMethod = aClass.getDeclaredMethod("addUser", String.class, Integer.class);
MayiktUserEntity mayiktUserEntity = (MayiktUserEntity) aClass.newInstance();
addUserMethod.setAccessible(true);
String result = (String) addUserMethod.invoke(mayiktUserEntity, "mayikt", 22);
System.out.println(result); //看自己编写的方法有没有返回值可获取

也是调用修改方法或属性强,如果是私有设置一下权限即可

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

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

相关文章

Docker端口映射与数据卷完全指南

目录 Docker端口映射与数据卷完全指南 1. 端口映射:连接Docker容器与外部世界 1.1 为什么需要端口映射 1.2 实现端口映射 1.3 查看端口映射 1.4 修改端口映射(高级操作) 2. 数据卷:Docker数据持久化解决方案 2.1 数据持久化问题 2.2 数据卷的含义 2.3 数据卷的特点 2.4 挂载…

【Linux篇章】穿越网络迷雾:揭开 HTTP 应用层协议的终极奥秘!从请求响应到实战编程,从静态网页到动态交互,一文带你全面吃透并征服 HTTP 协议,打造属于你的 Web 通信利刃!

本篇摘要 本篇将介绍何为HTTP协议&#xff0c;以及它的请求与答复信息的格式&#xff08;请求行&#xff0c;请求包头&#xff0c;正文等&#xff09;&#xff0c;对一些比较重要的部分来展开讲解&#xff0c;其他不常用的即一概而过&#xff0c;从静态网页到动态网页的过渡&a…

QT的项目pro qmake编译

使用qmake管理Qt库的子工程示例-CSDN博客 top_srcdir top_builddir

语音交互系统意图识别介绍和构建

一、意图识别简介**意图识别&#xff08;Intent Recognition&#xff09;**是语音交互系统的核心组件&#xff0c;用于理解用户语音输入背后的真实目的&#xff08;如查询天气、播放音乐等&#xff09;。输入&#xff1a;语音转文本&#xff08;ASR输出&#xff09;的语句输出&…

DINOv3 重磅发布

2025年8月14日 Meta 发布了 DINOv3 。 主页&#xff1a;https://ai.meta.com/dinov3/ 论文&#xff1a;DINOv3 HuggingFace地址&#xff1a;https://huggingface.co/collections/facebook/dinov3-68924841bd6b561778e31009 官方博客&#xff1a;https://ai.meta.com/blog/d…

ansible playbook 实战案例roles | 实现基于firewalld添加端口

文章目录一、核心功能描述二、roles内容2.1 文件结构2.2 主配置文件2.3 tasks文件内容免费个人运维知识库&#xff0c;欢迎您的订阅&#xff1a;literator_ray.flowus.cn 一、核心功能描述 这个 Ansible Role (firewalld) 的核心功能是&#xff1a;动态地、安全地配置 firewal…

【深度学习实战(55)】记录一次在新服务器上使用docker的流程

使用docker&#xff1a;apt-get install dockersudo usermod -aG docker sliu &#xff08;将用户 sliu 添加到 docker 用户组&#xff09;newgrp docker &#xff08;刷新&#xff09;docker imagessudo docker load --input /home/sliu/workspace/env/shuai_docker.tar &…

面试后的跟进策略:如何提高录用几率并留下专业印象

面试结束后&#xff0c;许多求职者认为自己的任务已经完成&#xff0c;只需等待结果通知。然而&#xff0c;面试后的跟进策略同样是求职过程中的关键环节&#xff0c;它不仅能提高你的录用几率&#xff0c;还能展示你的专业素养和持续兴趣。本文将结合酷酷面试平台的专业建议&a…

深入解析RAGFlow六阶段架构

下面用“流程图 六阶段拆解”的方式&#xff0c;把 RAGFlow 的完整流程逐层剖开&#xff0c;力求把每一步的输入、输出、可选策略、内部机制都讲清楚。 ──────────────────────── 一、总览图&#xff08;先建立体感&#xff09; 用户提问 │ ├─→【…

Go语言中的迭代器模式与安全访问实践

Go语言中的迭代器模式与安全访问实践 1. 迭代器模式在Go中的演进 1.1 传统迭代器模式回顾 在传统面向对象语言中&#xff0c;迭代器模式通常涉及三个核心组件&#xff1a;可迭代集合接口(Iterable)迭代器接口(Iterator)具体实现类// 传统迭代器模式示例 type Iterator interfac…

从零开始:JDK 在 Windows、macOS 和 Linux 上的下载、安装与环境变量配置

前言 在进入 Java 世界之前&#xff0c;搭建一个稳定、可用的开发环境是每个开发者必须迈过的第一道门槛。JDK&#xff08;Java Development Kit&#xff09;作为 Java 程序开发的核心工具包&#xff0c;其正确安装与环境变量配置直接关系到后续编译、运行、调试等所有开发流程…

【音视频】芯片、方案、市场信息收集

系统级芯片安霸&#xff08;Ambarella&#xff09;Ambarella H22/H32&#xff1a;高端方案&#xff0c;支持8K/4K高帧率录制&#xff0c;低功耗&#xff0c;广泛用于GoPro Hero 11/12、Insta360等旗舰机型。 Ambarella A12/A10&#xff1a;早期主流方案&#xff0c;支持4K60fps…

中科米堆CASAIM提供机加工件来料自动化测量尺寸方案

机加工行业面临日益严格的质量追溯要求&#xff0c;来料质量的稳定性直接影响着后续生产效率与成品合格率。传统人工检测方式受限于接触式工具的测量精度与操作效率&#xff0c;难以应对小批量、多品种的现代生产需求。传统机加工件来料检测长期面临这些问题&#xff1a;其一&a…

MySQL只操作同一条记录也会死锁吗?

大家好&#xff0c;我是锋哥。今天分享关于【MySQL只操作同一条记录也会死锁吗?】面试题。希望对大家有帮助&#xff1b; MySQL只操作同一条记录也会死锁吗? 超硬核AI学习资料&#xff0c;现在永久免费了&#xff01; 在 MySQL 中&#xff0c;死锁通常是由于多个事务对不同…

知识蒸馏 Knowledge Distillation 论文 Generalized Knowledge Distillation (GKD) 乘法法则、全概率公式、贝叶斯定理

知识蒸馏 Knowledge Distillation 论文 Generalized Knowledge Distillation (GKD) 乘法法则、全概率公式、贝叶斯定理 flyfish 代码实践 On-Policy Distillation of Language Models: Learning from Self-Generated Mistakes 设定&#xff08;方便算数&#xff09;&#x…

Fastjson 2.x踩坑——序列化Java字段为null值默认输出

先上无法实现效果的代码&#xff0c;我的目的是序列化时如果数字型字段为null则填0&#xff0c;尽可能保证数据整齐。 Data NoArgsConstructor AllArgsConstructor ToString JSONType(serializeFeatures {JSONWriter.Feature.WriteNulls,JSONWriter.Feature.WriteMapNullValue…

4G高负荷解决方案

4G高负荷解决方案 一、网络优化手段&#xff08;低成本优先&#xff09;参数优化 调整功率控制、负荷均衡参数。优化小区重选与切换参数&#xff0c;避免高负荷小区拥塞。负荷均衡 开启 MLB&#xff08;Mobility Load Balancing&#xff0c;移动负荷均衡&#xff09;。引导用户…

K8S 安装部署 Rocky Linux 10.0 + Docker + Containerd + Calico

Docker Containerd Flannel 安装部署K8S 系统环境准备 # 1. 设置主机名 hostnamectl set-hostname k8s-n1 && bash# hostnamectl set-hostname k8s-n2 && bash # hostnamectl set-hostname k8s-n3 && bash# 2. 删除系统自带的容器软件&#xff08;可…

新华三H3CNE网络工程师认证—等价路由

等价路由就是“去同一个地方有多条路&#xff0c;时间一样近&#xff0c;快递站聪明地分拨送货”的技术&#xff01;&#xff08;网络不堵车&#xff0c;速度翻倍爽&#xff01;&#xff09;路由表中存在等价路由之后&#xff0c;前往该目的网段的IP报文路由器辉通过所有有效的…

DBLens 业界首创AI表结构变更审查,智能评估影响,助力开发效率跃升。

智能守护每一次变更&#xff1a;dblens AI 审查流程详解 在快速迭代的软件开发过程中&#xff0c;数据库结构变更是常见却高风险的操作。一次不经意的字段调整&#xff0c;可能引发线上故障、数据不一致甚至业务中断。为应对这一挑战&#xff0c;dblens 率先引入AI驱动的表结构…