1.过程
-
加载
- 把class文件加载到内存(通过类加载器),转为二进制数据
- 生成一个java.lang.Class的对象,作为方法区访问这个类的入口
-
链接
-
验证 : 主要进行正确性的校验(class文件) cafe babe “咖啡宝贝” 魔法数字
-
准备:给类的静态成员分配内存,赋默认值
-
static int a = 10;
-
-
解析: 把符号引用替换为直接引用(真实的内存地址)
-
-
初始化
- 执行静态代码块中的内容, 静态成员赋真实的值
- 执行静态代码块中的内容, 静态成员赋真实的值
2.获取字节码文件的3种方式
- 对象.getClass()
- 类名.class
- Class.forName(“全类名”)
配置文件(Properties)
配置文件里面一般放配置信息 , 数据库配置信息, 第三方服务的配置信息(账号信息 )
比如使用一个软件时,将其用户和密码放置到配置文件中
Properties
Properties
类表示了一个持久的属性集。Properties
可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串
构造方法
Properties() 创建一个无默认值的空属性列表。
成员方法
void | load(InputStream inStream) 从输入流中读取属性列表(键和元素对)。 |
---|---|
void | load(Reader reader) 按简单的面向行的格式从输入字符流中读取属性列表(键和元素对)。 |
String | getProperty(String key) 用指定的键在此属性列表中搜索属性。 |
---|---|
注意:
- 如果有中文 , 使用load(Reader reader)
- 注释使用#
3.字节码的运用
1.通过字节码反射获取类的构造方法
/*
*
* @author:alia
* @DATA : 2023/3/2112:09
*
* 通过反射获取Person这个类的构造方法
*/
public class Demo {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//通过字节码文件对象获取信息
Class<?> personClass = Class.forName("_23Reflect.Person");
System.out.println("获取所有的public构造方法");
Constructor<?>[] constructors = personClass.getConstructors();
for (Constructor c:constructors){
System.out.println(c);
}
System.out.println("------------------------");
//获取全部构造方法
Constructor<?>[] declaredConstructors = personClass.getDeclaredConstructors();
for (Constructor c:declaredConstructors){
System.out.println(c);
}
//获取无参构造方法(条件获取
Constructor<?> constructor = personClass.getConstructor();
//获取有参构造方法
Constructor<?> constructor1 = personClass.getConstructor(String.class, int.class, boolean.class);
Constructor<?> declaredConstructor = personClass.getDeclaredConstructor(String.class, int.class);
//使用构造方法创建对象
System.out.println("使用构造方法创造对象");
Object o = constructor.newInstance();
System.out.println(o);
//通过该方法设置后,可以使用私有构造方法创造对象
declaredConstructor.setAccessible(true);
}
}
2.通过字节码反射获取成员变量
通过反射获取所有成员变量
Field[] getFields()
Field[] getDeclaredFields()
获取指定成员变量
Field getField(String name)
Field getDeclaredField(String name)
通过Field读写对象的成员变量(可暴力破解)
Object get(Object obj):获取值,传入对象
void set(Object obj, Object value):赋值,传入对象
public class Demo2 {
public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
// 获取字节码文件对象
Class<?> personCls = Class.forName("com.cskaoyan.domain.Person");
System.out.println("获取所有的带public的成员变量------");
// Field[] getFields()
Field[] fields = personCls.getFields();
for (Field f : fields) {
System.out.println(f);
}
System.out.println("获取所有的成员变量------");
//Field[] getDeclaredFields()
Field[] declaredFields = personCls.getDeclaredFields();
for (Field f : declaredFields) {
System.out.println(f);
}
System.out.println("获取指定的public的成员变量------");
// Field getField(String name)
Field nameField = personCls.getField("name");
System.out.println(nameField);
//Field getDeclaredField(String name)
Field ageField = personCls.getDeclaredField("age");
Field genderField = personCls.getDeclaredField("gender");
System.out.println(ageField);
System.out.println(genderField);
// 设置 获取成员变量的值
//void set(Object obj, Object value):赋值,传入对象
// 先获取构造方法
Constructor<?> declaredConstructor = personCls.getDeclaredConstructor();
// 再实例化对象
Object o = declaredConstructor.newInstance();
nameField.set(o,"zs");
System.out.println(o);
// 忽略语法检查
ageField.setAccessible(true);
ageField.set(o,20);
System.out.println(o);
// Object get(Object obj):获取值,传入对象
Object o1 = nameField.get(o);
System.out.println(o1);
Object o2 = ageField.get(o);
System.out.println(o2);
}
}