java反射机制

反射

1. 反射概述

  • Reflection被视为 动态语言,反射机制允许程序在执行期间借助于Reflection API 获取任何类的内部信息,并且 可以直接操作任意对象的属性和方法

  • 加载完类之后,在堆内存的方法区中包含一个Class类型的对象(一个类只有一个对象),这个对象包含完整的类的结构信息

    反射:实例化对象 -->getClass()–>得到完整的类

  • 框架=反射+注解+设计模式

  • java反射应用

    • 在运行时 判断任意一个对象所属的类
    • 在运行时 构造任意一个类的对象
    • 在运行时 判断任意一个类具有的成员变量方法
    • 在运行时 获得泛型信息
    • 在运行时 调用任意一个对象的属性 和方法
    • 在运行时 处理注解
    • 生成动态代理
  • 反射相关的主要API

    • java.lang.Class:代表一个类
    • java.lang.reflect.Method:代表类的方法
    • java.lang.reflect.Field:成员变量
    • java.lang.reflect.Constructor:类的构造器

2. Class类 并获取Class实例

Class clazz=Person.class;
//1.通过反射创建对象
Constructor con=clazz.getContructor(String.class,int.class);//获得构造方法
Object obj=con.netInstance("Tom",12);//获得实例
Person p=(Person)obj;

//2.通过反射可以调用属性 和方法
Field age=clazz.getDeclaredField("age");//属性
age.set(10);//给属性设置值

//3.调用方法
Method show=clazz.getDeclaredMethod("show");//第一个写方法名 后面是可变参数
show.invoke(p);//方法的调用
  • 一搬方式通过new创建对象 在外部不能对象调用其内部的私有结构
  • 但是 通过反射 可以调用私有属性 方法
Class clazz=Person.class;
//通过·反射 调用 私有结构 :私有构造器 方法 属性
// 1.私有构造器
Constructor cons=clazz.getDeclaredConstuctor(String.class);
cons.setAccessible(true);
Person p=(Person)cons.newInstance("Tom");//private Person(String name){this.name=name};

//2.私有属性
Field name=clazz.getDeclaredField("name");
name.setAccessible(true);// private String name;
name.set(p,"Lihua");

//3.私有方法
Method showNation =clazz.getDeclaredMethod("showNation",String.class);//
showNation.setAccessible(true);
String nation=(String)showNation.invoke(p,"China");//private String showNation(String nation)   showNation的返回值就是showNation.invoke(p,"China")的返回值

3. 类加载与ClassLoader

类加载过程

  • javac.exe编译生成.class文件
  • java.exe 命令对某个字节码文件进行解释运行 将字节码文件加载到内存中 (类加载)
  • 加载到内存中的类 称为运行时类 此运行时类 就作为Class的一个实例

ClassLoader的作用

将class文件字节码内容加载到内存中,并将这些数据静态数据转成方法区的运行时数据,然后在堆中生成一个代表这个类的java.lang.Class对象作为方法区中类数据的访问入口

类缓存

标准的javase类加载器可以按照要求查找类,一旦某个类加载到类加载器中,它将维持加载(缓存)一段时间,不过JVM垃圾回收可以回收这些class对象

ClassLoader

  • 类加载器的作用:把类装载到内存。

    BootStrap ClassLoader<–Extension ClassLoader <—System ClassLoader(app) <—自定义类加载器

    可以查看具体的双亲委派介绍
    超好的双亲委派

4. 创建运行时类的对象

获取Class的四种方式

//1.调用运行时类的属性:.calss
Class<Person> clazz1=Person.class;//Class clazz=Person.class;
//2.通过运行时的类的对象
Person p=new Person();
Class clazz2=p1.getClass();
//3.调用Class的静态方法  forName(String classPath)
Class clazz3=Class.forName("com.test.reflect.Person");//类的全路径 要throws ClassNotFounfException
//加载到内存中的运行时类 会缓存一段时间 在此期间之间 可以通过不同的方式来获取这个缓存中的实例 唯一存在的

//4.使用类的加载器
ClassLoader classLoader=ReflectionTest.class.getClassLoader();//获取当前运行时 类的类加载器
Class clazz4=classLoader.loadClass("com.test.Person");//加载类

有哪些类型可以有Class对象

  • class:外部类 成员(成员内部类 静态内部类),局部内部类,匿名内部类
  • 接口
  • 数组 只要数组的类型 维度一样 就是同一个Class
  • 枚举
  • 注解
  • 基本数据类型
  • void

5. 获取运行时类的完整结构

  • 获取运行时类的属性结构
Class clazz1=Person.class;

//获得属性结构
Field[] fields=clazz1.getFields(); //获取当前运行是 类 及其父类中声明为public的访问权限

//getDecalredFields()获取当前运行时类中所有的属性 不包含父类中声明的属性
Field[] declaredFields=clazz1.getDecalredFields();
for(Field f:declaredFields){
    //1.获取权限修饰符
    int i=f.getModifiers();//返回的是 Modifier中 权限修饰符的int整数
    String type=Modifier.toString(i);
    //2.数据类型
    Class type=f.getType();//获取数据的类型
    //3.变量名
    String name=f.getName();
}
  • 获取运行时类的方法结构
Class clazz=Person.class;
//getMethods 获取当前运行时类 及其父类public声明的方法
Method[] methods=clazz.getMethods();
//getDeclaredMethods获取当前运行时类声明的所有方法 不包含父类的
Method[] declaredMethods=clazz.getDeclaredMethods();
for(Method m:declaredMethods){
    //获取注解 
    Annotation[] annotations=m.getAnnotations();
    //权限修饰符 方法名 方法返回值 。。。。
    String quanxian=Modifier.toString(m.getModifiers());
    //返回值类型
    String returnType=m.getReturnType().getName();
    //方法名 
    String methodName=m.getName();
    //形参列表
    //m.getParameters();
    //抛出的异常 m.getExceptionsTypes()
    //.....
}

还有很多获取运行时类的内部结构 ,不得不说 ,真的很强大,把类一个一个的掰开。。。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值