反射机制(原理示意图、优缺点、调优)

Java Reflection

 

Java 反射机制原理示意图

Java程序计算机有三个阶段:代码阶段/编译阶段Class类阶段(加载阶段)Runtime运行阶段


比如说有一个Cat.java的源代码文件,里面有name属性,Cat构造器,hi方法

然后对它进行编译,通过编译就会得到一个Cat.class的字节码文件

那么字节码文件里面有什么呢?

里面肯定是包含了属性,构造器,方法等等。

如果我们在Runtime运行阶段,去new一个Cat对象,并且调用hi()方法

那么它会把字节码文件加载到内存里的堆里面,就会生成Class类对象(Cat的),里面就有成员变量、构造器、成员方法等等。。

那么为什么Cat.class字节码文件为什么会生成一个Class对象并且放在堆里面呢?

这里面就有个特别重要的东西,叫做类加载器——ClassLoader,其实是通过它加载进去的,并且生成Class对象。这里就已经体现出反射机制

它把生成的Class对象在堆里面其实就是数据结构,也就是可以操作的数据,它会在底层把成员变量当成对象来看待、构造器也是,当然构造器也可能有多个,也会映射成数组,方法也会当成对象来对待。

有这些东西过后————也就是类加载过后,就会生成对象,生成的这个对象就是在堆里面,该对象能够知道它是属于哪个Class对象。

当我们得到Class对象后,可以做很多工作,比如说创建对象,调用对象方法,还可以操作它的属性。


Java 反射机制可以完成什么?


反射相关的主要类

package com.godairo.reflection;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;

/**
 * @author GodAiro
 * Creation Time: 2022/7/17 15:33.
 */
@SuppressWarnings({"all"})
public class Reflection01 {
   public static void main(String[] args) throws Exception {
	  //根据配置文件 re.properties 指定信息, 创建 Cat 对象并调用方法 hi
	  Properties properties = new Properties();
	  properties.load(new FileInputStream("F:\\Java_Basis\\FanShe\\src\\re.properties"));
	  String classfullpath = properties.get("classfullpath").toString();
	  String methodName = properties.get("method").toString();
	  System.out.println(classfullpath+"+"+methodName);

	  //使用反射机制解决
	  //(1) 加载类,返回class类型的对象
	  Class cls = Class.forName(classfullpath);
	  //(2) 通过cls可以得到你加载的类。com.godairo.Cat的对象实例
	  Object o= cls.newInstance();
	  System.out.println("o的运行类型:"+o.getClass());//运行类型
	  //(3) 通过cls得到你加载的类 com.godairo.Cat的 methodName"hi" 的对象方法
	  //	即:在反射中,可以把方法视为对象(万物皆对象)
	  Method method1 = cls.getMethod(methodName);
	  //(4) 通过method调用方法:即通过方法对象来实现调用方法
	  System.out.println("======================");
	  method1.invoke(o);//传统方法:对象.方法(),反射机制:方法.invoke(对象)
	  
	  //java.lang.reflect.Field: 代表类的成员变量, Field 对象表示某个类的成员变量
	  //得到name字段
	  //getFired不能得到私有的属性
	  Field nameField = cls.getField("age");
	  System.out.println(nameField.get(o));//传统写法是:对象.成员变量。反射:成员变量对象.get(对象)
	  
	  //构造器
	  Constructor constructor = cls.getConstructor(); 	//()中可以指定构造器参数类型,里面没东西返回的就是无参构造器
	  System.out.println(constructor); //Cat() 没有形参的构造器
	  
	  Constructor constructor1 = cls.getConstructor(String.class);//这里传入的String.class 就是String类的Class对象
	  System.out.println(constructor1);//Cat(String name) 有形参的构造器
	  
   }
}


反射优点和缺点

package com.godairo.reflection;

import com.godairo.Cat;

import java.lang.reflect.Method;

/**
 * @author GodAiro
 * Creation Time: 2022/7/17 16:06.
 * 测试反射调用的性能,和优化方案
 */
public class Reflection02 {

   public static void main(String[] args) throws Exception {
	  m1();
	  m2();
   }
   
   //传统方法调用hi()方法
   public static void m1(){
	  Cat cat = new Cat();
	  long start = System.currentTimeMillis();
	  for (int i = 0; i < 9000000; i++) {
		 cat.hi();
	  }
	  long end = System.currentTimeMillis();
	  System.out.println("m1() 耗时="+(end-start));
   }
   
   
   //反射机制调用hi()方法
   public static void m2 ()throws Exception{

	  Class cls = Class.forName("com.godairo.Cat");
	  Object o = cls.newInstance();
	  Method hi = cls.getMethod("hi");
	  long start = System.currentTimeMillis();
	  for (int i = 0; i < 9000000; i++) {
		 hi.invoke(o); //反射调用方法
	  }
	  long end = System.currentTimeMillis();
	  System.out.println("m2() 耗时="+(end-start));
   }
}

为了方便调用,把实体类的hi方法输出语句可以先去掉。

确实反射方法调用性能会低点 


反射调用优化-关闭访问检查

public static void m3 ()throws Exception{

	  Class cls = Class.forName("com.godairo.Cat");
	  Object o = cls.newInstance();
	  Method hi = cls.getMethod("hi");
	  hi.setAccessible(true); //取消在反射调用方法,取消访问检查
	  long start = System.currentTimeMillis();
	  for (int i = 0; i < 9000000; i++) {
		 hi.invoke(o); //反射调用方法
	  }
	  long end = System.currentTimeMillis();
	  System.out.println("m3() 耗时="+(end-start));
   }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GodAiro

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值