Parcelable
Parcelable是一写一读两构造
写:writeToParcel
读:Creator静态内部类
两构造:一个用来外部new对象,一个给Creator用来构造对象
读写内容顺序要一致
读写的集合要先初始化,因为读取的时候要用
ArrayList<MyTarget> myTargets = new ArrayList<>();
in.readList(myTargets,MyTarget.class.getClassLoader());
package com.zsg.myparcelble;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
public class MyParcelble implements Parcelable {
String name;
int age;
MyTarget lisi;
ArrayList<MyTarget> myTargets = new ArrayList<>();
protected MyParcelble(Parcel in) {
this.age = in.readInt();
this.name = in.readString();
in.readList(myTargets,MyTarget.class.getClassLoader());
lisi = in.readParcelable(MyTarget.class.getClassLoader());
}
public MyParcelble(String name, int age, MyTarget lisi, ArrayList<MyTarget> myTargets) {
this.name = name;
this.age = age;
this.lisi = lisi;
this.myTargets = myTargets;
}
public static final Creator<MyParcelble> CREATOR = new Creator<MyParcelble>() {
@Override
public MyParcelble createFromParcel(Parcel in) {
return new MyParcelble(in);
}
@Override
public MyParcelble[] newArray(int size) {
return new MyParcelble[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(age);
parcel.writeString(name);
parcel.writeList(myTargets);
parcel.writeParcelable(lisi,0);
}
}
package com.zsg.myparcelble;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyTarget lisi = new MyTarget("lisi", 19);
MyTarget wanger = new MyTarget("wanger", 20);
MyTarget mazi = new MyTarget("mazi", 21);
ArrayList<MyTarget> myTargets = new ArrayList<>();
myTargets.add(wanger);
myTargets.add(mazi);
MyParcelble zhangsan = new MyParcelble("zhangsan", 18,lisi,myTargets);
Intent intent = new Intent(this, MainActivity2.class);
intent.putExtra("hh", zhangsan);
startActivity(intent);
}
}
package com.zsg.myparcelble;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.widget.TextView;
import java.util.ArrayList;
public class MainActivity2 extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
TextView textView = (TextView) findViewById(R.id.tv);
MyParcelble parcelableExtra = getIntent().getParcelableExtra("hh");
String name = parcelableExtra.name;
int age = parcelableExtra.age;
MyTarget lisi = parcelableExtra.lisi;
ArrayList<MyTarget> myTargets = parcelableExtra.myTargets;
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append(lisi.name).append(":").append(lisi.age);
for (MyTarget myTarget : myTargets) {
stringBuffer.append(myTarget.name).append(":").append(myTarget.age);
}
textView.setText(name+":"+age+stringBuffer.toString());
}
}
Serializable
*序列化
将数据结构或对象转换成二进制串的过程。
*反序列化
将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程
- Serializable 主要是用ObjectOutputStream 进行序列号,ObjectInputStream进行反序列化
- private static final long serialVersionUID 用于对象的版本控制,如果不写的话当修改了类中的任何字段,已经序列化的类将无法反序列化,因为新旧序列化对象中的serialVersionUID不同。
- transient的作用:静态和瞬时变量将不会被序列化。
- 类中的成员对象不实现Serializable将会报错。实现了Serializable的成员变量不用做其他操作,可以像平常的成员变量使用序列化。
- 实现了Serializable的子类如果想要保存父类中的信息,在序列化的时候必须用writeObject方法进行写,然后在反序列化的时候用readObject去进行读,并且父类必须要写空的构造方法,否则会报错,因为反序列化的时候是会反射父类的空参构造方法。
- 父类实现了Serializable则子类可以直接序列化操作不用写writeObject、readObject方法。如果子类中的某些字段不想序列化可以使用transient。如果子类全部不允许序列化,可以在writeObject、readObject、readObjectNoData方法中直接抛出异常。
throw new NotSerializableException("Can not serialize this class");
package com.zsg.serilable;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerialbleUtils {
private ObjectInputStream objectInputStream;
public static synchronized boolean saveObject(Object object, String path) {
if (object == null) {
return false;
}
ObjectOutputStream outputStream = null;
try {
outputStream = new ObjectOutputStream(
new FileOutputStream(path));
outputStream.writeObject(object);
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return false;
}
public static synchronized <T> T readObject(String path) {
ObjectInputStream objectInputStream = null;
try {
objectInputStream = new ObjectInputStream(
new FileInputStream(path));
try {
return ((T) objectInputStream.readObject());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (objectInputStream != null) {
try {
objectInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
```java
package com.zsg.serilable;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class MyClass {
public static final String path = "/Users/tenglixia/codestore/android/serialable/a.out";
public static void main(String[] args) {
NickName nickName2 = new NickName("lisi", "haha");
user zhangsan = new user("zhangsan", 18,"hah",nickName2);
SerialbleUtils.saveObject(zhangsan, path);
System.out.println("1: "+zhangsan);
zhangsan = SerialbleUtils.readObject(path);
System.out.println("fan : "+zhangsan);
}
public static class NickName /*implements Serializable*/{
String firstName;
String lastName;
public NickName(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return "NickName{" +
"firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
'}';
}
}
static class user implements Serializable {
public static final long serialVersionUID = 1;
private String name;
private int age;
private transient String nickName;
private NickName nickName2;
public user(String name, int age) {
this.name = name;
this.age = age;
}
public user(String name, int age, String nickName) {
this.name = name;
this.age = age;
this.nickName = nickName;
}
public user(String name, int age, String nickName, NickName nickName2) {
this.name = name;
this.age = age;
this.nickName = nickName;
this.nickName2 = nickName2;
}
@Override
public String toString() {
return "user{" +
"name='" + name + '\'' +
", age=" + age +
", nickName='" + nickName + '\'' +
", nickName2=" + nickName2 +
'}';
}
}
}
package com.zsg.serilable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class TwoExtendSeril {
public static void main(String[] args) {
user user = new user("zhangsan", 18, "nan", 100);
SerialbleUtils.saveObject(user,MyClass.path);
System.out.println("1: "+user.toString());
user = SerialbleUtils.readObject(MyClass.path);
System.out.println("fan : "+user);
}
public static class person {
private String sex;
private int id;
public person() {
}
public person(String sex, int id) {
this.sex = sex;
this.id = id;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@Override
public String toString() {
return "user{" +
"sex='" + sex + '\'' +
", id=" + id +
'}';
}
}
public static class user extends person implements Serializable {
private String name;
private int age;
public user(String name ,int age,String sex, int id) {
super(sex, id);
this.name = name;
this.age = age;
}
/* public user() {
super();
}*/
private void writeObject(ObjectOutputStream outputStream) {
try {
outputStream.defaultWriteObject();
outputStream.writeObject(getSex());
outputStream.writeInt(getId());
} catch (IOException e) {
e.printStackTrace();
}
}
private void readObject(ObjectInputStream objectInputStream) {
try {
objectInputStream.defaultReadObject();
setSex(((String) objectInputStream.readObject()));
setId(objectInputStream.readInt());
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
@Override
public String toString() {
return "user{" +
"name='" + name + '\'' +
", age=" + age +
", super=" + super.toString() +
'}';
}
}
}
Externalizable
Externalizable和Parcelable类似都是一写一读两构造:
一写:writeExternal
一读:readExternal
两构造:一个提供给外部new对象,一个空参提供给反射,没有空参会报错。
package com.zsg.serilable;
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
public class MyEexternalSrialable {
public static void main(String[] args) {
User user = new User("zhangsan", 18);
System.out.println(user);
SerialbleUtils.saveObject(user, MyClass.path);
user = SerialbleUtils.readObject(MyClass.path);
System.out.println(user);
}
public static class User implements Externalizable {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
public User() {
}
@Override
public String toString() {
return "user{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public void writeExternal(ObjectOutput objectOutput) throws IOException {
objectOutput.writeObject(name);
objectOutput.writeInt(age);
}
@Override
public void readExternal(ObjectInput objectInput) throws IOException, ClassNotFoundException {
this.name = (String) objectInput.readObject();
this.age = objectInput.readInt();
}
}
}
枚举类的序列化
Java的序列化机制针对枚举类型是特殊处理的。简单来讲,在序列化枚举类型时,只会存储枚举类的引用和枚举常量的名称。随后的反序列化的过程中,这些信息被用来在运行时环境中查找存在的枚举类型对象。
注:枚举类反序列化后拿到的是同一个对象。
package com.zsg.serilable;
enum EnumClazz {
ONE,TWO,THREE;
public void printValues() {
System.out.println("ONE: "+ ONE.ordinal()+" TWO: "+
TWO.ordinal()+" THREE: "+ THREE.ordinal());
}
public static void main(String[] args) {
SerialbleUtils.saveObject(EnumClazz.ONE,MyClass.path);
EnumClazz.ONE.printValues();
System.out.println("hashcode: "+ EnumClazz.ONE.hashCode());
System.out.println("fan :======");
EnumClazz enumClazz = SerialbleUtils.readObject(MyClass.path);
enumClazz.printValues();
System.out.println("hashcode: "+enumClazz.hashCode());
System.out.println(" === "+ (EnumClazz.ONE == enumClazz));
}
}
防止单例被反序列化
package com.example.xuliehuademo01;
import java.io.Serializable;
//Q: -当单例类被多个类加载器加载,如何还能保持单例?
//A: 用多个类加载器的父类来加载单例类
public class SingletonTest {
}
/**
* 单例类防止反序列化
*/
class Singleton implements Serializable{
public static Singleton INSTANCE = new Singleton();
private Singleton(){}
private Object readResolve(){
return INSTANCE;
}
}
/**
* 单例类如何防止反射
*/
class Singleton1 {
private static boolean flag = false;
private Singleton1(){
synchronized(Singleton.class){
if(flag == false){
flag = !flag;
} else {
throw new RuntimeException("单例模式被侵犯!");
}
}
}
private static class SingletonHolder {
private static final Singleton1 INSTANCE = new Singleton1();
}
public static Singleton1 getInstance(){
return SingletonHolder.INSTANCE;
}
}