文章目录

  • 反射(reflection)
    • 引出反射
    • Java Reflection
      • java反射机制可以完成
      • 反射相关的主要类:
      • 反射优点和缺点
      • 反射调用优化-关闭访问检查
    • Class类
      • 基本介绍
      • Class类的常用方法:
      • 获取Class 对象:
      • 拓展:哪些类型有Class对象
    • 类加载
      • 基本说明
      • 类加载时机
      • 加载阶段
      • 连接阶段-解析
      • Initialiaztion(初始化)
    • 通过反射获取类的结构信息
      • 第一组:java.lang.Class 类
      • 第二组: java.lang.reflect.Field 类
    • 通过反射创建对象
    • 通过反射访问类中的成员
      • 访问属性
      • 访问方法
    • 应用案例

反射(reflection)

引出反射

  1. 使用Propertier 类,可以读写配置文件
Propertier properties = new Properties();
properties.load(new FileInputStream("src\\re.properties"))//原路径
String classfullPath = properties.get("classfullpath").toString();//得到类信息
String method = properties.get("method").toString();//得到方法信息
System.out.println("classfullpath="+ classfulllpath);
System,out.println("method="+ method);
  1. 创建对象,传统的方法,行不通 ====> 反射机制
  2. 使用反射机制解决
//(1)加载类,返回Class类型的对象cls
Class acalss = Class.forName(classfullpath);
//(2)通过 cls 得到你加载的类 Cat 的对象实例
Object o = cls.newInstance();
System.out.println(o.getClass());// 运行类型
//(3)通过 cls 得到你加载的类 Cat 的methodName "hi" 的方法对象
// 即:在反射中,可以把方法视为对象(万物皆对象)
Method method1 = cls.getMethod(methodName);
//(4)通过method1 调用方法: 即通过方法对象来实现调用方法
method1.invoke(o); //传统方法 对象.方法(), 反射机制 方法.invoke(对象)说明:即通过外部文件配置,在不修改源码情况下,来控制程序,也符合设计模式的ocp原则(开闭原则:不修改源码,扩容功能)

