Java序列化

    最近在牛客网上刷面试题,然后看到关于java序列化的问题,由于自己之前没有遇到过相关的问题,所以稍微花了点时间了解了一下Serializable及关键字transient。本文参考了网络上的一些文章。

什么是序列化和反序列化,序列化的用途是什么?

      序列化:把对象转化成字节序列的过程,称之为对象的序列化

      反序列化:把字节序列恢复为对象的过程,称之为对象的反序列化

更形象的说法:
java序列化技术可以使你将一个对象的状态写入一个byte流里,并且可以从其他地方把该byte流里的数据读出来。

换种方式来说,就是把内存中的对象给变成一连串的字节描述的过程,最常见的是将其变成文件。

用途:
想把内存中的对象保存到一个文件中或者数据库中的时候
想把对象通过网络进行传播的时候

如何序列化?
(1)只要一个类实现了Serilizable接口,那么这个类就是可序列化的,这个类中的属性和方法都会自动序列化。若某个属性被声明为transient,则该属性不用被序列化。
(2) 若实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手工指定所要序列化的变量,这与是否被transient修饰无关。

其中,在实现 Serilizable接口的类中,可以使用transient关键字使得该对象不用序列化。
当一个类已经被序列化后,该类中的某个属性不需要被序列化,可以加上transient关键字。
例如,一个用户有一些敏感信息,为了安全起见,不希望在网络操作(序列化操作)中被传输,这些信息对应的变量加上transient关键字。
/**
 *  使用transient关键字不序列化某个变量
 */
public class TransientTest {
    
    public static void main(String[] args) {
        
        User user = new User();
        user.setUsername("tammy");
        user.setPasswd("123456");
        
        System.out.println("read before Serializable: ");
        System.out.println("username: " + user.getUsername());
        System.err.println("password: " + user.getPasswd());
        
        try {
            ObjectOutputStream os = new ObjectOutputStream(
                    new FileOutputStream("C:/user.txt"));
            os.writeObject(user); // 将User对象写进文件
            os.flush();
            os.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            ObjectInputStream is = new ObjectInputStream(new FileInputStream(
                    "C:/user.txt"));
            user = (User) is.readObject(); // 从流中读取User的数据
            is.close();
            
            System.out.println("\nread after Serializable: ");
            System.out.println("username: " + user.getUsername());
            System.err.println("password: " + user.getPasswd());
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

class User implements Serializable {
    private static final long serialVersionUID = 8294180014912103005L;  
    
    private String username;
    private transient String passwd;
    
    public String getUsername() {
        return username;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    
    public String getPasswd() {
        return passwd;
    }
    
    public void setPasswd(String passwd) {
        this.passwd = passwd;
    }

}
结果:
read before Serializable: 
username: tammy
password: 123456

read after Serializable: 
username: tammy
password: null

注意:transient关键字只能修饰变量,而不能修饰方法和类
一个被static修饰的变量,无论是否还被transient修饰,都不能被序列化。
实现Externalizable接口实现序列化,加不加transient,没什么关系。
public class ExternalizableTest implements Externalizable {

    private transient String content = "是的,我将会被序列化,不管我是否被transient关键字修饰";

    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeObject(content);
    }

    @Override
    public void readExternal(ObjectInput in) throws IOException,
            ClassNotFoundException {
        content = (String) in.readObject();
    }

    public static void main(String[] args) throws Exception {
        
        ExternalizableTest et = new ExternalizableTest();
        ObjectOutput out = new ObjectOutputStream(new FileOutputStream(
                new File("test")));
        out.writeObject(et);

        ObjectInput in = new ObjectInputStream(new FileInputStream(new File(
                "test")));
        et = (ExternalizableTest) in.readObject();
        System.out.println(et.content);

        out.close();
        in.close();
    }
}
运行结果: 是的,我将会被序列化,不管我是否被transient关键字修饰
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值