Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting generics list in Java

I found a weird situation when casting generics. I run this code:

class A { }

class B { }

public class Program {

    @SuppressWarnings("unchecked")
    public static void main(String[] args) {
        List<A> listA = new ArrayList<A>();
        List<?> list = listA;
        ((List<B>)list).add(new B());

        for (Object item : listA) {
            System.out.println(item.toString());
        }
    }
}

It compiles very well (only with warning but without error) and run without any exception and the output was:

B@88140ed

How did I do that? I mean why Java allow me to do such thing? I added an instance of B class to list of As?

It is very bad behaviour of generics. Why it is happening?

BTW, I tried it with Java 7.

EDIT:
What surprised me is that Java only notify the problem with warning that every programmer can ignore it. I know that SuppressWarnings is bad idea, but why Java didn't denied such behavior with error or exception?

In addition, this warning showed always, if you think that your casting is correct you have no choice but to ignore it. But if you think that is good casting and ignore it but it isn't?

like image 224
nrofis Avatar asked Jun 01 '15 08:06

nrofis


1 Answers

Every programming language allows you to shoot yourself into the foot.

In this case, Java is in a dilemma: It could keep the generics information in the bytecode and break millions of lines of existing code or silently drop the generics information after the compiler has do it's utmost to check and keep backward compatibility.

The Java team decided for the latter and introduced Type Erasure - which has its flaws. But if they had broken millions of perfectly fine (if type-wise incomplete) lines of Java code, people would have shown up with pitchforks and burning torches ...

like image 173
Aaron Digulla Avatar answered Sep 29 '22 11:09

Aaron Digulla