Java Reflection

  1. 反射机制允许程序在执行期借助于Reflection API 取得任何类的内部信息(比如成员变量,构造器,成员方法等等),并能操作对象的属性及方法。反射在设计模式和框架底层都会用到。
  2. 加载完类之后,在堆中就产生了一个Class 类型的对象(一个类只有一个Class对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构。这个对象就像一面镜子,透过一个镜子看见类的结构,所以,形象的称之为:反射。
  3. Java反射机制原理示意图

java反射机制可以完成
  1. 在运行时判断任意一个对象所属的类
  2. 在运行时构造任意一个类的对象
  3. 在运行时的得到任意一个类所具有的成员变量和方法
  4. 在运行时调用任意一个对象的成员变量和方法
  5. 生成动态代理
反射相关的主要类:
  1. java.lang.Class:代表一个类,Class对象表示某个类加载后在堆中的对象
  2. java.lang.reflect.Method:代表类的方法,Method对象表示某个类的方法
  3. java.lang.reflect.Field:代表类的成员变量,Field对象表示某个类的成员变量
  4. java.lang.reflect.Constructor:代表类的构造方法,Constructor对象表示构造器
反射优点和缺点
  1. 优点:可以动态的创建和使用对象(也是框架底层核心),使用灵活,没有反射机制,框架技术就失去底层支撑。
  2. 缺点:使用反射基本是解释执行,对执行速度有影响。
反射调用优化-关闭访问检查
  1. Method和Field、Constructor对象都有setAccessible() 方法
  2. setAccessible作用和禁用访问安全检查的开关
  3. 参数值为true表示 反射的对象在使用时取消访问检查,提高反射的效率。参数值为fasle则表示反射的对象执行访问检查

Class类

基本介绍
  1. Class类也是类,因此也继承Object类
  2. Class类对象不是new出来的,而是系统创建的
  3. 对于某个类的Class类对象,在内存中只有一份,因为类只加载一次
  4. 每个类的实例都会记得自己是由哪个Class实例所生成的
  5. 通过Class对象可以完整地得到一个类的完成结构,通过一系列API
  6. Class对象时存放在堆的
  7. 类的字节码二进制数据,是放在方法区的,有的地方称为类的元数据(包括 方法代码, 变量名, 方法名, 请求权限等等)
Class类的常用方法:

    String classAllPath = "reflection.Car";//获取到Car 类对应的 Class 对象// <?>表示不确定的java 类型Class<?> aClass = Class.forName(classAllPath);//输出clsSystem.out.println(aClass); //显示aClass 对象,是哪个类的Class reflection.CarSystem.out.println(Class.class); //输出aClass 运行类型 java.lang.Class//3. 得到包名System.out.println(aClass.getPackage().getName());//4.全类名System.out.println(aClass.getName());//5.通过aClass 创建一个对象实例Car car =(Car) aClass.getConstructor().newInstance();System.out.println(car);//6. 通过反射获取属性 brandField color = aClass.getField("color");System.out.println(color.get(car));//7. 通过反射给属性赋值color.set(car,"黄色");System.out.println(color.get(car));//8. 遍历所有属性System.out.println("====================");Field[] fields = aClass.getFields();for(  Field n : fields){System.out.println(n.getName());}
获取Class 对象:
public static void main(String[] args) throws Exception {//1.Class.forNameString classAllPath = "reflection.Car";Class<?> aClass1 = Class.forName(classAllPath);Object o = aClass1.getConstructor().newInstance();Field color = aClass1.getField("color");System.out.println(color.get(o));//2. 类名.classClass carClass2 = Car.class;System.out.println(carClass2);//3.对象.getClass(),应用场景,有对象实例Car car = new Car();Class aClass3 = car.getClass();System.out.println(aClass3);//4.通过类的加载器(4中类加载器)来获取到类的Class 对象//  (1)先得到类加载器 carClassLoader classLoader = car.getClass().getClassLoader();//  (2) 通过类加载器得到Class 对象Class<?> aClass4 = classLoader.loadClass(classAllPath);System.out.println(aClass4);// 上四个均为同一个对象System.out.println(aClass1.hashCode());System.out.println(carClass2.hashCode());System.out.println(aClass3.hashCode());System.out.println(aClass4.hashCode());//5.基本数据类型(int,char,boolean,float,double,byte,long,short)按如下方式得到Class类对象//Class aClass = 基本数据类型.classClass<Integer> integerClass = int.class;System.out.println(integerClass);Class<Character> characterClass = char.class;//6.基本数据类型对应的包装类,可以通过.type得到Class类对象//Class aClass = 包装类.TYPE;Class<Integer> integerClass1 = Integer.class;System.out.println(integerClass1);Class<Boolean> booleanClass = Boolean.class;
}
拓展:哪些类型有Class对象
  1. 外部类,成员内部类,静态内部类,局部内部类,匿名内部类
  2. interface: 接口
  3. 数组
  4. enum: 枚举
  5. annotation : 注解
  6. 基本数据类型
  7. void

类加载

基本说明

反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载.

  1. 静态加载:编译时加载相关的类, 如果没有则报错,依赖性太强
  2. 动态加载: 运行时加载需要的类,如果运行时不用该类,则不报错,降低了依赖性 ( 反射动态加载)
类加载时机
  1. 当创建对象时(new) //静态加载
  2. 当子类被加载时 //静态加载
  3. 调用类中的静态成员时 //静态加载
  4. 通过反射 //动态加载

加载阶段

JVM 在该阶段的主要目的是将字节码从不同的数据源(可能是class 文件、也可能是jar包,甚至网络) 转化为二进制字节流加载到内存中,并生成一个代表该类的java.lang.Class 对象

public int n1 = 10;
public static int n2 = 20;
public static final int n3 = 30;// n1 是实例属性,不是静态变量,因此在准备阶段,是不会分配内存
// n2 是静态变量,分配内存 n2 是默认初始化 0,而不是20
// n3 是static final 是常量,他和静态变量不一样,因为一旦赋值就不变 n3 = 30
连接阶段-解析

虚拟机将常量池内的符号引用替换为直接引用的过程

Initialiaztion(初始化)
  1. 到初始化阶段,才真正开始执行类中定义的java 程序代码,此阶段是执行 () 方法的过程
  2. () 方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中所有静态变量的赋值动作和静态代码块中的语句,并进行合并.
  3. 虚拟机会保证一个类的() 方法在多线程环境中被正确地加锁、同步、如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的() 方法,其他线程都需要阻塞等待,知道活动线程执行() 方法完毕

通过反射获取类的结构信息

第一组:java.lang.Class 类
  1. getName:获取全类名
  2. getSimpleName:获取简单类名
  3. getFields: 获取所有public 修饰的属性, 包含本类一级父类的
  4. getDeclaredFields: 获取本类中所有属性
  5. getMethods: 获取所有public 修饰的方法,包含本类以及父类的
  6. getDeclaredMethods: 获取本类中所有方法
  7. getConstructors: 获取所有public 修饰的构造器,包含本类所有public
  8. getDeclaredConstructors: 获取本类中 所有的构造器
  9. getPackage: 以Package 形式返回 包信息
  10. getSuperClass: 以Class 形式返回父类信息
  11. getInterfaces: 以Class[] 形式返回接口信息
  12. getAnnotations: 以Annotation[] 形式返回注解信息
第二组: java.lang.reflect.Field 类
  1. getModfiers:以int 形式返回修饰符

    [说明: 默认修饰符 是0, public 是1 ,private 是 2, protected 是4, static 是8 ,final 是 16]

  2. getType:

  3. 以Class 形式返回类型

  4. getName: 返回属性名

通过反射创建对象

  1. 方式一: 调用类中的public 修饰的无参构造器
  2. 方式二: 调用类中的指定构造器
  3. Class类相关方法
  • newInstance : 调用类中的无参构造器, 获取对应类的对象
  • getConstructor(Class…cls): 根据参数列表,获取对应的public 构造器对象
  • getDecalaredConstructor(Class…cls ): 根据参数列表,获取对应的构造器对象
  1. Constructor 类相关方法
  • setAccessible: 暴破
  • newInstance(Object…obj): 调用构造器

通过反射访问类中的成员

访问属性
  1. 根据属性名获取Field对象

Field f = cls 对象.getDeclareField(属性名);

  1. 暴力破解: f.setAccseeible(true); //f 是Field
  2. 访问 f.set(o, 值); syso(f.get(o)); //o表示对象
  3. 注意: 如果是静态属性,则set 和 get中的参数o, 可以写成null
        Class<?> aClass = Class.forName("reflection.Student");Object o = aClass.getConstructor().newInstance();System.out.println(o.getClass());//3.使用反射得到 age 属性Field age = aClass.getField("age");age.set(o,100);System.out.println(o);//4.使用反射操作name 属性Field name = aClass.getDeclaredField("name");
//        name.setAccessible(true);name.set(o,"Pink");// 因为name是static 属性,因此 o 也可以写出nullSystem.out.println(o);
访问方法
  1. 根据方法名和参数列表获取Method方法对象 : Method m = cls.getDeclaredMethod(方法名, xx.class);
  2. 获取对象 : Object o = clazz.newInstance();
  3. 暴破: m.setAccessible(true);
  4. 访问: Object returnValue = m.invlke(o, 实参列表);
  5. 注意: 如果是静态方法, 则invoke 的参数o, 也可以写成null;
        //1.得到Boss类对应的Class对象Class<?> aClass = Class.forName("reflection.Boss");//2.创建对象Object o = aClass.getConstructor().newInstance();//3. 得到hi方法对象Method hi = aClass.getMethod("hi", String.class);//4. 调用System.out.println(hi.invoke(o,"Tom"));//5.调用private static 方法Method declaredMethod = aClass.getDeclaredMethod("say", int.class, String.class,char.class);declaredMethod.setAccessible(true);System.out.println(declaredMethod.invoke(o,20,"Jack",'w'));//在反射中,如果方法有返回值,统一按照 Object 返回

应用案例

        Class<?> aClass = Class.forName("java.io.File");Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();for (Constructor<?> declaredConstructor : declaredConstructors) {System.out.println("File类中的构造器为=" + declaredConstructor);}Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class);String FilePath ="E:\\myNew.txt";Object file = declaredConstructor.newInstance(FilePath);Method createNewFile = aClass.getMethod("createNewFile");//得到方法的对象createNewFile.invoke(file);

