[java] generics problem

Started by
15 comments, last by Michael Nischt 17 years, 9 months ago
you coud try the following:

    static void print(List<? extends Object> list) {        for(Object o : list)            System.out.print(o + " ");    }        static List<Integer> asList(int... values) {        final int[] _values = values;                return new java.utial.AbstractList<Integer>() {            public Integer get(int index) {                return _values[index];            }            public int size() {                return _values.length;            }        };    }            public static void main(String... args) {        // primitive type int array        int [] array = { 0, 1, 2, 3};                print(asList(array));        // wrapper class integer array        Integer [] array2 = { 4, 5, 6, 7};        print(java.util.Arrays.asList(array2));            }

Advertisement
Quote:Original post by Aldacron
Quote:Original post by Kevinator
Interesting find. Do you think that was intentional?


I'm sure it was, but I can only guess as to why. I'm sure it has to do with the fact that arrays are objects themselves. Conceptually, you can think of an array of ints as a type of IntArray, and array of Integers as a type of IntegerArray. All arrays expose the public methods of Object, implement the Cloneable interface, and have a public final field called length. I imagine that this adds some amount of complexity to auto-boxing from a primitive aray to an Object array, and likely would involve too much overhead to do behind the scenes.
actually, if you look closely at the generics implementation, I'm sure it *wasn't* intentional, just an instance of very, very bad design on behalf of Sun. The generics system is incredibly flaky.and extremely easy to screw up. This is somewhat of a contrived example, but the fact that it is possible and not caught at compile time is extremely disconcerting:

ArrayList<String> a = new ArrayList<String> ();Object b = a;ArrayList c = (ArrayList) b;c.add (new Integer (23));        //<-- no bombSystem.out.println (a.get (0));  //<-- BOMB!


[Formerly "capn_midnight". See some of my projects. Find me on twitter tumblr G+ Github.]

Quote:actually, if you look closely at the generics implementation, I'm sure it *wasn't* intentional, just an instance of very, very bad design on behalf of Sun. The generics system is incredibly flaky.and extremely easy to screw up. This is somewhat of a contrived example, but the fact that it is possible and not caught at compile time is extremely disconcerting:

ArrayList<String> a = new ArrayList<String> ();Object b = a;ArrayList c = (ArrayList) b;c.add (new Integer (23));        //<-- no bombSystem.out.println (a.get (0));  //<-- BOMB!


This behavior is intentional to ensure for backward compatibility for both, using >= Java 1.5 libs with Java <= 1.4 and using Java <= 1.4 libs with Java >= 1.5.

If you had watched you compiler output, you would have reading the following note:

Note: XXX.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

The details are:
XXX.java:line: warning: [unchecked] unchecked call to add(E) as a member of the raw type java.util.ArrayList
which is exaclty your bomb, the 'add' method not the 'get' one!
Quote:
actually, if you look closely at the generics implementation, I'm sure it *wasn't* intentional, just an instance of very, very bad design on behalf of Sun. The generics system is incredibly flaky


Err.. considering that generics is 100% backwards-compatible it's pretty far from incredibly flaky. In fact it's very well designed.

What would you have done differently, without breaking things?

Quote:
and extremely easy to screw up.

Funny, I've used generics nearly everyday for since it was introduced and not once have I screwed it up.

And what you are doing in your example is just plain stupid, not to mention the fact that you ignored the compiler warnings completely.
Quote:Original post by Anonymous Poster
Quote:
actually, if you look closely at the generics implementation, I'm sure it *wasn't* intentional, just an instance of very, very bad design on behalf of Sun. The generics system is incredibly flaky


Err.. considering that generics is 100% backwards-compatible it's pretty far from incredibly flaky. In fact it's very well designed.

What would you have done differently, without breaking things?


Personally, I would've defined a separate set of generic containers, and let the existing ones unmodified. Then, when using generics, I would have made the compiler supply the type paramater(s) as a hidden data member(s), so that some additional runtime checking is possible (using assertions, so that you could turn it on and off, if speed would matter). This would also make the creation of arrays of type T possible, etc.
Quote:Original post by SamLowry
Quote:Original post by Anonymous Poster
Quote:
actually, if you look closely at the generics implementation, I'm sure it *wasn't* intentional, just an instance of very, very bad design on behalf of Sun. The generics system is incredibly flaky


Err.. considering that generics is 100% backwards-compatible it's pretty far from incredibly flaky. In fact it's very well designed.

What would you have done differently, without breaking things?


Personally, I would've defined a separate set of generic containers, and let the existing ones unmodified. Then, when using generics, I would have made the compiler supply the type paramater(s) as a hidden data member(s), so that some additional runtime checking is possible (using assertions, so that you could turn it on and off, if speed would matter). This would also make the creation of arrays of type T possible, etc.

Yes, and considering that 1.5 apps rarely run on a 1.4 VM flawlessly, I would have scrapped any plans to keep it backwards-compatible.

[Formerly "capn_midnight". See some of my projects. Find me on twitter tumblr G+ Github.]

Quote:Original post by capn_midnight
Quote:Original post by SamLowry
Personally, I would've defined a separate set of generic containers, and let the existing ones unmodified. Then, when using generics, I would have made the compiler supply the type paramater(s) as a hidden data member(s), so that some additional runtime checking is possible (using assertions, so that you could turn it on and off, if speed would matter). This would also make the creation of arrays of type T possible, etc.

Yes, and considering that 1.5 apps rarely run on a 1.4 VM flawlessly, I would have scrapped any plans to keep it backwards-compatible.


Personally, I'm very happy that there are *not* two versions of container casses like in .Net 2.0, however this is more a matter of taste..
but regardings the backward compatibility it really works 100% if developers are doing things right. For example using Foo<T extends Object & OtherType> instead of Foo<T extends OtherType> and so on..

Anyway, this is how Java has been changed and you have t live with it => your arguments in the previous post still don't count, as the compiler warns you not being type safe..

This topic is closed to new replies.

Advertisement