【问题标题】:Java handling method with changing return type具有更改返回类型的 Java 处理方法
【发布时间】:2021-07-15 10:36:45
【问题描述】:

我有一个方法,其中返回类型可以是几种已知类型。
它可以返回List<String>List<List<String>>
调用它的时候,我根据我传递的参数知道返回类型是什么。
为了清楚起见,方法是

public List<Object> getValueFromResponseBodyHook(Response res, String key){
    return res.body().jsonPath().getList(key);
}

我试着这样处理:

public boolean validateParameterValueInResponseBodyHook(Response res, String param, String expectedValue, Boolean flat){
    List<List<String>> complex;
    List<String> flat;
    if(flat){
        flat = (List<String>) getValueFromResponseBodyHook(res,param);
    }else {
        complex = (List<List<String>>) getValueFromResponseBodyHook(res,param);
    }
}

但是这给我带来了以下错误:

不可转换的类型;无法将 'java.util.List' 转换为 'java.util.List'

对于这一行

flat = (List<String>) getValueFromResponseBodyHook(res,param);

不可转换的类型;无法将 'java.util.List' 转换为 'java.util.List>'

对于这一行

complex = (List<List<String>>) getValueFromResponseBodyHook(res,param);

我该如何正确处理这种情况?

【问题讨论】:

    标签: java casting


    【解决方案1】:

    不要用一种方法来做到这一点。你违反了类型安全。您应该创建两种方法,一种返回List&lt;String&gt;,另一种返回List&lt;List&lt;String&gt;&gt;。像这样的:

    public List<String> getValueFromResponseBodyHookFlat(Response res, String key){
        return res.body().jsonPath().getList(key);
    }
    
    public List<List<String>> getValueFromResponseBodyHookComplex(Response res, String key){
        return res.body().jsonPath().getList(key);
    }
    

    然后在你的 if-test 中调用适当的方法:

    public boolean validateParameterValueInResponseBodyHook(Response res, String param, String expectedValue, Boolean flat){
        List<List<String>> complex = null;
        List<String> flat = null;
        if (flat) {
            flat = getValueFromResponseBodyHookFlat(res, param);
        } else {
            complex = getValueFromResponseBodyHookComplex(res, param);
        }
        ...
    }
    

    【讨论】:

    • 但这不是重载!这两种方法名称不同。这是我目前拥有并希望使用单一方法的。
    • 正确,错误地使用了术语“过载”。无论如何,这更干净,因为它避免了未经检查的强制转换和违反类型安全。您不能拥有仅在返回类型上有所不同的(实际)重载。
    • 好的,因为根据我接受您的回答的所有意见,您的方法更好。也照着执行。
    【解决方案2】:

    一个选项是关键字instanceOf

    public boolean validateParameterValueInResponseBodyHook(
       Response res, String param, String expectedValue, Boolean flat){
        List<List<String>> complex;
        List<String> flat;
        List<Object> result = getValueFromResponseBodyHook(res,param);
        for (Object listEntry : result)
        {
           if (listEntry instanceOf String) {
             flat = (List<String>) listEntry;
           } else if (listEntry instanceOf List) {
             complex = (List<List<String>>) listEntry;
           }
        
           //What ever you want do to with it
           //...
         }
    }
    

    注意:您可以使用这种方式与instanceof 一起检查complex 中的列表条目是否为字符串。不过,@mastran 建议的方式要好一些。希望它能引导你走向正确的方向。

    【讨论】:

    • 你不必投 listEntryresult
    • 由于根据所有意见,matran 的方法更好,所以我接受了他的回答。无论如何,非常感谢您的回答,您教会了我一些不错的想法,谢谢!
    【解决方案3】:

    有几种方法可以解决这个问题。 起初,最干净的方法是如marstran提到的编写两个方法。 无论如何:

    1. 您可以将返回类型更改为List&lt;? extends Object&gt;。 现在强制转换语句不会导致编译错误。

    2. 您可以通过将结果保存在非泛型列表中来“擦除”泛型:

    List<List<String>> complex;
    List<String> flat;
    List tmp = getValueFromResponseBodyHook(res,param);
    if (flat){
        flat = (List<String>) tmp;
    } else {
        complex = (List<List<String>>) tmp;
    }
    
    1. 您可以为您的方法使用动态泛型。 请注意,编译时没有类型安全。
    public <T> List<T> getValueFromResponseBodyHook(Response res, String key){
        // maybe need to cast here
        // only works if return type of getList allow cast to List<T> (I don't know the API)
        return res.body().jsonPath().getList(key);
    }
    

    【讨论】:

    • 由于根据所有意见,matran 的方法更好,我接受了他的回答。无论如何,非常感谢您的回答,您教会了我几个不错的想法,谢谢!
    猜你喜欢
    • 2012-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 2011-11-09
    相关资源
    最近更新 更多