0
点赞
收藏
分享

微信扫一扫

【卡卡谈Java】Java 反射

Java 反射


  同学们,今天我们来一起学习Java中的反射,反射在Java中也是一个比较重要的知识点,通过这篇文章同学们能够清晰的明白反射的原理以及在我们日常开发中如何正确的运用。

反射概念

  Java反射机制是在程序运行过程中,对于任意一个类都能够直到这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能我们称为Java的反射机制。

类加载过程

在学习反射之前我们先来学习一下类加载过程:

类加载图解1
类加载过程图解
类加载过程3
详细过程如下所示:
加载-验证-准备-解析-初始化-使用-卸载,其中验证-准备-解析称为链接

加载

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

链接(将java类的二进制代码合并到jvm的运行状态之中的过程)

  • 验证
    确保加载的类信息符合JVM规范,没有安全方面的问题
  • 准备
    正式为类变量(static变量)分配内存并设置类变量初始值的阶段,这些内存都在方法区进行分配
  • 解析
    虚拟机常量池中的引用替换为直接引用的过程(比如String a = “aaa”;转化为a的地址指向"aaa"的地址)

初始化

初始化阶段是执行类构造器的过程。类构造器方法是由编译器自动收集类中的所有变量赋值的动作和静态语句块(static)中的语句合并产生的。

双亲委派机制

  所谓双亲委派模型,就是指一个类接收到类加载请求后,会把这个请求依次传递给父类加载器(如果还有的话),如果顶层的父类加载器可以加载,就成功返回,如果无法加载,再依次给子加载器去加载。

反射的使用

获取Class对象的方式

  • 对象.getClass();
  • 任何数据类型(包括基本数据类型)都包含一个”静态“的Class属性:类名.class
  • 通过Class的静态方法:forName(String className):Class.forName(“类的全路径”);

常用方法

获取包名 类名
clazz.getPackage().getName()//包名
clazz.getSimpleName()//类名
clazz.getName()//完整类名

获取成员变量定义信息
getFields()//获取所有公开的成员变量,包括继承变量
getDeclaredFields()//获取本类定义的成员变量,包括私有,但不包括继承的变量
getField(变量名)
getDeclaredField(变量名)

获取构造方法定义信息
getConstructor(参数类型列表)//获取公开的构造方法
getConstructors()//获取所有的公开的构造方法
getDeclaredConstructors()//获取所有的构造方法,包括私有
getDeclaredConstructor(int.class,String.class)

获取方法定义信息
getMethods()//获取所有可见的方法,包括继承的方法
getMethod(方法名,参数类型列表)
getDeclaredMethods()//获取本类定义的的方法,包括私有,不包括继承的方法
getDeclaredMethod(方法名,int.class,String.class)

反射新建实例
clazz.newInstance();//执行无参构造创建对象
clazz.newInstance(666,”海绵宝宝”);//执行含参构造创建对象
clazz.getConstructor(int.class,String.class)//获取构造方法

反射调用成员变量
clazz.getDeclaredField(变量名);//获取变量
clazz.setAccessible(true);//使私有成员允许访问
f.set(实例,);//为指定实例的变量赋值,静态变量,第一参数给null
f.get(实例);//访问指定实例变量的值,静态变量,第一参数给null

反射调用成员方法
Method m = Clazz.getDeclaredMethod(方法名,参数类型列表);
m.setAccessible(true);//使私有方法允许被调用
m.invoke(实例,参数数据);//让指定实例来执行该方法

结语

  以上就是卡卡今日分享的Java 反射的主要内容,如果有写错的地方,希望同学们踊跃在评论区指出来,欢迎大家一起分享学习。

举报

相关推荐

0 条评论