transient修饰符

1.简述

  transient修饰符用于类属性、变量,表示该类的序列化过程在为该类的任何实例创建持久字节流时应该忽略此类变量。

  transient使用场景

  • 在类实现序列化接口,而类下某个变量不想被序列化的情况下,用transient修饰该变量,可避免该变量被序列化。

2.transient的使用

  在Java中,对象的序列化可以通过两种接口来实现,若实现的是Serializable接口,则所有的序列化将会自动进行,若实现的是Externalizable接口,则没有任何东西可以自动序列化,需要在writeExternal方法中进行手动指定所要序列化的变量,这与是否被transient修饰无关。

  实现Serializable接口示例

public class Test {
    public static void main(String[] args) throws Exception {
        User user = new User("test", "123456");
        System.out.println("写入文件前:name="+user.getName()+" password="+user.getPassword());
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("d:/Desktop/user.txt"));
        out.writeObject(user);
        out.flush();
        out.close();
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("d:/Desktop/user.txt"));
        User u = (User)in.readObject();
        in.close();
        System.out.println("重新读取后:name="+u.getName()+" password="+u.getPassword());
    }
}

class User implements Serializable{
    private static final long serialVersionUID = 1L;
    private String name;
    private transient String password;
    
    public User(String name,String password){
        this.name = name;
        this.password = password;
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}
View Code

运行结果

写入文件前:name=test password=123456

重新读取后:name=test password=null

  通过上面的示例我们可以看出以下几点:

  • 一旦变量被transient修饰,变量将不再是对象持久化的一部分,该变量内容在序列化后无法获得访问。
  • transient关键字只能修饰变量,而不能修饰方法和类。注意,本地变量是不能被transient关键字修饰的。变量如果是用户自定义类变量,则该类需要实现Serializable接口。
  • 被transient关键字修饰的变量不再能被序列化,一个静态变量不管是否被transient修饰,均不能被序列化。

  实现Externalizable接口示例

public class Test {
    public static void main(String[] args) throws Exception {
        User user = new User("test", "123456");
        System.out.println("写入文件前:name="+user.getName()+" password="+user.getPassword());
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("d:/Desktop/user.txt"));
        out.writeObject(user);
        out.flush();
        out.close();
        ObjectInputStream in = new ObjectInputStream(new FileInputStream("d:/Desktop/user.txt"));
        User u = (User)in.readObject();
        in.close();
        System.out.println("重新读取后:name="+u.getName()+" password="+u.getPassword());
    }
}

class User implements Externalizable{
    private String name;
    private String password;
    
    public User(){}
    public User(String name,String password){
        this.name = name;
        this.password = password;
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }

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

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

运行结果

写入文件前:name=test password=123456

重新读取后:name=test password=null

  通过上面的示例我们可以看出,在Exteralizable接口实现类中完全不一样,被transient修饰的属性,在exteralWrite中被写入,就能被序列化。

3.总结

transient使用总结

  • 修饰符transient可以应用于类的字段成员,以关闭这些字段成员的序列化。
  • 你可以在需要对现有状态字段进行保护或计算的字段的类中使用transient修饰符。当序列化那些字段(如日志记录器和线程)毫无意义时,可以使用它。
  • 序列化不关心访问修饰符,如private。所有非transient字段都被认为是对象持久状态的一部分,并且都符合持久状态的条件(实现Serializable接口的情况下)。
  • 无论何时将任何final字段、引用计算为常量表达式,JVM都会对其进行序列化,忽略transient修饰符的存在。
  • HashMap类是java中transient修饰符的一个很好的用例。

posted on 2020-12-21 10:11  码农记录  阅读(2038)  评论(0编辑  收藏  举报

导航