Java——反射(reflection)详解相关推荐

  1. java 反射机制详解

    火星十一郎 海纳百川, 有容乃大,QQ:791909235,Tel:13137910179 posts - 774, comments - 556, trackbacks - 0, articles ...

  2. java反射机制详解篇一(基础)

    反射基础 首先来看一下最常规的创建对象的方式: ObjectClass clazz = new ObjectClass(); 当程序执行到new ObjectClass的时候,java虚拟机会加载Ob ...

  3. C#反射(Reflection)详解

    1. 什么是反射 2. 命名空间与装配件的关系 3. 运行期得到类型信息有什么用 4. 如何使用反射获取类型 5. 如何根据类型来动态创建对象 6. 如何获取方法以及动态调用方法 7. 动态创建委托 ...

  4. java反射 invoke详解

    2019独角兽企业重金招聘Python工程师标准>>> JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法 ...

  5. java反射机制详解_Java反射机制详解

    Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为Java语言的反 ...

  6. java反射机制详解_JAVA反射机制详解_JSP/Java编程_互联网开发技术网_传播最新的编程技术_php361.com...

    今天,下午在和朋友聊天的时候,聊起了反射这个话题. 我们就从下面这个段简单的代码开始吧. 这个代码输出什么,想必大部分的读者跟我一样,会很快地知道答案:0 1 2 3 4 5 6 7 8 9.事实也是 ...

  7. [转]Java反射机制详解

    目录 1反射机制是什么 2反射机制能做什么 3反射机制的相关API ·通过一个对象获得完整的包名和类名 ·实例化Class类对象 ·获取一个对象的父类与实现的接口 ·获取某个类中的全部构造函数 - 详 ...

  8. Java 反射机制详解:私有方法调用头大?如何通过反射调用类中的私有方法?

    文章目录 前言 一.私有方法在本类中直接调用 1.1.在本类中实例化,调用私有方法 1.2.尝试在其他类直接调用私有方法(错误示范) 二.使用反射实例化类强制调用私有方法 2.1.使用类加载器加载被调 ...

  9. Java反射体系详解

    文章目录 1.获取一个类的对应的Class对象 (Class的C是大写) (1)调用Object提供的getClass方法 (2)类名称 . class (3)调用Class类提供的静态方法:Clas ...

  10. Java反射技术详解

    前言 相信很多人都知道反射可以说是Java中最强大的技术了,它可以做的事情太多太多,很多优秀的开源框架都是通过反射完成的,比如最初的很多注解框架,后来因为java反射影响性能,所以被运行时注解APT替 ...

