【问题标题】:Dynamically cast to each array type动态转换为每个数组类型
【发布时间】:2019-04-21 16:49:43
【问题描述】:

在任何可能的情况下,我都使用以下方法打印所有捆绑内容。问题是 PMD 同时报告了NcssCountCyclomaticComplexity。我想改进代码以消除警告,而不仅仅是压制它们。

private static String bundleToString(Bundle bundle) {
    StringBuilder out = new StringBuilder("Bundle[");

    if (bundle == null) {
        out.append("null");
    } else {
        boolean first = true;
        for (String key : bundle.keySet()) {
            if (!first) {
                out.append(", ");
            }

            out.append(key).append('=');

            Object value = bundle.get(key);

            if (value instanceof int[]) {
                out.append(Arrays.toString((int[]) value));
            } else if (value instanceof byte[]) {
                out.append(Arrays.toString((byte[]) value));
            } else if (value instanceof boolean[]) {
                out.append(Arrays.toString((boolean[]) value));
            } else if (value instanceof short[]) {
                out.append(Arrays.toString((short[]) value));
            } else if (value instanceof long[]) {
                out.append(Arrays.toString((long[]) value));
            } else if (value instanceof float[]) {
                out.append(Arrays.toString((float[]) value));
            } else if (value instanceof double[]) {
                out.append(Arrays.toString((double[]) value));
            } else if (value instanceof String[]) {
                out.append(Arrays.toString((String[]) value));
            } else if (value instanceof CharSequence[]) {
                out.append(Arrays.toString((CharSequence[]) value));
            } else if (value instanceof Parcelable[]) {
                out.append(Arrays.toString((Parcelable[]) value));
            } else if (value instanceof Bundle) {
                out.append(bundleToString((Bundle) value));
            } else {
                out.append(value);
            }

            first = false;
        }
    }

    out.append(']');
    return out.toString();
}

我尝试使用以下逻辑将代码分成两部分,但 NcssCountCyclomaticComplexity 只是移动到执行所有数组转换的新方法。

if (value != null && value.getClass().isArray()) {
   // the new method to call all the array casts
   newMethodThatSuffersFromTheSameProblem(out, value);
} else if (value instanceof Bundle) {
    out.append(bundleToString((Bundle) value));
} else {
    out.append(value);
}

我能以某种方式对每个数组类型进行动态转换吗?

if (value != null && value.getClass().isArray()) {
   out.append(Arrays.toString((<cast-to-class-array-[]>) value));
}

我也尝试过out.append(Arrays.toString(value.getClass().cast(value)));,但出现编译错误Cannot resolve method 'toString(capture&lt;? extends java.lang.Object&gt;)'

【问题讨论】:

    标签: java casting refactoring pmd static-code-analysis


    【解决方案1】:
    } else if (value instanceof String[]) {
      out.append(Arrays.toString((String[]) value));
    } else if (value instanceof CharSequence[]) {
      out.append(Arrays.toString((CharSequence[]) value));
    } else if (value instanceof Parcelable[]) {
      out.append(Arrays.toString((Parcelable[]) value));
    

    这 3 个ifs 可以替换为一个

    } else if (value != null && value.getClass().isArray())
      out.append(Arrays.toString((Object[]) value));
    

    对于其余部分,您可以使用静态 Map&lt;Class, Function&lt;Object, String&gt;&gt; convertors 并将其预填充为

    convertors.put(int[].class, value -> Arrays.toString((int [])value));
    ...
    

    然后使用

    Function<Object, String> convertor = convertors.get(value.getClass());
    if (convertor != null) {
      out.append(convertor.apply(value));
    } else ...
    

    适用于无法使用 Lambda 的旧安卓

    interface ToString { String convert(Object object); }
    ...
    static Map<Class, ToString> convertors = new HashMap();
    convertors.put(int[].class, new ToString() { public String convert(Object value) { return Arrays.toString((int [])value); }}); 
    ...
    

    然后使用

    ToString convertor = convertors.get(value.getClass());
    if (convertor != null) {
      out.append(convertor.convert(value));
    } else ...
    

    【讨论】:

    • 虽然该解决方案看起来清晰而漂亮convert.apply(value) 需要 Android API 24 及更高版本:(
    • 我对安卓不熟悉。它是否错过了 lambdas 或只是 Function 接口?两者都有解决方法,但如果它没有 lambda,那么您将不得不编写更多样板代码。
    • Function 接口是它只能从 Android 7.0 (Nougat, API 24) 获得的问题,我目前的目标是 4.4 (KitKat)。 developer.android.com/reference/java/util/function/Function
    • 所以你只需要定义你自己的函数接口interface Function&lt;T,R&gt; { R apply(T input); }
    • 我更新了答案以提供没有 lambda 和 Function 接口的映射
    【解决方案2】:

    我现在不能测试,但是有什么问题

    if (value == null) {
       // do whatever you want;
    } else if (value instanceof Bundle) {
       out.append(bundleToString((Bundle) value));
    } else if (value.getClass().isArray()) {
       out.append(Arrays.toString((Object[]) value));
    } else {
       out.append(value);
    }
    

    BTW 1:NCSS 和相关参数是提示。如果你有 20 个不同的案例,你有。虽然您总是应该考虑太大的数字,但有时@SuppressWarning 是正确的解决方案。

    顺便说一句 2:制作静态 bundleToString(Bundle) 而不是覆盖 Bundle.toString() 的原因是什么?

    【讨论】:

    • Bundle 是 Android 框架中的一个类...即使您能够扩展它并进行覆盖,在这种情况下系统将返回它自己的类。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多