不懂就看!P7 大牛珍藏的 Java 反射详解笔记,从入门到实践太香了
今日分享开始啦,请大家多多指教~
这篇文章给大家先简简单单地说下类的加载,以及具体实现,可以自己操作一下哦!
类的加载
在程序运行后,首次使用某个类,会把这个类的字节码文件读取到内存,并且会将这个类的所有信息存到一个 Class 对象中。
简单步骤:
1:jvm 执行代码,例如读到 new Student()
2 : 读取 Student 的字节码文件
3:把字节码文件的内容(读取成字节码对象)存储到方法区(以前的说法),1.8 以后叫做元空间(貌似)
4:最后类加载完成以后,在堆空间创建内存空间。
类的加载时机(下面六种)
创建类的实例。(new 一个类)
类的静态变量,或者为静态变量赋值。
类的静态方法。
使用反射方式来强制创建某个类或接口对应的 java.lang.Class 对象。
初始化某个类的子类。
直接使用 java.exe 命令来运行某个主类。(编译 javac 类名.java, 运行 java.类名)
今天的反射也属于类加载时机的一种
先上代码:
类加载时机代码演示
创建类的实例。 静态代码块随着类的加载而加载,并且只执行一次。
类的静态变量,或者为静态变量赋值。
类的静态方法。
4.反射通过 Class.forName("全类名") 进行反射
5.通过子类实例
运行结果
都证明了这个 stu 类被加载了。
类加载器(暂时先了解了解)
下面说说类加载器,类加载器是负责将实际空间中的某个 class 文件读取到内存中并且生成 Class 的对象。
Java 中有三种类加载器,它们分别用于加载不同种类的 class:
Java 中有三种类加载器,它们分别用于加载不同种类的 class:
启动类加载器(Bootstrap ClassLoader):用于加载系统类库<JAVA_HOME>\bin 目录下的 class,例如:rt.jar。
扩展类加载器(Extension ClassLoader):用于加载扩展类库<JAVA_HOME>\lib\ext 目录下的 class。
应用程序类加载器(Application ClassLoader):用于加载我们自定义类的加载器。
进去代码看看,我们是如何获得类加载器的
再点进 getClassLoader()方法看看 jdk 是怎么描述的
图中看到,一些实现可能使用 null 来表示引导类加载器,可能在此类中的实现返回 null.
举个例子。
好了,接下来该回到反射的主题
反射的概念
它一种机制,利用这个机制就可以在程序中对类进行解析,并且可以操作类中所有成员(变量,方法,构造方法)。
使用反射需要一个前提,获取需要反射的那个类的字节码对象。
Class 对象的获取方式
通过类名.class 获得
通过对象名.getClass()方法获得
通过 Class 类的静态方法获得: static Class forName(“类全名”)
Tips:每个类的 Class 对象都只有一个
Class 类常用的方法
String getSimpleName(); 获取类名字符串 String getName(); 获取全类名字符串
创建类的对象
1.T newInstance(): 创建 Class 对象关联类的对象。
2.通过 Constructor 类来创建对象
首先要获取构造器类
Class 类中与 Constructor 相关的方法
1.Constructor getConstructor(Class… parameterTypes)* 根据参数类型获得对应的 Constructor 对象。
getConstructor()的源码描述
上个使用的代码
如图所述,如果传入了没有相关参数重载的构造器,会报 NoSuchMethodException 异常
2.Constructor getDeclaredConstructor(Class… parameterTypes)
根据参数类型获得对应的 Constructor 对象
可以是 public、protected、(默认)、private 修饰符的构造方法。
如果是被 protected、(默认)、private 修饰符修饰的构造器,需要确定本身能否访问到,如果不能访问到就要设置权限,用 setAccessible(true)。
暴力获取构造器,能获取包括 public protected default private
通过 getDeclaredConstructor()暴力获取 Student 类中除了 public 其他修饰符的构造器,但这个构造类对象需要设置权限,setAccessible(true)
具体要不要设置,得看这个修饰符本身能否访问到相关资源。
图上是个反例。
3.Constructor[] getConstructors()获得类中的所有构造方法对象,只能获得 public 的
上代码:
通过 getConstructors()获取所有 public 修饰的构造器类对象。
遍历打印的结果:
4.Constructor[] getDeclaredConstructors()获得类中的所有构造方法对象
可以是 public、protected、(默认)、private 修饰符的构造方法。
通过 getDeclaredConstructors()获取所有 p 修饰的构造器类对象。
遍历打印的结果:
获取成员方法
接下来的部分就不放代码演示了,就提供下 api。
1 Method getMethod(String name,Class...args);
方法名和参数类型获得对应的成员方法对象,只能获得 public 的
2 Method getDeclaredMethod(String name,Class...args);
根据方法名和参数类型获得对应的成员方法对象,包括 public、protected、(默认)、private 的
3 Method[] getMethods();
获得类中的所有成员方法对象,返回数组,只能获得 public 修饰的且包含父类的
4Method[] getDeclaredMethods();
获得类中的所有成员方法对象,返回数组,只获得本类的,包括 public、protected、(默认)、private 的
通过反射访问成员变量
Method 对象常用方法
Object invoke(Object obj, Object... args)
调用指定对象 obj 的该方法
args:调用方法时传递的参数
void setAccessible(true)
设置"暴力访问"——是否取消权限检查,true 取消权限检查,false 表示不取消
通过反射获取类的成员变量
Class 类中与 Field 相关的方法
Field getField(String name);
根据成员变量名获得对应 Field 对象,只能获得 public 修饰
Field getDeclaredField(String name);
根据成员变量名获得对应 Field 对象,包括 public、protected、(默认)、private 的
Field[] getFields();
获得所有的成员变量对应的 Field 对象,只能获得 public 的
Field[] getDeclaredFields();
获得所有的成员变量对应的 Field 对象,包括 public、protected、(默认)、private 的
通过反射访问成员变量
Field 对象常用方法
今日份分享已结束,请大家多多包涵和指点!
评论