《Java工程师必读手册》——Java编程技巧系列——Java编程技巧之数据结构(4)

简介: 《Java工程师必读手册》——Java编程技巧系列——Java编程技巧之数据结构(4)

接上篇:https://developer.aliyun.com/article/1228148?spm=a2c6h.13148508.setting.27.21084f0eNCKPti


六、 定义Holder类实现参数的输出

 

在很多语言中,函数的参数都有输入(in)、输出(out)和输入输出(inout)之分。在C/C++语言中,可以用对象的引用(&)来实现函数参数的输出(out)和输入输出(inout)。

 

但在Java语言中,虽然没有提供对象引用类似的功能,但是可以通过修改参数的字段值来实现函数参数的输出(out)和输入输出(inout)。

 

这里,我们叫这种输出参数对应的数据结构为Holder(支撑)类。

 

1. Holder类实现代码

 

image.png 

 

2. Holder类使用案例

 

image.png 

 

其实,可以实现一个泛型支撑类,适用于更多的数据类型。

 

七、 定义Union类实现数据体的共存

 

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

 

结构体(struct)中所有变量是“共存”的,同时所有变量都生效,各个变量占据不同的内存空间;

联合体(union)中是各变量是“互斥”的,同时只有一个变量生效,所有变量占据同一块内存空间。

 

当多个数据需要共享内存或者多个数据每次只取其一时,可以采用联合体(union)。

 

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

 

这里,以微信协议的客户消息为例说明。根据我多年来的接口协议封装经验,主要有以下两种实现方式。

 

1. 使用函数方式实现Union

 

1) 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;

    }

    

    ...

}

 

2) Union类使用

 

image.png

 

3) 主要优缺点

 

优点:更贴近C/C++语言的联合体(union);

缺点:实现逻辑较为复杂,参数类型验证较多。

 

2. 使用继承方式实现Union

 

1) 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;

    }

}

 

2) Union类使用

 

image.png

 

3) 主要优缺点

 

优点:使用虚基类和子类进行拆分,各个子类对象的概念明确;

缺点:与C/C++语言的联合体(union)差别大,但是功能上大体一致。

 

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


 接下篇:https://developer.aliyun.com/article/1228146?groupCode=java

 

相关文章
|
9天前
|
存储 Java
Java数据结构:链表
Java数据结构:链表
21 2
|
9天前
|
算法 Java
Java数据结构——队列
Java数据结构——队列
25 4
|
9天前
|
Java 索引
Java数据结构——栈
Java数据结构——栈
22 1
|
9天前
|
Java
DAY-1 | Java数据结构之链表:删除无头单链表中等于给定值 val 的所有节点
力扣203题解:使用时间复杂度为O(n)的思路删除链表中所有值为key的元素。引入辅助指针pre,记录cur的前一个节点,遍历链表时,若cur.val!=key,pre和cur同时前进;若cur.val==key,则pre.next=cur.next,cur继续前进,确保pre不急于跟随以处理连续相同值的情况。遍历结束后,处理头节点可能需要删除的特殊情况。
22 0
|
12天前
|
算法 搜索推荐 Java
Java数据结构 -- 常见算法分析(查找算法、排序算法)精解详解!!!
Java数据结构 -- 常见算法分析(查找算法、排序算法)精解详解!!!
7 0
|
12天前
|
Java
JAVA数据结构刷题 -- 二叉树进阶
JAVA数据结构刷题 -- 二叉树进阶
19 0
|
12天前
|
存储 Java
JAVA数据结构刷题 -- 力扣二叉树
JAVA数据结构刷题 -- 力扣二叉树
18 0
|
5天前
|
Java 开发者 UED
掌握Java多线程编程:从基础到高级
【5月更文挑战第31天】本文深入探讨了Java多线程编程的核心概念,包括线程的创建、生命周期、同步机制以及高级并发工具。通过实际示例和代码片段,读者将学会如何有效地管理和协调线程,以编写高效且稳定的并发应用程序。
|
5天前
|
安全 Java 调度
Java语言多线程编程技术深度解析
Java语言多线程编程技术深度解析
271 1
|
1天前
|
算法 安全 Java
Java性能优化(五)-多线程调优-Lock同步锁的优化
基本特点Lock锁的基本操作通常基于乐观锁实现,尽管在某些情况下(如阻塞时)它也可能采用悲观锁的策略。通过对比图,我们可以清晰地看到两种同步锁的基本特点。Lock同步锁与Synchronized的比较在Java中,同步锁机制是确保多线程安全访问共享资源的重要手段。与JVM隐式管理锁的Synchronized相比,Lock同步锁(以下简称Lock锁)提供了更细粒度的控制,通过显式地获取和释放锁,为开发者提供了更大的灵活性。一、基本特点。
11 1