类加载器
作用: 1,加载字节码文件到内存中,
2.读取字节码目录下的资源文件
InputStream getResourseAsStream(路径)
路径,直接从字节码的根目录开始寻找东西即可, 因为类加载知道字节码目录!!!
分类:从上到下 指逻辑上的父–子关系
启动类加载器:(Bootstrap ClassLoader)虚拟机内置的加载器.
平台类加载器:(Plaform ClassLoader)负责加载JDK中的一些特殊模块
系统类加载器:(System ClassLoader)负责加载用户类路径上所指定的类库
自定义类加载:(User ClassLoader):如有必要可以使用
全盘委托机制, 保证类只会被加载一次
获得系统类加载器的三种方法:
Class.forName(“全限定类名(包名+类名)”):主要是和配置文件结合时一般才会使用, 灵活度最高的
类名.class:已知类名的时候用此方法,返回Class对象
对象.getClass();已知对象的时候用此方法,返回Class对象
注意: 不管用那种方式去获取, 字节码都是唯一的, 因为类加载器有全盘委托机制
Class类成员方法:
public InputStream getResourceAaStream(String name); 加载某一个资源文件
反射
作用: 用来操作对象用的
前提: 必须获取该类的Class对象
1.操作构造函数Constructor
获取Constructor:
Constructor[] 字节码对象.getConstructors();
//获取所有公共的构造, 返回数组, 但是没有太大用处
Constructor[] 字节码对象.getDeclaredConstructors();
//获取所有的构造, 包含私有的, 但是没有太大的用途
Constructor 字节码对象.getConstructor(Class ... clazz);
//获取单个公共的构造,参数的意义防止重载现象
Constructor 字节码对象.getDeclaredConstructor(Class ... clazz);
//获取单个构造,包含私有的,,参数的意义防止重载现象
使用Constructor:
setAccessible(true);
//暴力反射, 如果构造是私有的时候, 在使用前必须暴力反射
构造函数对象.newInstance(Object...args)
//你获取的构造, 有几个参数, 传参时参数要一一对应
字节码对象.newInstance()
//要求你的无参构造被public修饰才可以使用, 这个APIjdk1.8后过时了, 不推荐使用
Constructor使用场景:反射 + 多态+配置文件
反射比较灵活, 可以和配置文件结合, 完成一些比较吊的操作
2.操作成员变量Field
获取Filed:
Field[] getFields();
//获取所有的公共的成员变量,不常用
Field[] getDecleardFields();
//获取所有的成员变量, 也不常用
Field getFiled(String 成员变量名);
//获取单个public修饰的, 不常用
Filed getDeclearedFiled(String 成员变量名);
//获取单个成员变量, 包含私有的(常用)
对其赋值和获取
setAccessible(true)
//暴力反射, 私有的成员变量必须暴力反射才可以操作
set(要被设置的对象,值)
get(要被获取的对象)
注意: 成员变量必须在对象身上才有意义!!!因为成员变量是在堆内存中才会进行初始化
3.操作成员方法Method
获取Method
Method[] getMethods();
//获取所有的public修饰的方法, 包含继承的,用的不多!
Method[] getDeclaredMethods();
//获取所有方法, 不包含继承的, 但是包含本类私有的, 用的也不是很多!
Method getMethod(方法名, Class ... 参数类型)
//获取public修饰的单个方法
Method getDeclaredMethod(方法名, Class ... 参数类型)
//获取方法对象, 包含私有的
执行Method
setAccessible(true);
//暴力反射, 私有的成员方法必须暴力反射才可以操作
Object invoke(要执行方法的对象, 执行方法所需要的实际参数)
//如果方法有返回值类型, 则需要接受 ,如果方法没有返回值, 不需要接受,如果没有返回值非要接受, 则接受到null