优秀的编程知识分享平台

网站首页 > 技术文章 正文

我实现了Java多返回值

nanyue 2025-03-12 19:02:01 技术文章 2 ℃

大学时,实验室老师在为我们讲解各编程语言优缺点的时候,讲到Java时展示了一个这样的聊天框:

C:我能直接操作指针

Java:我生态好

PHP:我撸码快如闪电

Java:我生态好

Python:我的方法能够返回多个返回值

Java:......

Java作为编程界的老大哥,丰富的生态,跨平台,垃圾回收等等优点让人好不喜爱,但从编码上来讲,它有一个非常致命的缺点,就是他一个方法只能返回一个值,也就意味你如果需要返回多个值,你必须重新定义一个对象以包装这些值。

身为攻城狮的我,我必须优雅的摆脱单返回值的束缚,更不能让Map拖了后腿,我必须做点什么了。


小试牛刀

Java虽然只支持单返回值,但是并没有限制一个对象中返回的字段数量,那么我们就有两种方式,第一种就定义一个对象,然后在该对象中定义多个字段,类型全部声明为Object,但是这种太不优雅了,根本不知道具体的类型是什么。

那么我们立马就想到了参数化类型,把所有字段参数化,用的时候再指定具体类型,好,那么说干就干,直接上十个。

package main.java.com.github.dto;

import lombok.Data;

/**
 * @Description: 多返回值实体
 * @author: coffe
 * @date: 2023/7/25 19:32
 */
@Data
public class DynamicMultipleResultDto {

    /**
     * 第一个值
     */
    private First first;

    /**
     * 第二个值
     */
    private Second second;

    /**
     * 第三个值
     */
    private Third third;

    /**
     * 第四个值
     */
    private Fourth fourth;

    /**
     * 第五个值
     */
    private Fifth fifth;

    /**
     * 第六个值
     */
    private Sixth sixth;

    /**
     * 第七个值
     */
    private Seventh seventh;

    /**
     * 第八个值
     */
    private Eighth eighth;

    /**
     * 第九个值
     */
    private Ninth ninth;

    /**
     * 第十个值
     */
    private Tenth tenth;
}

怎么说呢,有点优雅,但更多的是浮夸,我一个对象中真的需要返回这么多的字段吗,如果我只想返回两三个字段,那后面的泛型填充将会变得非常麻烦;并且这样的命名方式毫无区分性可言,就是一到十直接梭哈,会无限膨胀。

有点东西,但不多

于是乎,为了解决泛型数量过多的问题,我们对多返回值对象做如下改良:

package main.java.com.github.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.Map;

/**
 * @Description: 五倍返回实体
 * @author: coffe
 * @date: 2023/6/28
 */
public class DynamicFivefoldResultDto {

    private Map resultMap;

    public DynamicFivefoldResultDto(Integer size) {
        if (size == null || size > FivefoldEnum.values().length) {
            throw new IllegalArgumentException("size must not be null and less than " + FivefoldEnum.values().length);
        }
        resultMap = new HashMap(size);
    }

    /**
     * 储值
     *
     * @param fivefoldEnum 枚举键值
     * @param remark 备注
     * @param val 具体值
     * @return
     */
    public DynamicFivefoldResultDto put(FivefoldEnum fivefoldEnum, String remark, Object val) {
        if (fivefoldEnum == null || StringUtils.isEmpty(remark) || val == null) {
            throw new IllegalArgumentException("param deletion");
        }
        resultMap.put(fivefoldEnum, val);
        return this;
    }

    /**
     * 获取值
     *
     * @param fivefoldEnum 枚举键值
     * @param remark 备注
     * @return
     */
    public Object get(FivefoldEnum fivefoldEnum, String remark) {
        if (fivefoldEnum == null || StringUtils.isEmpty(remark)) {
            throw new IllegalArgumentException("param deletion");
        }
        return resultMap.get(fivefoldEnum);
    }

    @Getter
    @AllArgsConstructor
    public enum FivefoldEnum {
        FIRST,SECOND,THIRD,FORTH,FIFTH;
    }
}

也就是我们通过定义枚举+Map+参数含义的形式,put时需要指定三个值,其一是枚举值,其二是真实的值,其三是这个值的含义。然后get时也需要指定该值的含义,这样就能避免多泛型的填充问题,也能清楚的知道字段的含义。但是这里有一个和文章开头冲突的点,就是我们好像又陷入了Map的误区当中,我们get的时候根本不知道里面已经存在的key是什么,当然这是map的通病引起的。并且我们这个枚举命名依然存在的点是没有区分性。

刚刚好

那么有没有一个对象刚刚好能够解决上面的问题点,并且不带来新的问题,甚至有更多的优点呢。

接下来我们有请今天的主角隆重登场:

org.apache.commons.lang3.tuple.ImmutablePair
org.apache.commons.lang3.tuple.ImmutableTriple


  	org.apache.commons
		commons-lang3

由commons-lang3提供的两个实体类,当我们需要返回两个值时使用ImmutablePair,三个值时使用ImmutableTriple。我们来看下这两个类的使用方式:

public static void main(String[] args) {
        ImmutablePair pair = ImmutablePair.of(true, "pair");
        System.out.println(pair.getLeft());
        System.out.println(pair.getRight());

        ImmutableTriple triple = ImmutableTriple.of(true,"triple",18);
        System.out.println(triple.getLeft());
        System.out.println(triple.getMiddle());
        System.out.println(triple.getRight());
    }

可以看到这两个类从命名上就很有意思,简单翻译一下,ImmutablePair-不可变的一对,ImmutableTriple-不可变的三个,属性字段就更有意思了,左右和左中右,相比一到十来说,这个就非常有辨识度了,并且天然具备约束性,不能无限扩张,并且也是采用泛型的形式,能够很清楚的知道具体是返回的什么类型;并且属于commons公共包,无需我们到处复制即可引用。


以上就是本篇文章的所有内容,虽然是一个非常微小的知识点,但也值得分享出来,困扰我多年的问题终于有了答案,在我调研完成后,这个小小的知识点大大的提升了我的工作效率,我再也不用纠结是否需要定义一个对象去承接多返回值,也不用因为直接返回Map而被骂猪队友。一切都是刚刚好,让返回多个值更加优雅。

如果大家还有更好的解决方案,欢迎评论区留言或者直接邮件我,一起拥抱分享与开源。

分享一句非常喜欢的话:把根牢牢扎深,再等春风一来,便会春暖花开。

PS:以上引用信息以及图片均来自网络公开信息,如有侵权,请留言或联系

504401503@qq.com,立马删除。

最近发表
标签列表