最新文章

  1. 如何搭建以太坊私有链
  2. com.android.phone已停止 vivo,oppo,vivo应用程序终止通知不在android fcm中出...
  3. Bootstrap4+MySQL前后端综合实训-Day03-AM【折叠、模态框】
  4. 制作css开关,纯css实现开关效果
  5. docker安装ubuntu镜像
  6. 如何在没有安全启动或 TPM 2.0 的传统 BIOS 上安装 Windows 11
  7. Oozie分布式任务的工作流——Sqoop篇
  8. 码农小汪-Hibernate学习6-hibernate中Annocation修饰属性
  9. 子网掩码-掩码位-反掩码 对照表
  10. 身份证验证判断、身份证正则表达式、15位、18位身份证验证
  11. db2 删除索引_[收录量]史上最全的百度索引量下降原因分析及解
  12. 如何打造高绩效的研发团队
  13. 小米手机部和平台部组织调整 前者设参谋部、触控部
  14. 聊聊我的英语学习经验
  15. 使用pydub的坑-----Permission denied: 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp\\tmpmt80te3g.wav'
  16. 我的服务器被挖矿了,原因竟是。。。
  17. linux下fdisk命令实战案例之详解
  18. 2008年MBA全国联考英语考试大纲
  19. 当前市场主流蓝牙音频SOC
  20. 前世、叶伸伸北京个人演唱会成功举行 用歌声唱出音乐梦想

热门文章

  1. 中科大自主招生2018年笔试数学之二
  2. 机房交换机网络测试软件,国内IDC机房带宽测试工具和方案
  3. 国内计算机刊物标准写作规范和标准
  4. 河北计算机四六级报名入口,英语四六级考试报名入口
  5. PPT设计思维进阶:提升设计能力
  6. 微信小程序获取openid(用户唯一身份识别)
  7. 使用DuckDuckGo在命令行中搜索
  8. 大龄程序员的4年生涯
  9. seo具体怎么优化-优化SEO的方法
  10. 新浪微博单点登陆分析