目录

反射概述

反射获取类对象

反射获取构造器对象

反射获取成员变量对象

反射获取方法对象

反射的作用-绕过编译阶段为集合添加数据

反射的作用-通用框架的底层原理

反射的作用-----总结


反射概述

反射是指对于任何一个Class类,在"运行的时候"都可以直接得到这个类全部成分。

在运行时,可以直接得到这个类的构造器对象:Constructor

在运行时,可以直接得到这个类的成员变量对象:Field

在运行时,可以直接得到这个类的成员方法对象:Method

这种运行时动态获取类信息以及动态调用类中成分的能力称为Java语言的反射机制。

反射的关键: 反射的第一步都是先得到编译后的Class类对象,然后就可以得到Class的全部成分。 例如:Class c = People.class;

反射的核心思想和关键就是:得到编译以后的class文件对象。

反射的作用:反射是在运行时获取类的字节码文件对象:然后可以解析类中的全部成分

反射获取类对象

反射的第一步:获取Class类的对象

方法一:Class c1 = Class.forName(“全类名”);

方法二:Class c2 = 类名.class

方法三:Class c3 = 对象.getClass();

public class People {private String name;private int age;
}
public class TestPeople0 {public static void main(String[] args) throws Exception {
//        1.Class类中的静态方法Class c = Class.forName("one.People");System.out.println(c);
//        2.类名.classClass c0 = People.class;System.out.println(c0);
//        3.获取对象对应类的Class对象People p = new People();Class c1 = p.getClass();System.out.println(c1);}}

反射获取构造器对象

获得class对象 ===》  获取构造器 ===》 创建对象

第二步:获得Constructor对象

提取构造器,具体使用在代码中:

1.Constructor[] constructors = c.getConstructors();

2.Constructor[] constructors = c.getDeclaredConstructors();

3.Constructor constructor = c.getConstructor();

4.Constructor constructor = c.getDeclaredConstructor();

Constructor<?>[] getConstructors​()

返回所有构造器对象的数组(只能拿public的)

Constructor<?>[] getDeclaredConstructors​()

返回所有构造器对象的数组,存在就能拿到

Constructor<T> getConstructor​(Class<?>... parameterTypes)

返回单个构造器对象(只能拿public的)

Constructor<T> getDeclaredConstructor​(Class<?>... parameterTypes)

返回单个构造器对象,存在就能拿到

public class People {private String name;private int age;public People(){System.out.println("无参构造!");}private People(String name, int age){this.name = name;this.age = age;System.out.println("有参构造!");}
public class TestPeople1 {public void getConstructors(){//1.获取类对象Class c = People.class;//2.提取类中的全部构造器对象----私有的拿不到,只能拿public的Constructor[] constructors = c.getConstructors();//遍历构造器for(Constructor constructor : constructors)System.out.println(constructor.getName()+"--->"+constructor.getParameterCount());   //名字--->参数个数}public void getDeclaredConstructors(){//1.获取类对象Class c = People.class;//2.提取类中的全部构造器对象----私有的也能拿到Constructor[] constructors = c.getDeclaredConstructors();//遍历构造器for(Constructor constructor : constructors)System.out.println(constructor.getName()+"--->"+constructor.getParameterCount());   //名字--->参数个数}public void getConstructor() throws NoSuchMethodException {//1.获取类对象Class c = People.class;//2.提取类中的一个构造器对象--根据参数拿对应构造器---只能拿public的Constructor constructor = c.getConstructor();//名字--->参数个数System.out.println(constructor.getName()+"--->"+constructor.getParameterCount());}public void getDeclaredConstructor() throws NoSuchMethodException {//1.获取类对象Class c = People.class;//2.提取类中的一个构造器对象--根据参数拿对应构造器---私有的也能拿到Constructor constructor = c.getDeclaredConstructor(String.class, int.class);//名字--->参数个数System.out.println(constructor.getName()+"--->"+constructor.getParameterCount());}public static void main(String[] args) throws Exception {TestPeople1 a = new TestPeople1();a.getConstructors();a.getDeclaredConstructors();a.getConstructor();a.getDeclaredConstructor();}
}

第三步创建对象:

constructor.setAccessible(true);  暴力开权限,反射可以破坏其封装性--私有的才需要开权限,公有的不需要
Object p = constructor.newInstance();   根据对应的构造器,创建对象---可强制转换

以下代码是在上面的基础上进行增添,具体使用在代码中:
import java.lang.reflect.Constructor;public class TestPeople2 {public void getObject() throws Exception {//1.获取类对象Class c = People.class;//2.提取类中的一个构造器对象--根据参数拿对应构造器---私有的也能拿到Constructor constructor = c.getDeclaredConstructor(String.class, int.class);//名字--->参数个数System.out.println(constructor.getName()+"--->"+constructor.getParameterCount());//私有构造器报错,不能创建对象,,需要暴力反射--开权限--setAccessible(true)constructor.setAccessible(true);    //只针对这一次有效Object p = constructor.newInstance("小明", 18);   //创建对象People,18岁的小明}public static void main(String[] args) throws Exception {TestPeople2 p = new TestPeople2();p.getObject();}
}

反射获取成员变量对象

获得class对象 ===》  获取成员变量 ===》 取值或赋值

第一步:获得class对象

第二步:获得Field对象

Field[] fields = c.getDeclaredFields();    获取全部成员变量
Field field = c.getDeclaredField("name"); 获取其中一个成员变量----根据变量名称获取

Field[] getFields​()

返回所有成员变量对象的数组(只能拿public的)

Field[] getDeclaredFields​()

返回所有成员变量对象的数组,存在就能拿到

Field getField​(String name)

返回单个成员变量对象(只能拿public的)

Field getDeclaredField​(String name)

返回单个成员变量对象,存在就能拿到

第三步:获取值或赋值

Field field = c.getDeclaredField("age");

get方法,取值        field.get(对象);

set方法,赋值        field.set(对象, 值);

void set​(Object obj, Object value):

赋值

Object get​(Object obj)

获取值。

具体使用在代码中:

import java.lang.reflect.Field;
public class TestPeople3 {public void getDeclaredFields(){//1.获取class对象Class c = People.class;//2.获取全部成员变量Field[] fields = c.getDeclaredFields();//遍历for(Field field : fields)System.out.println(field.getName() + "--->" + field.getType()); //名字--->类型}public void getDeclaredField() throws Exception {//1.获取class对象Class c = People.class;//2.获取其中一个成员变量----根据名称获取某个成员变量Field field = c.getDeclaredField("age");//输出    名字--->类型System.out.println(field.getName() + "--->" + field.getType());//3.赋值field.setAccessible(true);  //暴力开权限---private成员变量不能直接操作People p = new People();field.set(p, 18);System.out.println("赋值age:"+p.getAge());//4.取值int age = (int)field.get(p);System.out.println("取值age:"+age);}public static void main(String[] args) throws Exception {TestPeople3 p = new TestPeople3();p.getDeclaredFields();p.getDeclaredField();}}

反射获取方法对象

获得class对象 ===》  获取方法 ===》 触发执行方法

第一步:获得class对象

第二步:获得Method对象

Method[] getMethods​()

返回所有成员方法对象的数组(只能拿public的)

Method[] getDeclaredMethods​()

返回所有成员方法对象的数组,存在就能拿到

Method getMethod​(String name, Class<?>... parameterTypes)

返回单个成员方法对象(只能拿public的)

Method getDeclaredMethod​(String name, Class<?>... parameterTypes)

返回单个成员方法对象,存在就能拿到

第三步:Method类中用于触发执行的方法

成员方法是非public的,需要打开权限(暴力反射),然后再触发执行----setAccessible(boolean)

Object invoke​(Object obj, Object... args)

运行方法

参数一:用obj对象调用该方法

参数二:调用方法的传递的参数(如果没有就不写)

返回值:方法的返回值(如果没有就不写)

具体使用在代码中:

import java.lang.reflect.Method;public class TestPeople4 {public void getDeclareMethods(){//1.获取类对象Class c = People.class;//2.提取全部方法,包括私有的Method[] methods = c.getDeclaredMethods();//遍历for (Method method : methods)   //名字--->返回类型--->参数个数System.out.println(method.getName()+"--->"+method.getReturnType()+"--->"+method.getParameterCount());}public void getDeclareMethod() throws Exception {//1.获取类对象Class c = People.class;//2.提取某一个方法,根据名字Method method1 = c.getDeclaredMethod("setAge", int.class);Method method2 = c.getDeclaredMethod("getAge");//名字--->返回类型--->参数个数System.out.println(method1.getName()+"--->"+method1.getReturnType()+"--->"+method1.getParameterCount());System.out.println(method2.getName()+"--->"+method2.getReturnType()+"--->"+method2.getParameterCount());//3.方法的触发执行//如果方法不是public的,需要打开权限(暴力反射),然后再触发执行----setAccessible(boolean)People p = new People();Object a1 = method1.invoke(p, 20);Object a2 = method2.invoke(p);//若方法是无返回结果的,则返回的是nullSystem.out.println(a1);System.out.println(a2);}public static void main(String[] args) throws Exception {TestPeople4 p = new TestPeople4();p.getDeclareMethods();p.getDeclareMethod();}
}

反射的作用-绕过编译阶段为集合添加数据

1.反射是作用在运行时的技术,此时集合的泛型将不能产生约束了,此时是可以为集合存入其他任意类型的元素

2.泛型只是在编译阶段可以约束集合只能操作某种数据类型,在编译成Class文件进入运行阶段的时候,其真实类型都是ArrayList了,泛型相当于被擦除了。

具体使用在代码中:


import java.lang.reflect.Method;
import java.util.ArrayList;public class TestDemo5 {public static void main(String[] args) throws Exception {// 需求:反射实现泛型擦除后,加入其他类型的元素//编译成Class文件进入运行阶段的时候,泛型会自动擦除。反射是作用在运行时的技术,此时已经不存在泛型了。//故反射不受泛型的约束ArrayList<String> lists1 = new ArrayList<>();ArrayList<Integer> lists2 = new ArrayList<>();System.out.println(lists1.getClass());System.out.println(lists2.getClass());System.out.println(lists1.getClass() == lists2.getClass());   //ArrayList.classArrayList<Integer> lists3 = new ArrayList<>();lists3.add(11);lists3.add(22);
//      list3.add("小孩"); 类型不符合,错误Class c = lists3.getClass();  //ArrayList.class//获取c类中的add方法------不受泛型Integer的约束Method add = c.getDeclaredMethod("add", Object.class);//判断添加是否成功boolean ans = (boolean) add.invoke(lists3, "小孩");System.out.println(ans);System.out.println(lists3);}
}

反射的作用-通用框架的底层原理

下面是一个实例:

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;// 提供一个通用框架,支持保存所有对象的具体信息。
public class TestDemo2 {//保存任意类型的对象 Objectpublic static void save(Object obj){try (//文件输出到data.txt中PrintStream ps = new PrintStream(new FileOutputStream("demo1/src/data.txt", true));){//1.获取该类对象Class c = obj.getClass();ps.println("---------------> " + c.getSimpleName() + " <---------------");//2.提取该对象的全部成员变量Field[] fields = c.getDeclaredFields();for (Field field: fields){//暴力开权限field.setAccessible(true);//获取成员变量名字String name = field.getName();//取值String value = field.get(obj) + "";ps.println(name  + "=" + value);}}catch (IllegalAccessException e) {throw new RuntimeException(e);} catch (FileNotFoundException e) {throw new RuntimeException(e);}}public static void main(String[] args) {Worker w = new Worker(22, '男', "张三");save(w);}}

反射的作用-----总结

  1. 可以在运行时得到一个类的全部成分然后操作。
  2. 可以破坏封装性。(很突出)
  3. 也可以破坏泛型的约束性。(很突出)
  4. 更重要的用途是适合:做Java高级框架 基本上主流框架都会基于反射设计一些通用技术功能。

如果有错误,大哥们指出来,我会改的!!

JAVA反射----->看这篇就够了相关推荐

  1. python java混合编程_详解java调用python的几种用法(看这篇就够了)

    java调用python的几种用法如下: 在java类中直接执行python语句 在java类中直接调用本地python脚本 使用Runtime.getRuntime()执行python脚本文件(推荐 ...

  2. Java String,看这篇就够了

    String,是Java中最重要的类.这句肯定的推断不是Java之父詹姆斯·高斯林说的,而是沉默王二说的,因此你不必怀疑它的准确性. 关于字符串,有很多的面试题,但我总觉得理论知识绕来绕去没多大意思. ...

  3. Java应用系统监控看这篇就够了

    Java应用系统监控看这篇就够了 文章目录 业务背景 系统监控发展历程 技术方案 日志监控技术方案 Grafana+阿里云SLS日志服务 分布式链路追踪技术方案 阿里云jaeger方案 开源框架sky ...

  4. 一文详解JavaBean 看这篇就够了

    一文详解JavaBean 看这篇就够了 JavaBean的历史渊源 JavaBean的定义(通俗版) JavaBean应用 < jsp:useBean > < jsp:getProp ...

  5. uiautomation遍历windows所有窗口_万字长文!滑动窗口看这篇就够了!

    大家好,我是小浩.今天是小浩算法 "365刷题计划" 滑动窗口系列 - 整合篇.之前给大家讲解过一些滑动窗口的题目,但未作系统整理. 所以我就出了这个整合合集,整合工作中除了保留原 ...

  6. .NET Core实战项目之CMS 第二章 入门篇-快速入门ASP.NET Core看这篇就够了

    本来这篇只是想简单介绍下ASP.NET Core MVC项目的(毕竟要照顾到很多新手朋友),但是转念一想不如来点猛的(考虑到急性子的朋友),让你通过本文的学习就能快速的入门ASP.NET Core.既 ...

  7. Spring Cloud入门,看这篇就够了!

    点击▲关注 "中生代技术"   给公众号标星置顶 更多精彩 第一时间直达 概述 首先我给大家看一张图,如果大家对这张图有些地方不太理解的话,我希望你们看完我这篇文章会恍然大悟. 什 ...

  8. Docker入门实战看这篇就够了(最新详细以及踩过的坑)

    Docker入门实战看这篇就够了 前言 初识 是什么 容器与虚拟机 能干什么 去哪玩 安装 先决条件 查看自己的内核 安装所需的软件包(支持devicemapper存储类型) 设置镜像的仓库 设置yu ...

  9. NDK撩妹三部曲(四)—NDK 开发如何优雅的定位 Native 异常,看这篇就够了

    NDK 开发如何优雅的定位 Native 异常,看这篇就够了 从何说起? 摘要 案例实操 aaddr2line objdump ndk-stack 1.假设我们已经通过 adb logcat 拿到了程 ...

  10. groovy if 判断字符串_Groovy快速入门看这篇就够了

    原标题:Groovy快速入门看这篇就够了 来自:刘望舒(微信号:liuwangshuAndroid) 前言 在前面我们学习了和两篇文章,对Gradle也有了大概的了解,这篇文章我们接着来学习Groov ...

最新文章

  1. 从多媒体技术演进看AI技术
  2. 在GHOST的WINXPSP2安装SQL SERVER2000个人版时出现“以前的某个程序安装已在安装计算机上创建挂起的文件操作。运行安装之前,必须重新启动计算机。”错误的解决方法...
  3. python 导出数据并发邮件_Python自动化导出zabbix数据并发邮件脚本
  4. 微信非80端口网页授权
  5. C语言课程设计选哪个,C语言课程设计选题及要求.docx
  6. Leetcode python《热题 HOT 100》15. 三数之和
  7. html文字字号不改变,如何在不改变div大小的情况下更改HTML / css中的字体大小?...
  8. C++调用python(C++)
  9. php映射,PHP实现路由映射到指定控制器
  10. Graphics.TranslateTransform设置旋转角度不起作用?
  11. 4种字符串匹配算法:有限自动机(中)
  12. 计算机度分秒在线,度分秒换算器(度分秒换算器在线)
  13. 工程计算——实战:追赶法扰动分析
  14. JD eid fp
  15. buck dcm占空比计算_buck电路输出电容及其他参数计算
  16. 智能科学的泉眼——人性论
  17. Ubuntu 22.10 (Kinetic Kudu) 发布
  18. 正睿OI DAY8 ks1
  19. 男子1分钟16位数开14次方 曾被诊断中度智障
  20. go语言编程二维码生成及识别

热门文章

  1. DevOps之五Jenkins
  2. Unity教程:URP渲染管线实战教程系列【1】
  3. C++中,system的神级用法总和,实现用C++操作系统
  4. 使用Sentinel Dashboard监控项目流量
  5. 骑砍自建服务器,恶魔之魂玩家不忍服务器关闭 自建服务器上线运行
  6. Oracle中一个汉字占几个字节
  7. Presupposition
  8. 10岁学编程:虚幻引擎创始人Tim Sweeney
  9. C++产生随机数的几种方法
  10. led接口实验微型计算机,微型计算机原来与接口技术实验报告(全)