V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
RiceMarch
V2EX  ›  Java

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

  •  
  •   RiceMarch · 238 天前 · 2482 次点击
    这是一个创建于 238 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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 条回复    2021-04-14 18:23:10 +08:00
    yuanmomo
        1
    yuanmomo  
       238 天前 via iPhone
    没记错的话,我应该用的是问号
    xarthur
        2
    xarthur  
       238 天前 via iPhone
    不要用 null 不就行了……
    用 Optional 。
    我以为 null-safety 已经是个常识了(
    xarthur
        3
    xarthur  
       238 天前 via iPhone
    另外完全没看懂你的例子(
    RiceMarch
        4
    RiceMarch  
    OP
       238 天前
    @xarthur 可能我表达的不太好 hhhh,就是 BaseResponse 基础返回类中的 data 在一些情况下是没有值的,只有 code 和 message 有值,在确定 data 是没有值的情况下,我还想要在写 controller 方法的时候指定泛型类型,该怎么指定。
    zhazi
        5
    zhazi  
       238 天前 via Android
    Void
    lwq84510
        6
    lwq84510  
       238 天前 via iPhone
    一楼是答案
    aguesuka
        7
    aguesuka  
       238 天前 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  
       238 天前
    上面说了 问号,或者不理会编译器提醒 不加泛型也没问题。
    passerbytiny
        9
    passerbytiny  
       238 天前 via Android
    你需要构造的是:BaseResponse<Object>,在哪。任何类型可以承载 null,在你只需要它是 null 而不关心具体类型的时候,最高基类 Object 是一个勉强的选择。
    passerbytiny
        10
    passerbytiny  
       238 天前 via Android
    如果你这里的泛型,并不是给类似 Swagger 这样的自动生成 API 文档的工具用的,那么它是画蛇添足的东西,因为 Cortroller 方法是非框架代码中的最外层——除了框架不会有人从它那里获取返回值。

    这里去掉泛型,直接将 data 定义成 Object 类型,会更好。
    AoEiuV020
        11
    AoEiuV020  
       238 天前
    我一般用 String,
    xuanbg
        12
    xuanbg  
       238 天前
    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  
       238 天前
    当然,你要用 swgger 这些自动化文档的话,返回的时候空也不影响啊。为啥要 new BaseResponse ? return this 就行了呀。

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

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