Add Y to Collection<X>, and Y not instanceof X. Why is no runtime exception thrown?

huangapple go评论75阅读模式
英文:

Add Y to Collection<X>, and Y not instanceof X. Why is no runtime exception thrown?

问题

以下是翻译好的内容:

以下方法可将 任何内容 添加到 任何 集合中。为什么不会抛出运行时异常?

public static <T> void addAnything(Collection<? super T> c, Object t) {
    c.add((T) t);
}

例如,

List<String> list = new ArrayList<>();
addAnything(list, "ok");
addAnything(list, 2);
addAnything(list, true);
addAnything(list, new Object())
addAnything(list, new Anything())

为什么在这段代码中不会抛出任何异常?

英文:

The following method add anything to any collection. Why is no runtime exception thrown?

public static &lt;T&gt; void addAnything(Collection&lt;? super T&gt; c, Object t) {
    c.add((T) t);
}

For example,

List&lt;String&gt; list = new ArrayList&lt;&gt;();
addAnything(list, &quot;ok&quot;);
addAnything(list, 2);
addAnything(list, true);
addAnything(list, new Object())
addAnything(list, new Anything())

Why is there not any exception thrown in this piece of code?

答案1

得分: 1

两个原因:向后兼容性和性能。

为了与旧的、不安全的代码保持向后兼容,Java中的泛型是通过“类型擦除”来实现的。类型系统仅在编译时强制执行。当你使用类型转换时,你告诉编译器“没问题,我知道我在做什么”,然后你只会得到一个警告。

在运行时添加对象时检查对象的类型会导致性能退化。目前,ArrayList.add 不需要知道要添加的对象的任何信息:它只使用对象的引用 进行操作。这意味着不需要从主内存加载对象本身的任何内容到CPU寄存器或缓存中。如果必须检查对象的类型,缓存失效 的数量会显著增加,从而减慢程序的运行速度。

如果你想要一个只允许添加字符串的列表,你可以使用 Collections.checkedList 方法:

List<String> list = Collections.checkedList(new ArrayList<>(), String.class);
addAnything(list, 2); // 运行时错误
英文:

Two reasons: backwards compatibility and performance.

For backwards compatibility with old, unsafe code, generics in Java is implemented with "type erasure." The type system is enforced at compile time only. When you use a type cast you're telling the compiler "this is fine I know what I'm doing" and you merely get a warning.

Checking the types of the objects when they are added at run time would be a performance regression. Currently, ArrayList.add does not need to know anything about the object being added: it only works with the object reference. This means nothing about the object itself needs to be loaded from main memory into CPU registers or cache. If the type of the object had to be checked, the number of
cache misses would increase dramatically, which slows the program down.

If you want a list that makes sure only Strings are added, you can use the Collections.checkedList method:

List&lt;String&gt; list = Collections.checkedList(new ArrayList&lt;&gt;(), String.class);
addAnything(list, 2); // run time error

答案2

得分: 0

因为所写的方法旨在将 Object 类型的实例添加到任何 T 的超类型的列表中(正如您肯定知道的,对于任何 T,Object 都是 T 的超类型)。因此,该方法将您的 List<String> 视为 List<Object> 并向其中添加 Object 的实例。这显然是有效的行为。但是,如果您向列表中添加了非 String 对象并尝试对其内容进行操作,您将会看到异常。

英文:

Because the method as written is designed to add an instance of type Object to a list of anything that's a supertype of T (and as you surely know, for any T, Object is a supertype of T). So the method is treating your List&lt;String&gt; as a List&lt;Object&gt; and adding instances of Object to it. Which obviously is valid behaviour. You'll see the exceptions if you added non-String objects to the list and try to do something with its contents though.

答案3

得分: 0

因为type erasure,在运行时不会抛出任何异常。基本上,您的ArrayList&lt;String&gt;会被编译成一个非泛型的ArrayList,这意味着您可以向其中添加任何对象。

英文:

There is no exception thrown ay runtime because of type erasure. Basically your ArrayList&lt;String&gt; is compiled just like a non-generic ArrayList, which means you can add any objects to it.

答案4

得分: 0

> „<strike>为什么在添加过程中没有ClassCastException?</strike>&hellip;在这段代码中为什么没有抛出任何异常?&hellip;

因为泛型在编译时进行检查

你的代码就像这个经典示例中的代码。就像其中所说:“尽管代码在没有错误的情况下被编译,它会抛出运行时异常java.lang.ClassCastException &hellip;“

英文:

> „<strike>Why is there no ClassCastException in the adding process?</strike>&hellip;Why is there not any exception thrown in this piece of code?&hellip;

Because generics are checked at compile-time.

Your code is like the code in this classic example. And like it says there: „Although the code is compiled without error, it throws a runtime exception (java.lang.ClassCastException)&hellip;“

huangapple
  • 本文由 发表于 2020年8月22日 17:54:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/63534854.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定