news 2026/4/26 14:40:45

【JavaSE】十二、Collection工具类 反射 详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【JavaSE】十二、Collection工具类 反射 详解

文章目录

  • Ⅰ. Collection工具类
  • Ⅱ. 概念与意义
  • Ⅲ. 反射相关的类与操作
    • 一、Class类(一切反射的起点)
    • 二、获取Class类的三种方式(Student类见附录)
    • 三、创建对象的两种方式
      • ① 直接调用 `Class` 中的 `newInstance()` 方法
      • ② 生成 Constructor 构造方法对象
    • 四、操作类的字段(例子)
    • 五、操作类的方法(例子)
  • 附录

Ⅰ. Collection工具类

官方文档

CollectionsCollection,名字看起来很相似,但实际上它们是两个完全不同的东西!不过,它们确实有一些关系,主要体现在Collections是为了操作Collection接口的集合类提供了很多常用的工具方法

方法作用示例
sort()对 List 排序Collections.sort(list);
reverse()翻转 ListCollections.reverse(list);
shuffle()打乱 ListCollections.shuffle(list);
swap()交换元素Collections.swap(list, i, j);
max()/min()求最大 / 最小元素Collections.max(list);
frequency()某元素出现次数Collections.frequency(list, "apple");
copy()拷贝列表Collections.copy(dest, src);(dest 必须有足够容量)
fill()用一个值填充整个列表Collections.fill(list, 0);
binarySearch()二分查找(需已排序)Collections.binarySearch(list, target);
replaceAll()替换指定值Collections.replaceAll(list, oldVal, newVal);
rotate()旋转列表(整体右移)Collections.rotate(list, k);

其中要倒序排序的话,可以使用:Collections.sort(list, Collections.reverseOrder());

并且排序的类型如果是自定义类型,同样要重写一下特定的比较器,如下所示:

Collections.sort(rec,newComparator<String>(){publicintcompare(Stringword1,Stringword2){returncnt.get(word1)==cnt.get(word2)?word1.compareTo(word2):cnt.get(word2)-cnt.get(word1);}});

Ⅱ. 概念与意义

Java反射是一种机制,允许程序在运行时

  1. 查看类的信息(如属性、方法、构造器等)
  2. 动态创建对象
  3. 访问和修改属性
  4. 调用方法
  5. 操作泛型参数、注解等元信息

反射的意义和应用场景如下所示:

应用场景描述举例
框架设计核心Spring、Hibernate、MyBatis 等全靠它动态注入Bean、解析注解、AOP
通用工具类/库开发不知道具体类时也能处理JSON序列化、ORM字段映射
插件机制 / 动态加载类运行时加载未编译进来的类SPI机制、Class.forName()
动态代理 & AOP 编程实现日志增强、权限控制等JDK动态代理、AspectJ
测试 & Mock 框架访问私有字段,模拟行为JUnit, Mockito 等
简化开发 / 规避重复代码构建泛型代码库动态调用 setter/getter

使用反射的风险和代价如下所示:

风险/代价描述
⏱ 性能开销反射是解释型操作,慢于直接调用
🔒 安全问题可访问私有字段/方法,绕过封装
🧩 可读性差代码不直观,难调试
🧱 编译器检查失效编译时不知道是否写错方法名或类型

Ⅲ. 反射相关的类与操作

类名用途
Class类代表类的实体,在运行的Java应用程序中表示类和接口
Field类代表类的成员变量、属性
Method类代表类的方法
Constructor类代表类的构造方法
Annotation类代表类的注解

一、Class类(一切反射的起点)

官方文档

Java文件被编译后,生成了.class文件,JVM此时会去解读这个.class文件,而.class文件也被JVM解析为一个对象,这个对象就是java.lang.Class

通过Java的反射机制应用到这个实例,就可以去获得甚至去添加改变这个类的属性和动作,使得这个类成为一个动态的类。

一旦拿到了Class对象,比如:

Class<?>clazz=Person.class;// 具体获取方式看后面

可以做很多事,比如下面的操作:(剩下的查文档)

