SF/JavaOne, Day 3, JavaGenericsWhaaaa?!


I’m at the Java Collections talk and they’re bringing up the issue of
type safety with generics in java 1.5.  The speaker just told me
somethign that sent a shiver up my spine.  Let’s say you compiled
the following code in java1.4:



class Old {

    static void addIntegerToList(List list) {

        list.Add(new Integer(42));

    }

}



then in java1.5 you write and compile the following code:



class New {

    static void Foo() {

        List<String> strings = new ArrayList<String>();

        Old.addIntegerToList(strings);

        Srting firstString = strings.getAt(0);

    }

}



Then the above code compiles fine without a single warning!  Ack!



Double-ack!



Ack*Ack*Ack!



The compiler will make you think that everything is typesafe and you
won’t know that anything is wrong with your type system until it blows
up at runtime.



Comments (7)

  1. Uwe says:

    So does this apply to .NET 2, too?

  2. CyrusN says:

    Uwe: No, it does not. C# will not let this compile at all. This is a consequence of the fact that in java generics are forgotten (or "erased") so the compiler can’t tell if your original code was:

    class Old {

    ….static void addIntegerToList(List list) {

    ……..//stuff

    ….}

    }

    or if it was

    class Old {

    ….static void addIntegerToList(List<String> list) {

    ……..//stuff

    ….}

    }

    the compiled form for both is identical. So it can only presume that things were performed in a typesafe manner. Which, of course, might be totally wrong.

    In C#/.Net this generic information is not lost. It is preserved in metadata so you can’t ever have this kind of problem occurring.

  3. DrPizza says:

    Uh, duh. This is why I’ve pointed out in numerous places that Java doesn’t have real generics….

  4. Nat says:

    It just provides a way you can screw up like before with weakly-typed collection. So nothing new 😀

  5. When I see code like List<string>, I fully expect that the compiler will enforce that at COMPILE time.

    If not, why the hell even have that? As a coding convention?

    I get along fine with things like:

    //Only contains string

    List strings;

    The example that cyrus gives has about as much help from the compiler, and a lot of bad things, since the developer would expect strong typing.

  6. DrPizza says:

    Any developer expecting strong typing from Java’s generics is pretty incompetent, as they’re evidently using something they don’t understand.

    Sun has made no secret of the fact that Java’s generics are all fake–just syntactic shorthand with no runtime manifestation. Developers should not be the least bit surprised about the crappy behaviour.

  7. Plamen Jeliazov says:

    Hello,

    I just tried to compile the snippet you post here and the compiler reported 3 errors:

    <code>

    [kwark@kwark test]$ javac GenericsBugTest.java

    GenericsBugTest.java:19: cannot find symbol

    symbol : method Add(java.lang.Integer)

    location: interface java.util.List

    list.Add(new Integer(42));

    ^

    GenericsBugTest.java:27: cannot find symbol

    symbol : class Srting

    location: class New

    Srting firstString = strings.getAt(0);

    ^

    GenericsBugTest.java:27: cannot find symbol

    symbol : method getAt(int)

    location: interface java.util.List<java.lang.String>

    Srting firstString = strings.getAt(0);

    ^

    3 errors

    [kwark@kwark test]$

    </code>

    here is the code I tried to compile:

    <code>

    import java.util.ArrayList;

    import java.util.List;

    public class GenericsBugTest {

    public GenericsBugTest() {

    super();

    }

    public static void main(String[] args) {

    // TODO Auto-generated method stub

    }

    }

    class Old {

    static void addIntegerToList(List list) {

    list.Add(new Integer(42));

    }

    }

    class New {

    static void Foo() {

    List<String> strings = new ArrayList<String>();

    Old.addIntegerToList(strings);

    Srting firstString = strings.getAt(0);

    }

    }

    </code>

    The compiller I used is:

    <code>

    [kwark@kwark test]$ java -version

    java version "1.5.0_04"

    Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_04-b05)

    Java HotSpot(TM) Client VM (build 1.5.0_04-b05, mixed mode, sharing)

    </code>

    Operating system:

    <code>

    [kwark@kwark test]$ uname -a

    Linux kwark.info 2.6.11-1.1369_FC4 #1 Thu Jun 2 22:55:56 EDT 2005 i686 athlon i386 GNU/Linux

    </code>

    Are you really occurred this error or this is a new version of MS’s "Get the facts!" …

    No further comments.

    Plamen

    no further comments …