【问题标题】:Weird Java's typesafety not working for collections [duplicate]奇怪的 Java 类型安全不适用于集合 [重复]
【发布时间】:2021-02-19 05:38:26
【问题描述】:
  public static <T> List<T> toArray(JSONArray array) {
        if(array == null) {
            return Collections.emptyList();
        }

        List<T> o = new ArrayList<>();

        for(int i=0, l = array.length(); i < l; i++) {
            o.add((T) array.get(i));
        }

        return o;
    }

    public static void test() {
        List<Object> values = new ArrayList<>();
        values.add("Product");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("key", values);
        List<Long> test = new ArrayList<>();
        test = toArray((JSONArray) jsonObject.get("key"));
        System.out.println(test);
    }

上面的代码允许将String 值存储在List&lt;Long&gt; 中,这完全是荒谬的。任何帮助非常感谢?

【问题讨论】:

  • 你明白为什么它会警告你未经检查的演员表吗?
  • 如果您的代码(和所有库)在没有任何类型安全警告的情况下编译,泛型将提供类型安全。您的 (T) 演员表未选中,这意味着:编译器会假装您知道自己在做什么,但实际上并未验证对象是否为 T 类型。
  • @kannanrbk:那你没仔细看。您的代码不会在没有警告的情况下编译。
  • 除非您禁用了警告,否则您将从此代码中收到警告。
  • 不幸的是,一些 IDE 附带了错误的编译器警告默认值。

标签: java java-8


【解决方案1】:

这一行:

o.add((T) array.get(i));

将生成未经检查的强制转换警告。

未经检查的强制转换是编译器无法插入checkcast 字节码指令来检查它是否真的是您要强制转换的类型的实例的强制转换。它不能在这里这样做,因为它不知道T“是”什么。

您只是在做一些不安全的事情。除非你取消了警告,否则你会收到警告(这不是一个好主意,因为你不会被告知做不安全的事情)。

这正是 Java 的工作方式。


您可以通过传入Function&lt;Object, T&gt;(或更一般地,Function&lt;Object, ? extends T&gt;)作为参数来安全地执行此操作:

public static <T> List<T> toArray(JSONArray array, Function<Object, ? extends T> checker) {
  // ...
  o.add(checker.apply(array.get(i)));
  // ...
}

现在,确保它是T 的责任委托给checker:您可以这样调用此方法:

test = toArray((JSONArray) jsonObject.get("key"), Long.class::cast);

如果元素不是Long,这将失败。

【讨论】:

    猜你喜欢
    • 2022-11-15
    • 1970-01-01
    • 2021-05-09
    • 2016-05-06
    • 1970-01-01
    • 1970-01-01
    • 2023-02-23
    • 1970-01-01
    相关资源
    最近更新 更多