Shevek (shevek) wrote,
Shevek
shevek



I haven't actually proofread this, so I hope it makes sense after the braindump.

I've been experimenting with Java 1.5 Generics, and I have come
to the conclusion that they are a pain in the arse due to their
incompleteness, in the pure mathematical sense.
In fact, the use of Java 1.5 Generics frequently prevents me
from doing things I could do in 1.4, which are mathematically
and theoretically legal, and which work in C++/STL.


Consider the following examples:

    void add(Class<? extends Foo> clazz) {
        ...
    }

    void add(String name) throws Exception {
        add(Class.forName(name));
    }


As far as I can see, there is no way to make that code compile, even
though the Generics information included is entirely correct. But
if the Generics information is removed, then it compiles. (See C++
and dynamic_cast<> for a traditional solution to this problem.) In
this case, erasure does prevent us from doing:

    public static <T> Class<? extends T> forName(String name) { 
        ...
        if (T.class.isSubclass(ret))
            throw;
        return ret;
    }



Aside: Consider something ANDF-like for a solution to this problem,
although I'm sure Java would be capable of marking up type-parameters
as implicit runtime parameters where required, thus transforming

<T> foo() { ... }


into

foo(Class) { ... } 



Some of my issues are to do with cases where I am forced to capture
a <?> (impossible). As yet, I'm also slightly confused as to the
difference between (say) <? extends X> and <X>, or, for that matter,
<?> and <Object>. It's not like we can get any further information
from the knowledge that we are a _strict_ subclass, as opposed to
simply being of type X. Consider again C++. Consider the possiblity
of:

    Class<X> c = Class.forName<X>(name);


where we have explicitly specified the capture, which I don't
otherwise seem to be able to get my hands on. Naturally, this syntax
is disallowed, which leads me on to my next point: type inference in
this particular syntax.

Other peculiarities include the ability to say:

    Set<Long> s = Collections.emptySet();


Note how type inference is at work to template the method
emptySet<Long>(), the template for which _cannot_ be explicitly
specified. But you cannot say:

    void foo(Set<Long> s) { }
    void bar() { foo(Collections.emptySet()); }


You must say:

    void foo(Set<Long> s) { }
    void bar() { Set<Long> s = Collections.emptySet(); foo(s); }


All of these issues annoy me because the use of Generics
has actually detracted from what I was able to do before.

Note also that the problems I have posted above are not explicitly
caused by type erasure. These cases are compilable.

The only reason I'm using Generics at all is because they permit me to
do some rapid prototyping tricks, e.g. change the type of a Collection
element and have the compiler tell me about all the sources of that
Collection at compile-time, and to write simple functors, collators,
lambda-like expressions and so on slghtly more elegantly.





Bayard, if you're reading this, can you get the bcel people to get
their arses in gear so jrat works again? P.S. have you tried feeding
"a,b,\n" into gj-csv? You ought to get 3 fields, and you get 2. Mail
me for CsvResultSet.java.
Subscribe
  • Post a new comment

    Error

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 7 comments