方法用途
clazz.getName()获取类名
clazz.getDeclaredFields()获取所有字段(所有权限均可访问)
clazz.getDeclaredField(String name)获取指定字段(所有权限均可访问)(下面方法也是类似)
clazz.getDeclaredMethods()获取所有方法(所有权限均可访问)
clazz.getDeclaredConstructors()获取构造器(所有权限均可访问)
clazz.newInstance()创建对象(已废弃,推荐 getConstructor().newInstance())
clazz.getSuperclass()获取父类
clazz.getInterfaces()获取实现的接口
clazz.isInterface()是否是接口
clazz.isAnnotationPresent(XXX.class)是否被某注解标记
clazz.getLoader()获得类的加载器

二、获取Class类的三种方式(Student类见附录)

方式语法说明
Class.forName("全限定名")Class.forName("com.demo.Person")常用于配置、动态加载
类静态变量classPerson.class编译期就能获得类信息
对象.getClass()obj.getClass()运行时获得对象的真实类型
publicstaticvoidmain(String[]args){// 1. 使用Class.forName(),注意要指定包名,并且最好捕捉异常Class<?>c1=null;try{c1=Class.forName("Reflection.Student");}catch(ClassNotFoundExceptione){e.printStackTrace();}// 2. 使用指定类的class静态变量Class<?>c2=Student.class;// 3. 使用对象实例的getClass()方法Studentst=newStudent();Class<?>c3=st.getClass();// 一个类在JVM中只会有一个Class实例,因此c1、c2、c3都指向同一个Class实例System.out.println(c1==c2);// trueSystem.out.println(c2==c3);// trueSystem.out.println(c3==c1);// true}

☠注意事项:

  1. 一个类在JVM中只会有一个Class实例。不管你创建多少对象,它们的.getClass()是同一个。
  2. 泛型信息在运行时会被擦除,可以参考泛型笔记。
  3. Class.forName()会触发类初始化,会执行静态代码块,慎用

三、创建对象的两种方式

① 直接调用Class中的newInstance()方法

第一种方式就是调用Class对象中的newInstance()方法,这种方法现在已经被淘汰了,原因如下所示:

  1. 只能调用无参构造方法
  2. 如果构造方法不是public,会抛异常
  3. 已被标记为过时方法(从JDK 9起)
publicstaticvoidmain(String[]args){try{// 1. 先获取Class对象Classc=Class.forName("Reflection.Student");// 2. 然后调用newInstance()方法创建对象,注意要强转成Student类型Studentp=(Student)c.newInstance();System.out.println(p);}catch(ClassNotFoundExceptione){thrownewRuntimeException(e);}catch(InstantiationExceptione){thrownewRuntimeException(e);}catch(IllegalAccessExceptione){thrownewRuntimeException(e);}}

② 生成 Constructor 构造方法对象

官方文档

第二种方式先调用Class对象中的getConstructor()系列的方法,得到Constructor对象,然后调用该对象中的newInstance()方法,优势如下所示:

  1. 可调用有参构造方法
  2. 可修改构造器可见性(setAccessible(true)
publicstaticvoidmain(String[]args){try{// 1. 获取Class对象Class<?>cs=Class.forName("Reflection.Student");// 2. 获取无参的构造方法来创建对象Constructor<?>non_arg_constructor=cs.getDeclaredConstructor();Students1=(Student)non_arg_constructor.newInstance();System.out.println(s1);// 3. 获取带参的构造方法来创建对象,因为带参构造方法是私有的,所以要设置权限为trueConstructor<?>arg_constructor=cs.getDeclaredConstructor(String.class,int.class);arg_constructor.setAccessible(true);Students2=(Student)arg_constructor.newInstance("liren",18);System.out.println(s2);}catch(ClassNotFoundExceptione){thrownewRuntimeException(e);}catch(NoSuchMethodExceptione){thrownewRuntimeException(e);}catch(InvocationTargetExceptione){thrownewRuntimeException(e);}catch(InstantiationExceptione){thrownewRuntimeException(e);}catch(IllegalAccessExceptione){thrownewRuntimeException(e);}}// 运行结果:Student()Student{name='bit',age=18}Student(String,name)Student{name='liren',age=18}

四、操作类的字段(例子)

官方文档

publicstaticvoidmain(String[]args){// 使用反射操作字段try{Class<?>cs=Class.forName("Reflection.Student");// 1. 输出类名,打印字段信息System.out.println("ClassName: "+cs.getName());for(Fielde:cs.getDeclaredFields()){System.out.println(e.getName()+" "+e.getType().getName()+" "+Modifier.toString(e.getModifiers()));}// 2.1 获取私有属性nameFieldnamefield=cs.getDeclaredField("name");namefield.setAccessible(true);// 对于私有属性,需要设置Accessible为true// 2.2 获取该类对象,并设置name属性的值,然后用namefield.get()获取这个私有值Studentst=(Student)cs.newInstance();namefield.set(st,"liren");System.out.println("反射私有属性修改了name:"+namefield.get(st));}catch(ClassNotFoundException|NoSuchFieldExceptione){thrownewRuntimeException(e);}catch(InstantiationExceptione){thrownewRuntimeException(e);}catch(IllegalAccessExceptione){thrownewRuntimeException(e);}}// 运行结果:ClassName:Reflection.Studentnamejava.lang.StringprivateageintpublicStudent()反射私有属性修改了name:liren

五、操作类的方法(例子)

官方文档

publicstaticvoidmain(String[]args){try{Class<Student>cs=Student.class;// 获取带参的私有方法,然后设置权限,最后使用invoke()方法进行调用Method func_method=cs.getDeclaredMethod("function",String.class);func_method.setAccessible(true);func_method.invoke((Student)cs.newInstance(),"我是给私有的function函数传的参数");// 还可以输出方法的指定信息System.out.println("方法名:"+func_method.getName());System.out.println("修饰符为:"+Modifier.toString(func_method.getModifiers()));}catch(NoSuchMethodException e){thrownewRuntimeException(e);}catch(InvocationTargetException e){thrownewRuntimeException(e);}catch(IllegalAccessException e){thrownewRuntimeException(e);}catch(InstantiationException e){thrownewRuntimeException(e);}}// 运行结果:Student()我是给私有的function函数传的参数 方法名:function修饰符为:private

附录

classStudent{// 私有属性nameprivateStringname="bit";// 公有属性agepublicintage=18;// 不带参数的构造⽅法publicStudent(){System.out.println("Student()");}privateStudent(Stringname,intage){this.name=name;this.age=age;System.out.println("Student(String,name)");}privatevoideat(){System.out.println("i am eat");}voidsleep(){System.out.println("i am pig");}privatevoidfunction(Stringstr){System.out.println(str);}@OverridepublicStringtoString(){return"Student{"+"name='"+name+'\''+", age="+age+'}';}}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 12:08:44

ubuntu配置Cuda

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 看显卡类型 //////////…

作者头像 李华
网站建设 2026/4/25 14:43:01

25、使用 SpamAssassin 对抗垃圾邮件(上)

使用 SpamAssassin 对抗垃圾邮件(上) 在当今数字化时代,垃圾邮件泛滥成灾,严重影响了我们的工作和生活。SpamAssassin 作为一款强大的开源垃圾邮件过滤工具,为我们提供了有效的解决方案。本文将详细介绍 SpamAssassin 的使用方法和配置技巧,帮助你更好地应对垃圾邮件的挑…

作者头像 李华
网站建设 2026/4/26 1:38:11

Font Awesome图标子集化:5个步骤实现网站加载速度翻倍

你的网站还在为加载全量Font Awesome图标而拖慢速度吗&#xff1f;想象一下&#xff0c;你的项目只需要20个图标&#xff0c;却要加载包含2000图标的完整字体包&#xff0c;这种资源浪费就像为了喝一杯水而买下整个超市&#xff01;今天&#xff0c;我将带你深入了解Font Aweso…

作者头像 李华
网站建设 2026/4/21 16:17:28

终极SPARTA渗透测试工具完整指南:从零开始掌握网络安全评估

SPARTA是一款强大的Python GUI应用程序&#xff0c;专门用于简化网络基础设施渗透测试流程。作为SECFORCE开发的网络渗透测试工具&#xff0c;它通过直观的点击界面帮助安全专家在扫描和枚举阶段节省大量时间&#xff0c;让您专注于分析结果而非繁琐的命令设置。 【免费下载链接…

作者头像 李华
网站建设 2026/4/22 3:25:19

FlashAI多模态整合包:我的3分钟本地AI助手体验分享

FlashAI多模态整合包&#xff1a;我的3分钟本地AI助手体验分享 【免费下载链接】flashai_vision 项目地址: https://ai.gitcode.com/FlashAI/vision 开篇体验 作为一名自媒体创作者&#xff0c;我一直在寻找既能保护创作隐私又能高效处理多格式文件的AI工具。直到遇见…

作者头像 李华