Union

Union

在 C/C++语言中,联合体(Union),又称共用体,类似结构体(Struct)的一种数据结构。联合体(Union)和结构体(Struct)一样,可以包含很多种数据类型和变量,两者区别如下:

  • 结构体(Struct)中所有变量是“共存”的,同时所有变量都生效,各个变量占据不同的内存空间;
  • 联合体(Union)中是各变量是“互斥”的,同时只有一个变量生效,所有变量占据同一块内存空间。

当多个数据需要共享内存或者多个数据每次只取其一时,可以采用联合体(Union)。在 Java 语言中,没有联合体(Union)和结构体(Struct)概念,只有类(class)的概念。众所众知,结构体(Struct)可以用类(class)来实现。其实,联合体(Union)也可以用类(class)来实现。但是,这个类不具备“多个数据需要共享内存”的功能,只具备“多个数据每次只取其一”的功能。

使用函数方式实现 Union

/** 客户消息类 */
@ToString
public class CustomerMessage {

    /** 属性相关 */
    /** 消息类型 */
    private String msgType;
    /** 目标用户 */
    private String toUser;

    /** 共用体相关 */
    /** 新闻内容 */
    private News news;
    ...

    /** 常量相关 */
    /** 新闻消息 */
    public static final String MSG_TYPE_NEWS = "news";
    ...

    /** 构造函数 */
    public CustomerMessage() {}

    /** 构造函数 */
    public CustomerMessage(String toUser) {
        this.toUser = toUser;
    }

    /** 构造函数 */
    public CustomerMessage(String toUser, News news) {
        this.toUser = toUser;
        this.msgType = MSG_TYPE_NEWS;
        this.news = news;
    }

    /** 清除消息内容 */
    private void removeMsgContent() {
        // 检查消息类型
        if (Objects.isNull(msgType)) {
            return;
        }

        // 清除消息内容
        if (MSG_TYPE_NEWS.equals(msgType)) {
            news = null;
        } else if (...) {
            ...
        }
        msgType = null;
    }

    /** 检查消息类型 */
    private void checkMsgType(String msgType) {
        // 检查消息类型
        if (Objects.isNull(msgType)) {
            throw new IllegalArgumentException("消息类型为空");
        }

        // 比较消息类型
        if (!Objects.equals(msgType, this.msgType)) {
            throw new IllegalArgumentException("消息类型不匹配");
        }
    }

    /** 设置消息类型函数 */
    public void setMsgType(String msgType) {
        // 清除消息内容
        removeMsgContent();

        // 检查消息类型
        if (Objects.isNull(msgType)) {
            throw new IllegalArgumentException("消息类型为空");
        }

        // 赋值消息内容
        this.msgType = msgType;
        if (MSG_TYPE_NEWS.equals(msgType)) {
            news = new News();
        } else if (...) {
            ...
        } else {
            throw new IllegalArgumentException("消息类型不支持");
        }
    }

    /** 获取消息类型 */
    public String getMsgType() {
        // 检查消息类型
        if (Objects.isNull(msgType)) {
            throw new IllegalArgumentException("消息类型无效");
        }

        // 返回消息类型
        return this.msgType;
    }

    /** 设置新闻 */
    public void setNews(News news) {
        // 清除消息内容
        removeMsgContent();

        // 赋值消息内容
        this.msgType = MSG_TYPE_NEWS;
        this.news = news;
    }

    /** 获取新闻 */
    public News getNews() {
        // 检查消息类型
        checkMsgType(MSG_TYPE_NEWS);

        // 返回消息内容
        return this.news;
    }

    ...
}

Union 类使用如下:

String accessToken = ...;
String toUser = ...;
List<Article> articleList = ...;
News news = new News(articleList);
CustomerMessage customerMessage = new CustomerMessage(toUser, news);
wechatApi.sendCustomerMessage(accessToken, customerMessage);

使用继承方式实现 Union

/** 客户消息类 */
@Getter
@Setter
@ToString
public abstract class CustomerMessage {
    /** 属性相关 */
    /** 消息类型 */
    private String msgType;
    /** 目标用户 */
    private String toUser;

    /** 常量相关 */
    /** 新闻消息 */
    public static final String MSG_TYPE_NEWS = "news";
    ...

    /** 构造函数 */
    public CustomerMessage(String msgType) {
        this.msgType = msgType;
    }

    /** 构造函数 */
    public CustomerMessage(String msgType, String toUser) {
        this.msgType = msgType;
        this.toUser = toUser;
    }
}

/** 新闻客户消息类 */
@Getter
@Setter
@ToString(callSuper = true)
public class NewsCustomerMessage extends CustomerMessage {

    /** 属性相关 */
    /** 新闻内容 */
    private News news;

    /** 构造函数 */
    public NewsCustomerMessage() {
        super(MSG_TYPE_NEWS);
    }

    /** 构造函数 */
    public NewsCustomerMessage(String toUser, News news) {
        super(MSG_TYPE_NEWS, toUser);
        this.news = news;
    }
}

Union 类使用如下:

String accessToken = ...;
String toUser = ...;
List<Article> articleList = ...;
News news = new News(articleList);
CustomerMessage customerMessage = new NewsCustomerMessage(toUser, news);
wechatApi.sendCustomerMessage(accessToken, customerMessage);

在 C/C++语言中,联合体并不包括联合体当前的数据类型。但在上面实现的 Java 联合体中,已经包含了联合体对应的数据类型。所以,从严格意义上说,Java 联合体并不是真正的联合体,只是一个具备“多个数据每次只取其一”功能的类。

上一页