枚举类、序列化

一、枚举类

1.1 枚举类的特点

  1. 如果枚举类中只有一个对象,则可作为一种单例模式的实现方式
  2. 使用 enum 定义的枚举类默认继承了 java.lang.Enum 类
  3. 枚举类的构造方法只能是私有的,只能使用 private 修饰,如果使用其他的访问权限修饰符修饰则会报错
  4. 枚举类的所有对象都必须放在第一行显示列出,并且枚举类的所有对象默认被 public static final 修饰
  5. 多个对象之间用逗号 “,” 隔开,最后一个对象后面用分号 “;” 结束
  6. 枚举类中的对象不需要使用 new 关键字,不需要显式地调用构造方法,它会自动调用构造方法。
  7. 使用 enum 定义、非抽象的枚举类默认使用 final 修饰,不可以被继承。
  8. 枚举类每个成员变量的值是不能改变的,应该用 private final 修饰。

1.2 枚举类示例

enum Season{
    // 默认调用的是无参的构造方法
    SPRING, // 等价于:public static final Season SPRING = new Season();
    SUMMER,
    AUTUMN,
    WINTER;
    private Season(){ // 构造器需定义为私有的
        System.out.println("无参构造方法执行");
    }
}
enum Season{
    // 默认会调用有参构造方法
    SPRING("春天"), // 等价于:public static final Season SPRING = new Season("春天");
    SUMMER("夏天"),
    AUTUMN("秋天"),
    WINTER("冬天");

    private final String name; // 应该用 private final 修饰
    private Season(String name){ // 构造器需定义为私有的
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

1.3 Enum 类中的常用方法

  • toString():返回当前枚举类对象的名称
  • values():返回枚举类中所有的对象,以数组的形式返回
  • valueOf(String str):返回枚举类中对象名是 str 的对象,如果枚举类中没有名字是 str 的对象,则会抛出异常:IllegalArgumentException
public class SeasonTest {
    public static void main(String[] args) {
        System.out.println(Season.SPRING.toString());

        Season[] values = Season.values();
        for(Season value : values){
            System.out.println(value.getName());
        }
        
        System.out.println(Season.valueOf("WINTER1").getName());
    }
}
enum Season{
    // 默认会调用有参构造方法
    SPRING("春天"), // 等价于:public static final Season SPRING = new Season("春天");
    SUMMER("夏天"),
    AUTUMN("秋天"),
    WINTER("冬天");

    private final String name; // 应该用 private final 修饰
    private Season(String name){ // 构造器需定义为私有的
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

1.4 枚举类实现接口

  • 情况 1:在 enum 类中实现接口
public class SeasonTest {
    public static void main(String[] args) {
        Season.SPRING.show();
    }
}
interface Info{
    void show();
}
enum Season implements Info{
    SPRING, SUMMER, AUTUMN, WINTER;

    @Override
    public void show() {
        System.out.println("这是一个季节");
    }
}
  • 情况 2:让枚举类中的对象分别实现接口中的方法
public class SeasonTest {
    public static void main(String[] args) {
        Season.SPRING.show();
    }
}
interface Info{
    void show();
}
enum Season1 implements Info{
    SPRING{
        @Override
        public void show() {
            System.out.println("这是春天");
        }
    },
    SUMMER{
        @Override
        public void show() {
            System.out.println("这是夏天");
        }
    },
    AUTUMN{
        @Override
        public void show() {
            System.out.println("这是秋天");
        }
    },
    WINTER{
        @Override
        public void show() {
            System.out.println("这是冬天");
        }
    };
}

二、序列化

2.1 基础知识

  • 序列化:把内存中的 Java 对象转换成和平台无关的二进制流,从而允许把这这种二进制流持久地保存在磁盘上,或者通过网络将这种二进制流传输到另一个网络节点。
  • 反序列化:当其他程序获取了这种二进制流,就可以恢复成原来的 Java 对象
  • 自定义的类需要满足以下要求才能实现序列化:
    (1)自定义的类需要实现 Serializable 接口。Serializable 是标识接口,凡是实现了这个 Serializable 接口的类都是可序列化的
    (2)自定义类中的所有成员变量都必须是可序列化的
    (3)在自定义类中添加一个 serialVersionUID 常量
  • static 和 transient 修饰的成员变量不会被序列化
  • 注:凡是实现了 Serializable 接口的类都有一个表示序列化版本标识符的常量:private static final long serialVersionUID。serialVersionUID 用来表示类的不同版本之间的兼容性,Java 的序列化机制是通过判断运行时类的 serialVersionUID 来验证版本一致性的。如果类没有显式定义这个常量,那么 Java 序列化机制会根据编译的 Class 自动生成一个 serialVersionUID。如果类的实例变量做过改变,那么 serialVersionUID 可能会发生变化,导致反序列化的失败。即序列化 ID 是为了保证能够成功地进行反序列化
  • 如果 Class 文件没有发生变化,就算编译再多次, serialVersionUID 也不会变化的。
  • 具体的序列化过程:序列化操作的时候系统会把当前类的 serialVersionUID 写入到序列化文件中,当反序列化时系统会去检测文件中的 serialVersionUID,判断它是否与本地相应实体类的 serialVersionUID 一致,如果一致就说明序列化类的版本与当前类版本是一样的,可以反序列化成功,否则失败。
  • 示例:当我们编写一个类时,随着时间的推移,我们可能会因为需求改动,需要在本地类中添加其他的字段,这个时候再进行反序列化时便会出现 serialVersionUID 不一致,导致反序列化失败。那么如何解决呢?便是在本地类中添加一个“serialVersionUID”变量,值保持不变,便可以进行序列化和反序列化。

2.2 实际案例

import org.junit.Test;
import java.io.*;

public class XuLieHuaTest1 {
    // 序列化:将内存中的 Java 对象转换成和平台无关的二进制流,以保存到磁盘中或者通过网络传输出去
    @Test
    public void testObjectOutputStream(){
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("D://xuliehua.txt"));
            oos.writeObject(new User("张三", 18, new Account()));
            oos.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(oos != null){
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    // 反序列化:将序列化后生成的二进制流恢复成原来的 Java 对象
    @Test
    public void testObjectInputStream(){
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream("D://xuliehua.txt"));
            User user = (User)ois.readObject();
            System.out.println(user);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if(ois != null){
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
import java.io.Serializable;

public class User implements Serializable {
    private static final long serialVersionUID = 1231546514667L;
    private String name;
    private int age;
    private int num;
    private Account acct;
    public User(){}
    public User(String name, int age, Account acct){
        this.name = name;
        this.age = age;
        this.acct = acct;
    }

    public String getName() { return name; }

    public void setName(String name) { this.name = name; }

    public int getAge() { return age; }

    public void setAge(int age) { this.age = age; }

    public Account getAcct() { return acct; }

    public void setAcct(Account acct) { this.acct = acct; }

    @Override
    public String toString() {
        return "User{" + "name='" + name + '\'' + ", age=" + age + ", num=" + num + ", acct=" + acct + '}';
    }
}

class Account implements Serializable{
    public Account(){}
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

静波波呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值