V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
RiceMarch
V2EX  ›  Java

Java 泛型 接口返回类 如何面对 空?

  •  
  •   RiceMarch · Apr 10, 2021 · 4840 views
    This topic created in 1844 days ago, the information mentioned may be changed or developed.

    Java 接口返回类 中 泛型如何面对 返回值本应为null的情况??

    在设计 web 应用中的返回基础类时,我会这样写

    public class BaseResponse<T> implements Serializable {
       private static final long serialVersionUID = 1L;
    
        private int code;
        private String message;
        private T data;
    
        //... 省略构造方法等
    
        public static BaseResponse success() {
            return new BaseResponse();
        }
         public static BaseResponse success(String message) {
            return new BaseResponse(RespCodeEnum.SUCCESS, message);
        }
        
        //... 省略失败等
    }
    
    

    当在 controller 中 使用这些基础返回类进行数据包装时,通过泛型进行返回内容的指定

    但 例如一些添加操作时,将不会有具体的返回值,只会返回 code 来判断是否操作成功

    @PostMapping("/something")
    public BaseResponse postSomething(@Valid @RequestBody Something request) {
    
        //添加操作
    
        //根据添加操作判断返回内容
        // if success
        return new BaseResponse.success();
    
        // if failed ...
    }  
    

    在上述代码中,我没有指定泛型类型,因为有些添加操作时,没有具体的返回值内容,我本来想写成 public BaseResponse<Void> postSomething,但在return时,却不知道该如何写。

    想请问一下,指定泛型类型 理论上应该是都进行的(如果说错,请不要打我,个人想法 /(ㄒoㄒ)/~~),

    但在这里如何进行正确的泛型类型指定呢(或者说需要指定泛型么)?

    (太多知识不懂,天天来问 v 友,学到了很多,感谢感谢

    28 replies    2021-04-14 18:23:10 +08:00
    66Zi2nJk5Z6mdtzj
        1
    66Zi2nJk5Z6mdtzj  
       Apr 10, 2021 via iPhone
    没记错的话,我应该用的是问号
    xarthur
        2
    xarthur  
       Apr 10, 2021 via iPhone
    不要用 null 不就行了……
    用 Optional 。
    我以为 null-safety 已经是个常识了(
    xarthur
        3
    xarthur  
       Apr 10, 2021 via iPhone
    另外完全没看懂你的例子(
    RiceMarch
        4
    RiceMarch  
    OP
       Apr 10, 2021
    @xarthur 可能我表达的不太好 hhhh,就是 BaseResponse 基础返回类中的 data 在一些情况下是没有值的,只有 code 和 message 有值,在确定 data 是没有值的情况下,我还想要在写 controller 方法的时候指定泛型类型,该怎么指定。
    zhazi
        5
    zhazi  
       Apr 10, 2021 via Android
    Void
    chiikawa
        6
    chiikawa  
       Apr 10, 2021 via iPhone
    一楼是答案
    aguesuka
        7
    aguesuka  
       Apr 10, 2021 via Android   ❤️ 2
    不要使用问号作为泛型

    @PostMapping("/something")
    public BaseResponse<Void> /*改了这里*/postSomething(@Valid @RequestBody Something request) {

    //添加操作

    //根据添加操作判断返回内容
    // if success
    return new BaseResponse.<Void>/*会有灰色警告,即可将其省略*/success();

    // if failed ...
    }
    wolfie
        8
    wolfie  
       Apr 10, 2021
    上面说了 问号,或者不理会编译器提醒 不加泛型也没问题。
    passerbytiny
        9
    passerbytiny  
       Apr 10, 2021 via Android
    你需要构造的是:BaseResponse<Object>,在哪。任何类型可以承载 null,在你只需要它是 null 而不关心具体类型的时候,最高基类 Object 是一个勉强的选择。
    passerbytiny
        10
    passerbytiny  
       Apr 10, 2021 via Android
    如果你这里的泛型,并不是给类似 Swagger 这样的自动生成 API 文档的工具用的,那么它是画蛇添足的东西,因为 Cortroller 方法是非框架代码中的最外层——除了框架不会有人从它那里获取返回值。

    这里去掉泛型,直接将 data 定义成 Object 类型,会更好。
    AoEiuV020
        11
    AoEiuV020  
       Apr 10, 2021
    我一般用 String,
    xuanbg
        12
    xuanbg  
       Apr 10, 2021
    public class BaseResponse implements Serializable {
    private static final long serialVersionUID = 1L;

    private int code;
    private String message;
    private Object data;

    //... 省略构造方法等

    public static BaseResponse success() {
    return new BaseResponse();
    }
    public static BaseResponse success(String message) {
    return new BaseResponse(RespCodeEnum.SUCCESS, message);
    }

    //... 省略失败等
    }

    不用泛型,用 Object 。因为你不用知道类型也能序列化。
    xuanbg
        13
    xuanbg  
       Apr 10, 2021
    当然,你要用 swgger 这些自动化文档的话,返回的时候空也不影响啊。为啥要 new BaseResponse ? return this 就行了呀。

    public BaseResponse success() {
    setCode(200);
    setMessage("请求成功");

    return this;
    }
    Oktfolio
        14
    Oktfolio  
       Apr 10, 2021
    BaseResponse<?>
    zm8m93Q1e5otOC69
        15
    zm8m93Q1e5otOC69  
       Apr 10, 2021
    就是说你的 data 是 T 类型的?我们一般用<?>代替
    RiceMarch
        17
    RiceMarch  
    OP
       Apr 10, 2021
    @passerbytiny 但如果是 Object 的话,我就不能在编译和运行前就知道返回值是否是我期望的内容了啊。
    arthas2234
        18
    arthas2234  
       Apr 10, 2021   ❤️ 1
    我都是在 controller 直接返回对象,没有返回值就是 void
    然后实现 ResponseBodyAdvice 拦截 controller 方法默认返回参数,统一处理返回值
    RiceMarch
        19
    RiceMarch  
    OP
       Apr 10, 2021
    @arthas2234 拓展了新思路 🐂
    young1lin
        20
    young1lin  
       Apr 11, 2021
    我不建议你使用自定义的返回结果,使用 ResponseEntity<?> 就行了,真的,这个很重要。你必须了解各个状态码大概是什么意思,不要再二次包装 HTTP 状态了,那个不太好,对前端和对接的人,都是折磨,还要再解析一遍。
    chanchan
        21
    chanchan  
       Apr 11, 2021
    说?的我吐了,增加代码阅读成本
    Valid
        22
    Valid  
       Apr 11, 2021
    我这个名字每次都会被迫学习 java
    zm8m93Q1e5otOC69
        23
    zm8m93Q1e5otOC69  
       Apr 11, 2021
    返回值类中改成这样吧
    public static <T> Result<T> success(){
    return new Result<>(HttpStatus.Ok);
    }
    这样你写什么泛型都无所谓的。。你的 T 对应的都是 null 了
    使用就直接
    public Result<Void> test(){
    return Result.success();
    }
    RiceMarch
        24
    RiceMarch  
    OP
       Apr 11, 2021
    @young1lin 我也这么觉得! 但是看到公司是这么做的...所以就改变了我的思路
    RiceMarch
        25
    RiceMarch  
    OP
       Apr 11, 2021
    @Valid 哈哈哈哈哈哈 疯狂被 at 么
    young1lin
        26
    young1lin  
       Apr 11, 2021
    @RiceMarch 你可以记下来,写出对应的 Demo 让大家看,并记录有什么好处之类的。然后下次开会或者适当的时候提出来,改掉这个。二次包装 HTTP 已经存在的东西,不太好。
    RiceMarch
        27
    RiceMarch  
    OP
       Apr 12, 2021 via iPhone
    @young1lin 这个太难了 公司自己已经封装了一套很全的东西。
    liian2019
        28
    liian2019  
       Apr 14, 2021
    Object
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2663 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 71ms · UTC 16:01 · PVG 00:01 · LAX 09:01 · JFK 12:01
    ♥ Do have faith in what you're doing.