简体   繁体   中英

Generics Java Wildcards and Subtyping

I am reading on Generics in Java atm, and things go a little slow would love some help. I read from Oracles own database:

https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html

At the bottom we can see List<Integer> is a subtype of List<? extends Number> List<? extends Number>

I also came across this stackoverflow question:

Java Generic type : difference between List <? extends Number> and List <T extends Number>

Which says in one answer: this is true:

((List<Integer>)list).add((int) s);

I have verified it, so that's ok. But I don't understand It completely.

What if the Wildcard is the Short class and I add a number higher than 2^15-1(=32767) Shouldn't it give error?

I even tried something like this and it works fine:

import java.util.*;
class CastingWildcard{
    public static void main(String[] args){
        List<? extends Number> list = new ArrayList<Short>();
        int s=32770;
        ((List<Integer>)list).add((int) s);
        System.out.println(list.get(0));
    }
}

To sum up: Why Can I cast List<? extends Number> List<? extends Number> to List<Integer> when the wildcard could be Short, and even Byte, which also extends Number?

You can cast an object to anything you want, but it might fail at runtime. However since generics information isn't present during runtime, your code becomes essentially ((List)list).add(s); . At that point list will take any object, not just a Number . Generics can help you avoid casts and keep type safety during compile time, but during runtime they don't matter anymore.

The cast makes the compiler ignore the fact, that the types may not be assignable.

At runtime the type parameters are unimportant, see type erasure .

The ArrayList internally stores the content in a Object[] array, which means you can add any reference type to the list object, if you "abuse" casting.

You may get a exception when you retrieve a Object though, since there's a cast hidden in the get statement.

Example:

List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
List<String> list2 = (List) list;
list2.add("Hello World");

Integer i = list.get(0); // works
String s = list2.get(3); // works
s = list2.get(1); // ClassCastException
i = list.get(3); // ClassCastException

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM