Java generics unchecked casts - wildcard framework

I'm trying to get my head around generics, but I block with wildcard constraints and drops. For example:

List<? extends Number> l = new ArrayList<>();
List<PositiveInteger> p = new ArrayList<PositiveInteger>();
p.add(new PositiveInteger(10));
l = p;
NegativeInteger ni = (NegativeInteger) l.get(0);// runtime java.lang.ClassCastException:
System.out.println(ni);

      

NegativeNumber and PositiveNumber increase the number. So the question is, why is there no warning at compile time when casting an item from a list to NegativeNumber? Is there a way to prevent this type of exception?

+3


source to share


3 answers


Ok, the same will happen if you do:

Object a;
Integer b = new Integer(5);
a=b
Double c = (Double)a;

      

ClassCastException occurs because you are trying to convert a class to another class that is not a parent / child class

regarding the question of preventing this:



the compiler doesn't know what will happen at l

runtime. but you can use List<PositiveInteger>

a wildcard instead to tell the compiler what will be in l

. if you need to use List<? extends Number>

, you can create a method that tries to pass an object, this way you can determine if there is an object List<PositiveInteger>

or List<NegativeInteger>

like here :

if(l instanceof List<NegativeInteger>){
   //Do something
}

      

so if I change your code accordingly:

List<? extends Number> l = new ArrayList<>();
List<PositiveInteger> p = new ArrayList<PositiveInteger>();
p.add(new PositiveInteger(10));
l = p;
Object ni = l.get(0);
if(ni instanceof NegativeInteger){
   NegativeInteger tmp = (NegativeInteger)ni;
   System.out.println(ni);
}

      

0


source


When you define a Generic type using type wildcards <? extends Number>

, you should not be throwing objects into Number subclasses, because the generic type says you will get an instance of the subclasses Number

. Like this piece of code:



Number n = new PositiveInteger(10);
NegativeInteger  ni = (NegativeInteger ) n;

      

0


source


Once you do the casting, you tell the compiler "I know what I'm doing", so it won't complain as long as it's possible to create an object (NegativeNumber extends Number -> ok).

If you really need to do the cast (which you want to avoid, generics are all it takes to compile and avoid "unsafe" dumps), you can test it first like this:

Number number =  l.get(0);
if (number instanceof NegativeInteger){
    NegativeInteger ni = (NegativeInteger) l.get(0);
    ...
}

      

0


source







All Articles