Discussions

News: J2SE 1.5 new language features prototype available now!

  1. An early access prototype implementation of new J2SE 1.5 language features is available. In this version of prototype for JSR014, JSR 65 Concise Object-Array Literals (usually referred to varargs) and JSR 201 Extending the Java Programming Language with Enumerations, Autoboxing, Enhanced for loops and Static Import are also supported. In addition, Variance concept for generic types and array types are introduced so that you may program Java codes in a more abstract and integral fashion.

    You can download this exciting implementation from http://developer.java.sun.com/developer/earlyAccess/adding_generics/index.html

    It requires J2SE 1.4.1 or later and provides some examples on how to actually use enum, varargs, foreach style loop, boxing-unboxing, static import, and so on.

    This early access must be bliss for those who can’t wait for Tiger beta which is going to appear in 2003 4th quarter.

    Threaded Messages (51)

  2. Server Error. This have been occuring for a while on java.sun.com. Hopefully gets fixed soon.
  3. Hi All,

    I'm just wondering if you reckon that you'll use the new features. Is it just unneccesary bloat which you won't use. Will it make your life easier, you really relish the thought of these? Let us all know.

    Regards,
    Max
    p.s. I'm looking forward to some of these additions, although I think some are adding things which operate a bit to implicitly(my major gripe when I write C# apps)
  4. Absolutely, auto-boxing, enum, foreach and (drum roll please!) generics are hard to ignore to make things easier.

    Nick
  5. There is no "foreach"!!![ Go to top ]

    There is, nor will be, a "foreach" keyword in Java 1.5

    In C#, where you have

    foreach (SomeClass element in someCollection)

    In Java 1.5 it'll be

    for (SomeClass element : someCollection)

    http://jcp.org/aboutJava/communityprocess/jsr/tiger/enhanced-for.html
  6. No Foreach sucks[ Go to top ]

    Yea... I understand that they did this for backwards compatibility reasons. However I'd rather have a more complete and readable language where I need to make some tweeks to my source than a hack of the short IF form syntax.

    In my mind, I think of the word "hokie". I didn't quite understand the reasoning for this either.
  7. Great[ Go to top ]

    None of this is unneccesary bloat.

    I hope they got it right.
  8. Absolutely.

    We've already converted most of our app to use generics. It's very, very nice.

    Once the other parts are stable (esp the iteration syntax), we'll probably convert into that pretty quickly.
  9. |
    | Is it just unneccesary bloat ?
    |

    Bloat is a bit strong - but are these additions really essential? In particular, are generics really essential?

    For me its going to be one of those things where I will have to wait and see. Java has obviously managed to become pretty much the dominant language without these features. Having said that, its entirely possible that you will find me strongly advocating these features in a few months - I reserve the right to change my mind. ;-)

    My fear is that with these (not insignificant) changes we will compromise what has been the key aspect of Java - its simplicity.

    My opinion is that there exists some measure of the complexity of a language - its something like (the number of API's) to-the-power-of (the number of language constructs).
    IMO the number of language constructs has by far the larger impact on complexity and consequently I think that Java's simplicity has been largely due to the very minimalist approach to language constructs.

    Unlike C++, you get very few interview questions like "What will happen when this piece of Java code runs?" The low number of language features means that there is a very low likelihood of seeing some weird permutation of constructs that you have never seen before.

    I have spent a bit of time looking at C# - and there are many features where you think "thats interesting" or "I can see where that might be useful" however quite a few of them leave me with a feeling of "thats additional complexity for not much win".

    To some extent, I hold the same views on the new additions to Java - esp in the area of Templates. I was never a big fan of templates in C++ - and though I can see why they are useful, I just dont think they are critical. I can, on the other hand, forsee many java newcomers really making a mess of their usage - resulting in code that is really hard to understand (compared to C++, its rather difficult to write java code that someone else cant read).

    I have been doing some internal training recently - teaching some VB/ASP developers Java/Struts (with a fair amount of success, I would like to say). I can say without too much qualification that they would really struggle getting their heads around templates (on top of polymorphism, reflection, interfaces etc, etc). And they will have to get their heads around it. They may not write any code that uses templates initially (though they will end up dabbling) but they will eventually have to read code with templates. It wont be long before OSS developers start using templates and then everyone will have to understand them if they want to look at the source for WebWork or Struts or (insert favourite OSS here).

    I may change my mind completely, but my fear is that, however useful they might be, templates may be "a bridge too far" in keeping Java simple.

    -Nick
  10. I agree with Nick's concenrs. When the initial generics proposal came out I was actually quite satisfied with it's mix between simplicity of syntax/semantics and power of expression. However, it seems that this early access release also contains a further extention: the dreaded generic type covariance. Much have been said on this topic, and I don't want to dwell on the pros and cons. The basic goal, anyway, it to improve expressiveness and type safety at the expense of added complexity. I fear this added complexity may make Java code dealing with generics significantly harder to read. Just take a look at the new Collection interface. It takes several pages of white-paper to explain why some parameters are covariant, some contra-variant, some bivariant, and some invariant. When newcomers can't read and understand something simple like the Collection interface, I think the language may have gotten a little to complex. There are also new covariant array types, and a not-so-obvious interaction between them and the normal array types.

    I'm not sure if covariance is currently on the plan for Tiger. The change log seems to indicate they are considering it.

    By the way, I don't think there is any problem with the covariance proposal (at least as far as I can understand it from the whitepaper/overview). The proposed syntax is also quite natural if you understand the type system. I just think this extension to the type system will be hard to understand for newbies, and they'll have to understand it in order to use things as basic as Collection.

    What's your opinion about this new feature?

    Gal
  11. I don't think this will be a problem for beginners. While it may be difficult for a new programmer to understand the Collections.java code, I don't think many newbies go in and delve into the API code when they're getting started.

    A new programmer will just be able to use the Collections classes without understanding variance. Only a programmer designing a new generic class will have to understand variance and that is only if they want to make their class as flexible as possible.

    I like variance. Perhaps the syntax is a bit ugly and could be improved (an additional keyword or two such as covariant or contravariant may be in order), but overall it is a simple, elegant concept that does add value to the language.
  12. Sebastian,

    If Java ever introduces complete variance support, programmers generally needs to understand it, at least to exploit the full power of it.

    I'm baffeled that variance (especially covariance) isn't part of all modern OO programming languages.
  13. I happen to like the syntax, I think the "+T" and "-T" syntax nicely highlights the range of the type.

    Anyway, the code for the Collection interface is not implementation-level code. It is the actual interface, and what a developer will see (perhaps in an API format) when he wants to work with a Collection. When a developer wants to get an array of items from Collection<T>, he would get an invariant T[=]. Using this in "normal" array context won't work. You can't treat it as Object[] (or any S[] for S super-type of T).
    I don't think it is good for programmers to work with an interface without understanding what the declarations really mean. This can yield compilation errors that take hours to resolve (unless the newbie asks for some expirienced help), and is exactly what C++ templates causes.

    That said, I agree that covariance/contravariance is elegant and adds power to the language. I'm just not sure if newbies will be able to understand what you are saying when you use this expressive language.

    Gal
  14. The whitepapers don't go into the Collection code at all. All they have is interfaces and beginners will have to understant these.

    So they will have to understand that
    Set<+Object> is different from Set<Object> and how. Also, this change does not affect only generics but arrays as well, so you can write now Number[+] to get covariant array, or Object[=], and the [] isn't co/contra/in variant either. So if that doesn't confuse people, I don't know what will.

    Originally I thought that generics were a welcome addition, but now I'm starting to have doubts.
    I don't like the C-like optional arguments at all, as it makes method more ambiguous. I.e.
    class A {
    void blah(Object a, object b);
    void blah(Object[] a);
    }
    blah(1,2) will hopefully call the first blah, not coming up with ambiguous call.
    What happens then when I add blah(Object a, Object b, Object c)? Java doesn't do dynamic binding, co if I pass it into a compiled library that calls blah(1,2,3) I will get still blah(Object[] a) called - w/o failing. If I recompile, it will call the three parameter method though. Yes, it is what you'd expect but if you forget to recompile. So everytime you ship a new library version to your customer they have to recompile.

    I do think that they are adding a lot of unnecessary things. I'd much more appreciated if they came with a less verbose way of creating anonymous inner classes so I could use them as closures more often.

    Regards,
    Vlad
  15. I'm not sure if covariance is currently on the plan for Tiger.

    >The change log seems to indicate they are considering it.

    Well, seems like that they will eventually go into subsequent
    version if not for Tiger. I felt luck that when they release
    1.3 generic was not in, then I felt luck again when 1.4 came out.
    Unfornately, they keep coming back. And, I know such luck doesn't
    last forever.

    The ugly syntax. I agree Jordan Zimmerman that more keywords might
    help. They are too much bound to the C++ template syntax. Using
    different keywords for declaration and application will also
    help. Consider current exception, "throws" as declaration and
    "throw" as application. Maybe they should also consider "type
    alias" or "separate the syntax that narrows a type".

        IntegerCollection parameterize Collection:Integer;
        IntegerCollection ic = new IntegerCollection();

        interface Map exteneds Clonable bounds KeyType, ValueType {
             public put( KeyType key, ValueType value );
        }

    (I am not trying to propose something, so don't be too serious.
     But maybe somebody will throw some better idea because of this?)

    They explains why we need generic type, but never explains why such
    syntax is choosen (because they haven't consider other?)

    Beside, the syntax is ugly, that's quite a few of concepts to
    grab from the generic type. Consider a small language like
    Java (the libaray isn't small), the addition to syntax is
    considered as big.

    Considering the current proposal, it is not what I will
    scaifies simplicity for. A simple language makes everything
    simplier. But, the generic additions only make generics easier.

    I wonder why don't they release a separate module/add-on to
    those people who weight the "expressive" power over the
    "simplicity". (I knew earlier generic type doesn't need
    any JVM change, not sure about the current one). And, leave
    Java the "simplicity" which've made Java so popular in
    the first place.
  16. I knew earlier generic type doesn't need any JVM change, not sure about the current one.


    It doesn't require a JVM change. However this has some unfortunate ramifications. Because the generic class file is formed by erasing all type information from the class, the runtime can't discover this as wrong:
    Collection<String> collection = new Collection<Integer>();

    Of course the compiler catches that. But what about:

    Object[] array = new Collection<String>[1];
    array[0] = new Collection<Integer>();

    This wouldn't get caught at runtime! So what the variance proposal basically does is eliminate "dynamic" (i.e normal) arrays of templates. As a result, you also can't have dynamic arrays of a parameterized type (because it can take a template type). In the previous example you would have to make the array covariant, but then you couldn't write into it.

    So we get backwards compatability, but there is some cost.

    Gal
  17. <snip>
    > Of course the compiler catches that. But what about:
    >
    > Object[] array = new Collection<String>[1];
    > array[0] = new Collection<Integer>();
    >
    > This wouldn't get caught at runtime! So what the variance proposal basically
    > does is eliminate "dynamic" (i.e normal) arrays of templates. As a result, you also can't have dynamic arrays of a parameterized type (because it can take a template type). In the previous example you would have to make the array covariant, but then you couldn't write into it.
    >

    You can have dynamic arrays of a parameterized type (in the prototype atleast) even though you will get a compiler warning:
    "Note: ArrayTest.java uses unchecked or unsafe operations.
    Note: Recompile with -warnunchecked for details."

    This is IMHO good as you will know that something fishy is going on in your code.

    > So we get backwards compatability, but there is some cost.

    I'm probably a little slow here, but could you elaborate on which cost you mean?
    > Gal
  18. You can have dynamic arrays of a parameterized type (in the prototype atleast) even though you will get a compiler warning:

    "Note: ArrayTest.java uses unchecked or unsafe operations.
    Note: Recompile with -warnunchecked for details."

    What causes warning messages instead of compile time errors is unsafe assignment operations from a parameterized array type to a dynamic array. As far as I can read from the whitepaper, the warning status of these unsafe operations was defined to allow smooth integration of old code. Here is a relevant quote:

    <whitepaper>
    ... For compatibility reasons, it is not a compile time error: combinations of old and new code should be allowed. However, if the warning is not the result of integration with old code, programmers should regard it as an error and rearrange their code to avoid it, typically by shifting to statically safe arrays.
    </whitepaper>

    Also, you really can't have dynamic arrays of generics or parameterized type. These do result in compile-time errors, because they cannot be created by integration of old code. Here is the quote:

    <whitepaper>
    For similar reasons, dynamic arrays of generic classes and of type variables
    are not allowed:
    class C<T> {
    T[] ts; // Rejected
    C<Object>[] cs; // Rejected
    }
    Such examples cannot occur as a result of integration with old code, as both
    generic classes and type variables are new features of Generic Java. Hence,
    the declarations cause compile time errors.
    </whitepaper>

    > I'm probably a little slow here, but could you elaborate on which cost you mean?

    The cost is the lack of type-checking on generic types. At runtime, the VM can't tell apart Collection<String> and Collection<Integer>. If I were to put one of them in an Object reference and then cast it to the other, no error would be signalled by the VM. This is certainly less type checking than I would like to have.

    Gal
  19. <whitepaper>

    > For similar reasons, dynamic arrays of generic classes and of type variables
    > are not allowed:
    > class C<T> {
    > T[] ts; // Rejected
    > C<Object>[] cs; // Rejected
    > }
    > Such examples cannot occur as a result of integration with old code, as both
    > generic classes and type variables are new features of Generic Java. Hence,
    > the declarations cause compile time errors.
    > </whitepaper>

    Just to avoid confusion (and in no way counter your point), the following is perfectly legal, however:

    class C<T> {
      T[=] ts;
      C<Object>[=] cs;
    }


    I fully agree that runtime checks in addition to the compile time ones would have been much better and more powerful, ESPECIALLY when serialization/deserialization is involved (e.g. RMI). Unfortunately, doing that would have required major reworking of the VM, the cost of which Sun & friends were obviously not prepared to accept (and I can understand that position).
    I guess some initial gaps in language design are just too hard to plug.
  20. You are perfectly right, of course. But the point was that it's not very easy to work with template libs such as Collections without knowing about X-variance. Newbies, whether they want to write a generic class or just call Collection.toArray would have to know a thing or two about dynamic arrays, covariant arrays, contra-variant arrays and invariant arrays.

    I hope that the generic-type class attribute that is provided in the class file would enable generics-aware VMs to perform real type checking. However, I'm not sure if it wouldn't break the semantic definition of Java code. It's not healthy to have a single line of Java code result in very different behaviours in different VMs (e.g, throw exception in one VM and get ignored in the other). I guess they would address that if and when VMs are able to support this feature.

    Gal
  21. You can have dynamic arrays of a parameterized type (in the prototype atleast) even though you will get a compiler warning:

    > "Note: ArrayTest.java uses unchecked or unsafe operations.
    > Note: Recompile with -warnunchecked for details."
    >
    > What causes warning messages instead of compile time errors is unsafe assignment operations from a parameterized array type to a dynamic array.
    >

    yes. exactly my point such assignment are *unsafe* thus I don't like dynamic arrays of a generic collections (YMMV)

    <snip reason - I read that paper ;)>

    > Also, you really can't have dynamic arrays of generics or parameterized type. These do result in compile-time errors, because they cannot be created by integration of old code. Here is the quote:
    >
     
    Yes, which IMHO is good.

    <snip whitepaper>
    > > I'm probably a little slow here, but could you elaborate on which cost you mean?
    >
    > The cost is the lack of type-checking on generic types. At runtime, the VM can't tell apart Collection<String> and Collection<Integer>.
    >

    True, this will be the next step:
    http://delivery.acm.org/10.1145/290000/286958/p201-cartwright.pdf?key1=286958&key2=0952924501&coll=GUIDE&dl=GUIDE&CFID=10717078&CFTOKEN=16019562
    (NextGen - basically a proxy class - disclaimer: I haven't read the whole paper)

    > If I were to put one of them in an Object reference and then cast it to the other, no error would be signalled by the VM.
    >

    Yes, but this is not only the fault of the generics system is it?
    Consider the same with regular Strings and Integers.

    String text = "kaboom";
    Object ref = text;
    int value = ((Integer) ref).intValue();

    Even though your conceived example will (probably) be fixed by the nextgen proposal.


    > This is certainly less type checking than I would like to have.

    I agree, even though I can't really see a need to cast things to objects all the time when we get generics (if so I would probably consider it a design error).

    > Gal
    /Anders
  22. yes. exactly my point such assignment are *unsafe* thus I don't like dynamic arrays of a generic collections (YMMV)


    Well, the reason it is more unsafe than normal "dynamic" arrays is the lack of runtime information on the parameterized type arguments. Dynamic arrays are generally somewhat unsafe, but we still support them for normal types because they are convinient.

    > Yes, but this is not only the fault of the generics system is it?
    > Consider the same with regular Strings and Integers.

    > String text = "kaboom";
    > Object ref = text;
    > int value = ((Integer) ref).intValue();

    There is no problem with this code. Evaluation of the expression (Integer)ref will (rightfully) throw a ClassCastException, because according to Java's type system a String type is not assignable to an Integer type. This is not the case with Collection<Integer> and Collection<String>. In this case, even though one type is not supposed to be assignable to the other, you can still cast them without error. Up until now you could be sure that a reference of type X really refers to some object whose type is assignable to X. Now you can't. I think this is definately the fault of the generics system. Unfortunately it seems to be hard to fix while maintaining backwards compatability. I hope future VMs will solve this problem.

    > I agree, even though I can't really see a need to cast things to objects all the time when we get generics (if so I would probably consider it a design error).

    When you interface with legacy code you have to use the raw types of generics.

    Gal
  23. yes. exactly my point such assignment are *unsafe* thus I don't like dynamic arrays of a generic collections (YMMV)

    >
    > Well, the reason it is more unsafe than normal "dynamic" arrays is the lack of runtime information on the parameterized type arguments. Dynamic arrays are generally somewhat unsafe, but we still support them for normal types because they are convinient.
    >

    eeh?

    > > Yes, but this is not only the fault of the generics system is it?
    > > Consider the same with regular Strings and Integers.
    >
    > > String text = "kaboom";
    > > Object ref = text;
    > > int value = ((Integer) ref).intValue();
    >
    > There is no problem with this code.
    >

    Well, then add the wrongfully cast object to a collection of some sort (it won't matter as it's the same thing basically), if you want it to show up at a later point of execution.

    > Evaluation of the expression (Integer)ref will (rightfully) throw a ClassCastException,
    >
    yes
    > because according to Java's type system a String type is not assignable to an Integer type.
    >

    ...

    > This is not the case with Collection<Integer> and Collection<String>. In this case, even though one type is not supposed to be assignable to the other, you can still cast them without error.
    >

    No you can't. You must first cast them to a object and then to another type. Adding (wrong type of) objects to this strangely casted collection though is another point.

    > Up until now you could be sure that a reference of type X really refers to some object whose type is assignable to X.>

    Nope. See my previous example.

    > Now you can't. I think this is definately the fault of the generics system.
    >

    No, it's no different than it was before generics - other than now you get compile time errors if you don't try hard to work around it (i.e. like when casting to object and back).


    >Unfortunately it seems to be hard to fix while maintaining backwards compatability. I hope future VMs will solve this problem.
    >

    If you read the link about nextgen I posted in my previous post you will see that there already exists proposals to fix it without breaking backwards compatibility (theory ain't gonna help us though until it's implemented ;).

    > > I agree, even though I can't really see a need to cast things to objects all the time when we get generics (if so I would probably consider it a design error).
    >
    > When you interface with legacy code you have to use the raw types of generics.

    Yes, but then you're already using "unsafe" code (bad word - can't think of a better - maybe "not compile time safe"?).

    > Gal
    /Anders
  24. yes. exactly my point such assignment are *unsafe* thus I don't like dynamic arrays of a generic collections (YMMV)

    > >
    > > Well, the reason it is more unsafe than normal "dynamic" arrays is the lack of runtime information on the parameterized type arguments. Dynamic arrays are generally somewhat unsafe, but we still support them for normal types because they are convinient.
    > >
    >
    > eeh?

    Can you elaborate on what exactly you don't understand?

    >
    > > > Yes, but this is not only the fault of the generics system is it?
    > > > Consider the same with regular Strings and Integers.
    > >
    > > > String text = "kaboom";
    > > > Object ref = text;
    > > > int value = ((Integer) ref).intValue();
    > >
    > > There is no problem with this code.
    > >
    >
    > Well, then add the wrongfully cast object to a collection of some sort (it won't matter as it's the same thing basically), if you want it to show up at a later point of execution.

    This wasn't my point (read the next comment).

    >
    > > Evaluation of the expression (Integer)ref will (rightfully) throw a ClassCastException,
    > >
    > yes
    > > because according to Java's type system a String type is not assignable to an Integer type.
    > >
    >
    > ...
    >
    > > This is not the case with Collection<Integer> and Collection<String>. In this case, even though one type is not supposed to be assignable to the other, you can still cast them without error.
    > >
    >
    > No you can't. You must first cast them to a object and then to another type. Adding (wrong type of) objects to this strangely casted collection though is another point.

    That's what I ment. The point is, no matter how you spin it, that you can have a Collection<Integer> reference pointing to a Collection<String> object.

    >
    > > Up until now you could be sure that a reference of type X really refers to some object whose type is assignable to X.>
    >
    > Nope. See my previous example.

    You didn't give an example that counters this fact, and I'm quite sure you can't. In your example Object ref = text is allright, because String is assignable to Object. Then (Integer)ref throws a ClassCastException. No problem here. The VM can allways verify the type by issuing a cast operation. When generic types are involved, this isn't the case. A Collection<String> reference can, at runtime, point to a Collection<Integer>. Even though Collection<Integer> should not be assignable to Collection<String>. Can you give me an example where this happens (reference value type not assignable to reference type) without generics?

    >
    > > Now you can't. I think this is definately the fault of the generics system.
    > >
    >
    > No, it's no different than it was before generics - other than now you get compile time errors if you don't try hard to work around it (i.e. like when casting to object and back).

    It's different as I described in my previous comment.

    >
    >
    > >Unfortunately it seems to be hard to fix while maintaining backwards compatability. I hope future VMs will solve this problem.
    > >
    >
    > If you read the link about nextgen I posted in my previous post you will see that there already exists proposals to fix it without breaking backwards compatibility (theory ain't gonna help us though until it's implemented ;).

    Unfortunately I don't have a registration and it seems to require it... do you happen to know of some free source where I can get that article?

    >
    > > > I agree, even though I can't really see a need to cast things to objects all the time when we get generics (if so I would probably consider it a design error).
    > >
    > > When you interface with legacy code you have to use the raw types of generics.
    >
    > Yes, but then you're already using "unsafe" code (bad word - can't think of a better - maybe "not compile time safe"?).

    I think you are missing my point. The point is not whether you should or shouldn't get to this situation. In C you shouldn't get to a situation where you have a struct A pointer pointing to struct B, but you can. In Java, before generics, you couldn't. All casts were verified at runtime. Now they're not, and there can be situations where you have a pointer of one type pointing at a value of another (not assignable) type. That's all I'm saying.

    Gal
  25. yes. exactly my point such assignment are *unsafe* thus I don't like dynamic arrays of a generic collections (YMMV)

    > > >
    > > > Well, the reason it is more unsafe than normal "dynamic" arrays is the lack of runtime information on the parameterized type arguments. Dynamic arrays are generally somewhat unsafe, but we still support them for normal types because they are convinient.
    > > >
    > >
    > > eeh?
    >
    > Can you elaborate on what exactly you don't understand?

    Hehe, here I am again - trying to explain my thought on this ;)

    "Dynamic arrays are generally somewhat unsafe, ..."
    I guess I'm not convinced that it really matter *when* you get a classcast exception - it's still a programmer error and thus IMHO doesn't really matter that much where it happens as it is still an error (you could argue that it's easier to find a bug if you get an early class cast exception, but see below how "easy" - haven't thought that long on it, could be some errors in the implementation - it is with generics to get such an exception).
    <snip>
    > That's what I ment. The point is, no matter how you spin it, that you can have a Collection<Integer> reference pointing to a Collection<String> object.
    >

    sure.
     
    > > > Up until now you could be sure that a reference of type X really refers to some object whose type is assignable to X.>
    > >
    > > Nope. See my previous example.
    >
    > You didn't give an example that counters this fact,
    >

    ok, I plee bad explanation of my example ;)

    > and I'm quite sure you can't. In your example Object ref = text is allright, because String is assignable to Object. Then (Integer)ref throws a ClassCastException. No problem here. The VM can allways verify the type by issuing a cast operation. When generic types are involved, this isn't the case. A Collection<String> reference can, at runtime, point to a Collection<Integer>. Even though Collection<Integer> should not be assignable to Collection<String>. Can you give me an example where this happens (reference value type not assignable to reference type) without generics?
    >

    See above why I don't think this is a good example as I believe it's an error to even get to the situation where you can have a typed generic list pointing to another different type of list (this involves casting to object and back - and I consider that unsafe programming).

    <snip>
    > > No, it's no different than it was before generics - other than now you get compile time errors if you don't try hard to work around it (i.e. like when casting to object and back).
    >
    > It's different as I described in my previous comment.

    If you want an "early" classcast exception (when you add wrong type) instead of when you try to get wrong type, you can subclass for example an ArrayList<E> to also take a class argument and use isAssignableFrom in all add operations.
    This will not help when you cast a List<String> => Object => List<Integer> - but it will tell you where you add the wrong type to a collection (and IMO that is good enough until nextgen fixes the hole).

    <snip>

    > > > > I agree, even though I can't really see a need to cast things to objects all the time when we get generics (if so I would probably consider it a design error).
    > > >
    > > > When you interface with legacy code you have to use the raw types of generics.
    > >
    > > Yes, but then you're already using "unsafe" code (bad word - can't think of a better - maybe "not compile time safe"?).
    >
    > I think you are missing my point. The point is not whether you should or shouldn't get to this situation.
    >

    Well, that was kind of my point ;D
     
    > In C you shouldn't get to a situation where you have a struct A pointer pointing to struct B, but you can. In Java, before generics, you couldn't. All casts were verified at runtime. Now they're not, and there can be situations where you have a pointer of one type pointing at a value of another (not assignable) type. That's all I'm saying.
    >

    Ok, then we sort of agrees, I don't consider this to be a good case against generics as I find this situation to be a desing error anyway (and you will most probably get a class cast exception eventually anyway), but I see your point about this can make uncareful programmers confused.

    Let's hope that nextgen fixes this in 1.5.* :)

    > Gal
    /Anders
  26. Anders,

    I guess we actually agree. My case wasn't against generics in general. I just mentioned that the backward compatability support was gained at a certain price. I didn't say that price is too heavy to pay, just that it exists. I agree that you generally shouldn't get to the point where it matters. And even if you do, unlike C, you can't get data corruption. All the basic types are still runtime-checked. The problem is more theoretical, about Java's type system, than practical.

    I haven't read all the NextGen spec paper yet but it seems compatible with the current VMs. It does have a somewhat bigger footprint, but that shouldn't matter so much I think...

    Gal
  27. On Generics, I think that something that meets the need is definitely needed. I've seen big apps without it, and it then becomes a nightmare to figure out what the x342HashMap contains without debugging or a lot of walking around.

    I don't mind open object collections in the same class, but our solution was to create strong-typed String, Int, and Bool List and Maps collection classes to solve our problem. We used things like StringList that only accepts/returns strings. Also with some other more specific object collections, we went ahead and created strong-typed lists for those as well, which worked out very nicely because many of them needed extra processing to handle the object containment appropriately.

    So while I think Generics (or strong-typed collections in my book) are good, I have a couple of issues with it so far:
    - It might be better to build strong-typed classes instead. After all, understanding the details of StringHashMap are negligible when you understand HashMap. So who cares if you have a wad of a new classes.
    - I find the whole "List<String> list = new ArrayList<String>()" syntax bizarre. It really looks more like a hack to me, just to be honest. The point here is that it seems far less readable that say "StringList list = new StringList()" or something else more constructive.

    Now that I think about it, it bothers me for a couple of reasons:
    - The syntax order is backwards as compared to variable and method definitions. Am I the only one that things "<String>List list = new <String>ArrayList()" makes more sense? Or maybe "(String)List list = new (String)ArrayList()"? Or maybe... oh, never mind.
    - Also this looks like your applying a class type to a class type with the "List<String>" syntax.

    On the positive side, I am very, very glad to see SUN taking great strides to improve the language rapidly. Now if we can just get them to put in a file copy, directory move, or string join command. :)

    Anyway, I've griped long enough. These are just my creative thoughts... anyone?
  28. The syntax order is backwards as compared to variable and method definitions. Am I the only one that things "<String>List list = new <String>ArrayList()" makes more sense? Or maybe "(String)List list = new (String)ArrayList()"? Or maybe... oh, never mind.


    I guess that depends on where you are coming from. Generic types treat other types as parameters. Like a function takes a list of parameters after it's name, generics take a list of type parameters after their name. Anyway I'm sure once you get used to it it would seem natural.

    > On the positive side, I am very, very glad to see SUN taking great strides to improve the language rapidly.

    Heh, improve the language rapidly... :) The generics JSR was approved around 4 years ago. Research papers on GJ (Generic Java, the system on which the current proposal is based) has appeared even before that, on OOPSLA 98. So much for rapid improvement.

    Gal
  29. The NextGen paper[ Go to top ]

    FYI, I found a version of the NextGen paper which is available without subscription at CiteSeer.

    Gal
  30. Initially I was on the side of "Java's a wonderfully simple language and has worked for pretty much everyone so far so why change it?" but I'm starting to move towards "great, something new", "something to get my teeth into", "at last something that will let the *real* Java programmer shine above the rest".

    The last point made me think though, do we really want to start having wonderful "modern" code with generics and boxing and varargs all over the place? Won't this mean that the code will start to become like most C++ I've seen (written and worked on too), virtually unmaintainable except by the most advanced programmer.

    Perhaps, it's good news for us consultants, we can start to lock ourselves into contracts by writing complex code, readable by only the top programmers. There is the arguement that it's actually more readable in some cases, we'll see.

    Either way, it's progress and evolution. I played with the last version of generics a good year ago and I'm looking forward to playing with this one. I will use it, it's my job as a consultant. Let's embrace it and get on with writing some .NOT killing code!

    The JCP.ORG logo is going to have to change!!!

    import static java.lang.System.*;

    char[] result={60,74,111,104,110,47,62};
    for(char c : result)
    {out.print(c);}
  31. I think templates are an awful solution. Evolution of OOP languages are in the way of untyped variables, so you don't need cast them.
    Templates only resolve the sentence:
      AClass a = (AClass) aIterator.next();

    A serious change for a minimal problem.
    Thats my opinion anyway
  32. I'm just wondering if you reckon that you'll use the new features. Is it just unneccesary bloat which you won't use. Will it make your life easier, you really relish the thought of these? Let us all know.


    generics for sure, been waiting for this in java for so long.

    boxing, the new foreach construct are useless to me

    /T
  33. Variable arugment lists?[ Go to top ]

    I didn't realize that they were including variable argument lists. This was always an eyesore in C. At least it's cleaner in this version (autoboxing into an array). But, still - I think Java can live without this one.
  34. Variable arugment lists?[ Go to top ]

    They don't implement variable argument lists like C/C++/C#. They implement it as a shortcut for an Object array (see http://www.jcp.org/en/jsr/detail?id=65 )

    Suppose you have: int i; double x; String s;
    Then:
        { i, x, s }
    would be expanded into:
        new Object[] { new Integer(i), new Double(x), s }

    So that instead of writing:

    f.fmt("%d bytes in %d seconds (%.2f KB/s)\n",
              new Object[] { new Integer(nbytes),
                             new Integer(seconds),
                             new Double((double)(nbytes / 1024)
                                        / (double)seconds)});

    you could now write:

    f.fmt("%d bytes in %d seconds (%.2f KB/s)\n", { nbytes, seconds, (double)(nbytes/1024)/(double)seconds } );

    It's definitely a lot cleaner, explicit, backwards compatible, and general purpose than the C/C++/C# vararg approach.
  35. Variable arugment lists?[ Go to top ]

    Robert,

    That's what I thought too, but it's not what the early access version contains. Take a look at this code from one of the examples:

    <code>
    // varargs
        public static void printf(String fmt, Object[] args...) {
    int i = 0;
    // foreach on primitive array
    for (char c : fmt.toCharArray()) {
    if (c == '%')
    System.out.print(args[i++]);
    else
    System.out.print(c);
    }
        }

    ...

        printf("Addition: % plus % equals %\n", 1, 1, 2);
    ...
    </code>

    Seems like they added some sort of C-like syntax for varargs. However you still have typing and access the arguments through an array, so it's not quite as bad. Just syntactic sugar.

    Gal
  36. Variable arugment lists?[ Go to top ]

    Suppose you have: int i; double x; String s;

    > Then:
    >     { i, x, s }
    > would be expanded into:
    >     new Object[] { new Integer(i), new Double(x), s }
    >
    > So that instead of writing:
    >
    > f.fmt("%d bytes in %d seconds (%.2f KB/s)\n",
    >           new Object[] { new Integer(nbytes),
    >                          new Integer(seconds),
    >                          new Double((double)(nbytes / 1024)
    >                                     / (double)seconds)});

    Your example shows how you can implement
    variable arguments feature using "{ i, x, s }" feature.

    But you can also implement "{ i, x, s }" as "arr(i, x, s)" where
    arr is variable arguments, statically imported method:

    public static Object[] arr(Object[] args...) {
        return args;
    }

    So, "{ i, x, s }" is not more general then variable arguments.

    Moreover, I can say that variable arguments are more general because arr method may return List or String [], but "{ i, x, s }" is always Object [].

    Nebojsa
  37. Why not new keywords[ Go to top ]

    I wish language creators weren't so averse to adding new keywords. C++ went out of its way not to introduce new keywords so we got stuck with the many meanings of virtual, the bizarre parsing issues with templates ( a<b>> vs a<b> >), etc.

    Now, the Java folks have adopted C++ syntax for templates and this new strange use of '+', '-', '*'. Add a keyword please!
  38. Couple of observations

    - 20 years ago; how difficult it was to accept ideas of OOP looking at code like
    public class Foo extends Bar implements List, Serializable{…
    I can imagine discussions similar to this one about "beginners will have to understand these".

    - It’s obvious that introduction of generics in Java creates a lot of various problem for language syntax and implementation. It’s interesting how Microsoft is going to do it for .Net. Will they invent something new or just slightly modify Java syntax again…
  39. Don't worry about MS[ Go to top ]

    Microsoft learned much from C++ and Eiffel, much more than Sun did. In .NET 1.1, MS made a significant modification to the framework, so that C# can have a comprehensive generic mechanism. If you are interested in this, you can read this article:

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vbconCProgrammingLanguageFutureFeatures.asp

    Though can't match the flexibility of C++'s generic programming, C#-with-generics is more meaningful than Java 1.5.
  40. Don't worry about MS[ Go to top ]

    I agree Jeff,

    And Sun is in a shitty situation because they cannot easily change the VM (thus breaking millions of installations.) Changing the VM is required to get a really good genericity mechanism (such as reflection on generic classes.)
  41. I agree[ Go to top ]

    Microsoft was in very different situation in C# creation time, they started design from begining and they learned a lot from already established products. Sun's java is older language than C# and diffs. are obvious and as Han said it's not easy (possible) to do fundamental architectural changes and do redesign from scratch only because some nice features.
  42. Don't worry about MS[ Go to top ]

    It is interesting that you should mention Eiffel and type traits at the same time. Type traits are the generics' equivalent of overloading, of which the Eiffel creator (considered to be a major OO guru) says that it is a feature that he simply fails to understand -- it brings along a lot of potential problems, and provides absolutely no benefits. Please go read more on the web about this if interested.

    And I am sure it is easy to see the difference between the 'recompile' approach used by C++ and parametric polymorphism by interface -- one is simply a glorified macro, the other is clearly defined and hence much more maintainable. Interestingly, C# uses precisely generics by interface, rather than the free style practiced by C++. I wonder why.

    In fact, the only thing in which the C# proposal is more comprehensive is that it carries runtime information, while the Java stuff is runtime only. This is important, yes, but it should not be overstated. The generics variance mechanism now proposed in Java is a major step forward, not available in the C# proposal. I think I can safely say that it now makes the Java stuff more powerful (and I am saying this even though I have always considered runtime info important).

    Please stop shooting randomly in the dark.
  43. Don't worry about MS[ Go to top ]

    Jeff wrote:

    C#-with-generics is more meaningful than Java 1.5.

    I don't think so. C# has the exact same subtype polymorphism generics mechanism as Java. Java Generics also supports runtime reflection. With variance, Java Generics are more powerful.

    God bless,
    -Toby Reyelts
  44. C# and DOTNET has problems too[ Go to top ]

    C# is also missing the ability to create anonymous inner classes. It just isn't supported. Go figure. Also MS has problems with the VS Studio debugger. Never a perfect world I guess.

    What I would like to know, and maybe I missed it, is how does the compiler know what can be generic? Is it always an child object of collection?
  45. Everything can be generic[ Go to top ]

    Compiler will erase all type arguments into Objects. So you should only take care of the duplication problem(i.e. you can't place two element have same signature).

    I studied the whitepaper about variance, it's something interesting. For example, if you write:

    <T> T choose(T t1, T t2);
    Set<Integer> is;
    List<String> sl;

    You will get T as a Collection<*>. Yepp, variance mechanism is useful, but still a little awful. If Java can strictly distinguish the "getter" methods and the "modifier" methods (just like Eiffel), we'll needn't to take care about variance.
  46. Following is my code:

    public class Happy<T>
    {
    private T subject = new T();

    public <T> void beHappy()
    {
    subject.beHappy();
    }

    public static void main(String[] args)
    {
    Happy<Dog> o1 = new Happy<Dog>();
    o1.beHappy();

    Happy<Cat> o2 = new Happy<Cat>();
    o2.beHappy();
    }
    }

    In C++, compiler should check whether class Dog(or Cat) has a default constructor and a method named beHappy. But in Generic-Java, it just tell me that there isn't a method named beHappy in class java.lang.Object -- oh, it treat all template arguments as an instance of Object. Dos it mean that template can only be used to write containers?

    Furthermore, the sentence "private T subject = new T();" can't compile. Who can tell me, how to store an instance of template argument in a generic class? Who can tell me, how to write some *really* generic program, but not only containers?
  47. Jeff,

    Java generics are more type-safe than C++ templates and less macro-like. If you want to treat type T assuming it supports some interface, you need to state that explicitly:
    public class Happy<T implements MyInterface>

    As for creating a new instance, I don't know any way to do it (but I've only taken a shallow look at the generics spec so far so maybe I'm missing something). You can't be sure that a type would have a no-arg constructor (or even that the type is instanciable, maybe it is an interface). Maybe you can do something using reflection (I don't see a way, but maybe).

    A workaround would be to define an interface:
    public interface Factory<T> {
       T newInstance()
    }

    And take this factory as a parameter as well.

    Gal
  48. You are right[ Go to top ]

    In C++, if type T don't support default ctor or any method which be called in the generic method, it will be a compile-time error. But because of the implementation of GJ, maybe I shouldn't expect that Java compiler will do that for me.

    Of course I can explicitly declare that T implements some interface. However, if I do so, template will only be a type-safety mechanism.

    And more, GJ neither support template explicitly specialization. For example, following code won't compile:

    class NumTraits<T>
    {
    public void doSomething()
    {
    System.out.println("General Traits");
    }
    }

    class NumTraits<T extends Number>
    {
    public void doSomething()
    {
    System.out.println("Traits for Integer");
    }
    }

    So I can't implement type-traits in GJ. Then, why call it "Generic Java"? Without compile-time binding, without type-traits (partial specialization? let's just forget it...), also without policy-based programming, maybe the correct name should be "Java with some type-safety containers".
  49. [i]Java generics are more type-safe than C++ templates and less macro-like.[/i]

    I call BS. Explain even one way in which Java Generics are more type safe than C++ templates. I can tell you how Java Generics are unsafe and can cause errors at runtime, though.

    As far as "macro-like" is concerned, Java Generics use subtype polymorphism to implement generics, and the lack of power shows. C++ templates use structural conformance and the expressiveness shows. Unfortunately, you can only achieve parts of what you can with C++ templates by resorting to runtime reflection and all that that implies.

    God bless,
    -Toby Reyelts
  50. Toby> Explain even one way in which Java Generics are more type safe than C++ templates. I can tell you how Java Generics are unsafe and can cause errors at runtime, though.

    Honestly, I would just go back to understanding the policy based software design concepts about templates based metaprogramming and worry less about C++, GJ and C# when it comes to generics (templates). I feel once you internalize the policy based meta-programming paradigm, you understand why "Modern C++ design" developer like Andrei Alexandrescu mandates it! We developers owe it to him, I think folks who create generics support in their languages should learn from him, in this post-GoF era. If I don't know what policy based class design is, I would not call myself a generics/templates designer anyway! At that level, honestly languages don't matter, policy based software design is the key!

    regards,
    /Ravi
  51. What a C++ fun you are[ Go to top ]

    Just like me, hehe.

    But, policy-based design, type-traits, type-list, metaprogramming(archived by template)...these "modern C++ designs" will shock our colleague. Yesterday I showed a Java program with template and enhanced for loop to my manager, he was extremely shocked.

    From my perspective, policy-based design and some other "modern designs" are hopeful to join the Java community. Maybe AOP will be the key. There's a message in TSS said that someone has implemented 17 GoF patterns in AOP's style. This is Java's "modern design" way.
  52. In trying to keep our apps independent of the exact type of the numerical data in the database we end up converting everythyng to BigDecimals or BigIntegers with casts and method invocations. Can you imagine the length of the code you have to write when you just want to do "a=(b+c*20/d)*0.80"?

    Why are there still no plans for operator overloading? :-(