Java反序列化原理
Serializable 接口的使用
类需要被序列化和反序列化,需要实现接口 java.io.Serializable
Java 提供的序列化接口 Serializable ,是一个空接口,没有成员方法和变量
1 2
| public interface Serializable { }
|
1 2 3 4 5 6
| import java.io.Serializable;
public class Example implements Serializable{ private String name; .... }
|
序列化 调用 ObjectOutputStream
类的 writeObject
方法
反序列化 调用 ObjectInputStream
类的 readObject
方法
注意:
只有实现了Serializable或者Externalizable接口的类的对象才能被序列化为字节序列,否则会抛出异常。Externalizable 接口继承自Serializable接口,实现 Externalizable接口的类完全由自身来控制序列化的行为,而仅实现 Serializable 接口的类可以采用默认的序列化方式。
- 它是Java 提供的序列化接口,是一个空接口,没有成员方法和变量
- 一个类要想序列化就必须继承java.io.Serializable接口,同时它的子类也可以序列化(不用再继承Serializable接口)
- 一个实现Serializable 接口的子类也是可以被序列化的。在反序列化过程中,它的父类如果没有实现序列化接口,那么父类将需要提供无参构造函数来重新创建对象,这样做的目的是重新初始化父类的属性,父类对应的属性不会被序列化
- 序列化只能保存对象的非静态成员变量,不能保存任何的成员方法和静态的成员变量,而且序列化保存的只是变量的值,对于变量的任何修饰符都不能保存。即序列化是保存对象的状态(对象属性)
- transient 标识的对象成员变量不参与序列化
- Serializable 在序列化和反序列化过程中大量使用了反射,因此其过程会产生的大量的内存碎片
注:JAVA会被称为八股文,原因在于它的一个小知识点里会有很多细节在里面
Person
Read More
Java反射&动态代理
反射机制
Java 反射(Reflection)是一种机制,它允许 Java 程序在运行时获取和操作它本身的数据结构,比如类、方法、属性等。通过反射,我们可以动态地创建对象、调用方法、访问属性等,而无需在编译时知道这些信息。
Java 反射主要包括以下几个核心类:
- Class 类:表示一个类或接口,包含了获取类信息的方法,如获取类名、父类、接口、属性、方法等。
- Constructor 类:表示一个构造函数,包含了获取构造函数信息的方法,如获取构造函数名、参数列表等。
- Field 类:表示一个属性,包含了获取属性信息的方法,如获取属性名、类型、访问权限等。
- Method 类:表示一个方法,包含了获取方法信息的方法,如获取方法名、参数列表、返回类型等。
以下是一些 Java 反射的常见用法:
- 获取类信息:通过
Class.forName()
方法获取某个类的 Class
对象,然后使用 Class
对象的各种方法获取类的信息,如 getName()
获取类名,getDeclaredMethods()
获取所有方法等。
- 创建对象:通过
Class
对象的 getConstructor()
或 getDeclaredConstructor()
方法获取指定构造函数的引用,然后使用 newInstance()
或 newInstance()
方法创建对象。
- 访问属性:通过
Class
对象的 getDeclaredField()
方法获取指定属性的引用,然后使用 set()
或 get()
方法设置或获取属性的值。
- 调用方法:通过
Class
对象的 getDeclaredMethod()
方法获取指定方法的引用,然后使用 invoke()
方法调用方法并传递参数。
- 动态代理:通过 Java 反射实现动态代理,可以在运行时创建一个实现了指定接口的代理类,并实现指定的方法逻辑。
Class
类就是通过Field
和Method
来描述类中的字段和方法
代码
Person 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package net.Seck2y.a02;
public class Person { private String name = "zhangsan"; private int age = 23;
public Person(){}
public Person(String name, int age) { this.name = name; this.age = age; }
public void action(String string){ System.out.println(string); } @Override public String toString(){ return "Person{" + "name: " + this.name + ", age: "+ this.age + "}"; } }
|
Reflection 类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| package net.Seck2y.a02;
import java.lang.reflect.*;
public class Reflection { public static void main(String[] args) throws Exception { Class<?> personClass = Class.forName("net.Seck2y.a02.Person"); Constructor<?> constructor = personClass.getConstructor(String.class, int.class);
Object person = constructor.newInstance("lisi", 24); System.out.println(person); Field[] personField = personClass.getDeclaredFields(); for (Field f:personField){ System.out.println(f); }
Field nameField = personClass.getDeclaredField("name"); Field ageField = personClass.getDeclaredField("age"); nameField.setAccessible(true); ageField.setAccessible(true); String name = (String) nameField.get(person); int age = (int) ageField.get(person); System.out.println( nameField.getName() + ": " + name + ", " + ageField.getName() + ": " + age); Field setName = personClass.getDeclaredField("name"); Field setAge = personClass.getDeclaredField("age"); setName.setAccessible(true); setAge.setAccessible(true); setName.set(person, "wangwu"); setAge.set(person, 25); System.out.println( setName.getName() + ": " +setName.get(person) + ", " + setAge.getName() + ": " + setAge.get(person)); Method[] personMethod = personClass.getDeclaredMethods(); for (Method m: personMethod) { System.out.println(m); }
Method actionMethod = personClass.getMethod("action",String.class); actionMethod.invoke(person,"Reflection"); } }
|
Class
Read More