Discussions

News: Tech Talk with Joshua Bloch on New Java Language Constructs

  1. TheServerSide recently interviewed Joshua Bloch, author of the Collections framework, java.math, the book Effective Java, etc. Joshua discusses new Java language features scheduled for the Java 1.5 'Tiger' release including Typesafe Enums, autoboxing, static imports, and generics. He also talks about the various people, groups and institutions that are driving the Java language forward.

    Watch Joshua Bloch's Interview.

    Threaded Messages (124)

  2. so many cool new things... :-)

    When the Tiger is scheduled to hit the streets ?

    he said all things but this one.
  3. I am not sure whether the "static import" is very good.

    I hope it will not turn Java programms into something like C++ with "global functions" without classes. I am sick of those every time I see C++.
  4. static import of methods?[ Go to top ]

    A static import of constants I suppose might not be a bad thing though if it was my choice I would do without it.

    Static import of methods - VERY BAD IDEA. So would it not be the case that calls to these methods will look like a call to the local class when in fact they are a call to some distant class? Thats like a global function.

    Currently, a call to a static method reads well becuase we know which class it belongs to. This helps the readability of the code. I don't know why they want to diminish the readability of the code by changing it. The classname prefix may be cumbersome but at the end of the day it is for the greater good.
  5. static import of methods?[ Go to top ]

    Agreed. I don't like even the constants import - if you want a local access to them, use an interface to declare them and implement it. I think it's cleaner to do it that way as it makes it more explicit and is no harder (in terms of how much effort is required from a developer). And it doesn't introduce new things into language.
    For similar reason, I would prefer a different implementation of the foreach. I would prefer to extend the Collection interface (or introduce a new one, which both Array and Collection would implement - which 1.5 does anyway, but it's just a tag) so that it would take a functor object which could execute something on every item in the collection. In previous versions, this wouldn't work with arrays, but with autoboxing it would be easy. The argument against this could be that it's slightly more work than foreach, but I would argue that it might actually be a good thing as it would force people to think more about what they do in their loops (and separate it cleanly out). I've seen too many for loops nested 3+ leves with various breaks and continues inside, and I suspect that making iteration easier will mean I will see even more of them.
    Still, at least all the boilerplate in good code can disappear now :).
    Not to mention I'm slightly split on 1.5 also because it will mean I will have to change a lot my code inspector :).
    Regards,
    Vlad
  6. If you have ever created a Java class with a main function, you have used this. The ignorance of some Java developers still surprises me.
  7. Dear Evans,
    Please quote the original message.
    R u ignorant abt what u r trying to say?
    Not being able to say anything important on some topic doesnt mean that blabbering would be noticed too.
  8. What's the point for static import?[ Go to top ]

    Current mechanism for using constants in source code requires a little more keystrokes, but certainly it is a clearer and better way to using them. I don't want to use something like "Object Browser" in VB for me to locate just a single Constant.

    Another side effect is that creating a constant automatically by Eclipse when the symbol cannot be resolved cannot work anymore :-)
  9. Waon.. I can't wait to play with Tiger!
    This will be a major improvement for the language, which hasn't really improved since the 1st release.
    Too bad Josuah didn't talk about Metadata feature, which is to my point of view the most exciting feature!
    Kudos for Sun!
  10. waht about gilad?[ Go to top ]

    Not saying ANYTHING about Gilad Bracha was really a shame
  11. Mea Culpa[ Go to top ]

    Yep, you're right. I'm sorry. Gilad Is co-leading JSR-201 (enums, foreach, autoboxing, static import) and leading JSR-14 (generics). He also maintains the Java Language Specification. He is enormously influential in ensuring the quality and integerity of all the language changes.

    Several others at Sun also deserve mention (in addition to Neal Gafter and James Gosling, whom I did mention in the interview): Graham Hamilton, Tim Lindholm, Guy Steele, and Jim Waldo all played a big part in the early work surrounding the language JSRs.

              Regards,

              Josh
  12. Restraint appreciated.[ Go to top ]

    When I first came across C++, it was a really small but useful extension to C. Sure it didn't have many features, but it simple, easy to understand, and a vast improvement over regular C. Then it very legitimately added multiple inheritance (although it went overboard by adding multiple implementation inheritance), and it legitimately added exceptions, and it legitimately replaced the I/O library, and added templates, run-time type identification, and the STL. Even though each individual change was important and legitimate, the sum total of those changes turned C++ into the PL/1-like monster that it is now.

    I'm glad that Java has a lot more restraint in adding language extensions. Java learned early the thing C programmers known for years: a limitted language with a great library is much better than a power language with a small library.

    A great number of language extensions can be implemented through standard libraries. For example, come people have been asking for the C# using() statement to be added:
          using (Resource valueableResource1 = GDIObjectThatMustBeReleasedAsSoonAsPossible()) {
              // use resource valueableResource1
              using (Resource valueableResource2 = GDIObjectThatMustBeReleasedAsSoonAsPossible()) {
                 // use resource valueableResource2 and valueableResource1
              }
              // use resource valueableResource1
          }
          // the "Destroy()" method is called on valueableResource1 to ensure it's freed.
          // the "Destroy()" method is called on valueableResource2 to ensure it's freed.


    It's possible to make a convincing case that sometimes you need to manage resources that tightly in many systems, this sort of resource scarcity and that the Java alternative is very messy (you need two nested try/finally blocks) so it's more error-prone.

    Fortunately, there's a clean alternative: resource pools. The above code could be rewritten in Java as:
        try {
          Collection resourcePool = new List();
          // use resource valueableResource1
          ValuableResource valuableResource1, valuableResource2;
          resourcePool.add(valuableResource1=new ValuableResource());
          resourcePool.add(valuableResource2=new GDIObjectThatMustBeReleasedAsSoonAsPossible());
          // use resource valueableResource2 and valueableResource1
        }
        finally {
          // ensure that Destroy() method is called on each resource
          ResourceManager.releaseResources(resourcePool);
        }

    Yes, it's a bit less eager to reclaim resources, and it's a bit longer, but it's more flexible. For instance, it can manage an array of resources while the using() clause can't. Adding the using() clause would only add complexity to the language.

    A case can be made, however, that
    * since different resources use different names of their "Destroy()" method (some use "close()", some use "free()", some use "destroy()", "deallocate()", and some use "cleanup())
    * and each resource manager can only handle one type of resource
    that it would benefit Java if the "Destroy()" and "resourceManager" classes were put in the standard library. Much the same reason was used when bool/true/false were added to C++ (i.e. to avoid having BOOLEAN/TRUE/FALSE mixed with boolean/true/false with int/0/1, etc in the same program).

    This addition would make resource managers less error prone (since you have to worry about matching the resource type with the resource manager) and you could make standard types like files and socket (if done correctly). It would also allow the compiler to check to ensure that you're not using the resource after it's freed (in much the same way that some compilers warn if there are statements after an "java.lang.System.exit()" call). Essentially, all that would be required is that java.lang.Runtime.callFinalize(Collection resourcePool) be added to the library. When called, it would call the finalize() method of all objects in the collection.
  13. Shouldn't resourcePool be outside the try..finally?

        ResourcePool resources = new ResourcePool();
        try {
            InputStream stream = ...
            resources.add(stream);

            File file = ...
            resources.add(file);
        } finally {
            resources.release();
        }

    See also: http://www.research.att.com/~bs/bs_faq2.html#finally.
  14. Java is going down the C# path... Up until now Java had simplicity going
    for it, this will be lost with tiger and I will probably be forced to
    upgrade to a language I don't even like anymore. While some of you may
    say that I don't have to use these features, the libraries and API's
    will start using them and thus force me to use them as well:

    1. ENUM's are the absolute worst. They make my blood boil and every
    programmer I see using them (in C++ as well) is fired on the spot.
    Programmers who try to use ENUM "alternatives" such as small classes
    or interger constants will never get promoted and need serious help
    in understanding object oriented design. No OO language needs ENUM's.

    2. Generics are just plain wrong, and even worse in the way they
    are implemented. Did you know that it is still possible to get a
    ClassCastException (or equivalent) when using generics in Java?
    Generics is simply a different syntax for writing a cast, I think
    programmers should be aware of what the language/VM is doing.

    3. Autoboxing again is here to cut down on typing... As if typing
    is a complicated part of the programming process. Its not as if
    the VM is "really" changed, you end up writing one thing (adding
    an int to a collection) which comes out as another thing alltogether.
    This is one of the main problems and debugging pitfalls in C++
    (anyone who ran a large enough real world C++ project knows this),
    C++ "thinks" it knows what you want. This allows you to repeatedly
    shoot yourself in the foot, due to a mistake made by a novice who
    didn't understand the complexities of the language. No amount
    of coding conventions or filtering of programmers can protect you
    within a large team from the complications of the language.

    4. Why add static imports is beyond me. It seems as if someone
    in this horrible JSR team is using a really bad text editor and
    wants to save a few keystrokes. Why not turn Java into a functional
    language and get it over with.


    Every SINGLE one of these features offers NO benefit whatsoever
    to the language neither in performance nor in readability or
    maintainance (every benefit gained in readability is offset
    by the fact that your reading something that isn't realated
    to whats really happening).

    Languages should be complex in the API level and not in the
    lanugage level. The API doesn't have wide sweeping effects on
    the quality of the whole project.

    I only wish that there was a way to vote against RFE's in the
    sun bug parade.
  15. RE: these are BAD ideas[ Go to top ]

    Yeah I don't find these enum/staticimport/etc stuff intersting at all. They are not much important at all imho. I just want two things in JDK 1.5:

    - blocks, like Ruby
    - runtime attributes, like C#

    JSR 175 adds runtime attributes, but I don't know if blocks are in the agenda at all. Maybe part of the other jsr for adding foreach/etc? I hope foreach is implemented as a block. A richer runtime api would also be great ("give me all classes that implement Persistable and have @hibernate attribute").

    Sun seems so conservative to add a interception mechanism to the language. CGLIB, aspectworks, nanning, blabla. We need a clean and standard way of doing it. We need a clean mechanism for adding/removing interceptors to classes when they are new-ed.

    Ara.
  16. Java is going down the C# path...

    What is wrong with borrowing good things from C# ? At the end, C# borrowed much more from Java.

    > 1. ENUM's are the absolute worst. They make my blood boil and every
    > programmer I see using them (in C++ as well) is fired on the spot.
    > Programmers who try to use ENUM "alternatives" such as small classes
    > or interger constants will never get promoted and need serious help
    > in understanding object oriented design. No OO language needs ENUM's.

    And what about thousands of enum-like integer constants in Java libraries ? How would you replace them or how would you redesing public interfaces of these Java libraries to avoid them ?

    > 2. Generics are just plain wrong, and even worse in the way they
    > are implemented. Did you know that it is still possible to get a
    > ClassCastException (or equivalent) when using generics in Java?
    >Generics is simply a different syntax for writing a cast, I think
    > programmers should be aware of what the language/VM is doing.

    And how would you implement generics (the so wanted feature by many, many Java programmers) into Java language by not breaking byte code compatibility with older VMs ? Do you have better idea ?

    > 3. Autoboxing again is here to cut down on typing...
    > 4. Why add static imports is beyond me.
    > Every SINGLE one of these features offers NO benefit whatsoever
    > to the language neither in performance nor in readability or
    > maintainance (every benefit gained in readability is offset
    > by the fact that your reading something that isn't realated
    > to whats really happening).

    Saying that this changes do not improve readibility of Java language is at least not objective.

    Regards,
    Mileta
  17. Java is going down the C# path...

    > What is wrong with borrowing good things from C# ? At the end, C# borrowed
    >much more from Java.

    I didn't say stealing from C# was wrong. I said we are making the same mistakes.
    IMO C# is bloated and unreadable, just as bad as C++ only newer.
     
    > > 1. ENUM's are the absolute worst. They make my blood boil and every
    > > programmer I see using them (in C++ as well) is fired on the spot.
    > > Programmers who try to use ENUM "alternatives" such as small classes
    > > or interger constants will never get promoted and need serious help
    > > in understanding object oriented design. No OO language needs ENUM's.
    >
    > And what about thousands of enum-like integer constants in Java libraries ?
    >How would you replace them or how would you redesing public interfaces of these
    >Java libraries to avoid them ?

    The people who wrote these API's did a bad job IMO.
    However I have to use Calendar, JOptionPane etc...
    I am not the only one who thinks Calendar should be rewriten since it is
    particularly bad, but I don't say it about every use of ENUM like structures.
    I think that we should use what works to a reasonable extent.
    I don't think we should supply another tool strictly because people choose to
    write none object oriented code. Might as well add support for functions
    and goto.

    > > 2. Generics are just plain wrong, and even worse in the way they
    > > are implemented. Did you know that it is still possible to get a
    > > ClassCastException (or equivalent) when using generics in Java?
    > >Generics is simply a different syntax for writing a cast, I think
    > > programmers should be aware of what the language/VM is doing.
    >
    > And how would you implement generics (the so wanted feature by many, many Java
    >programmers) into Java language by not breaking byte code compatibility with
    >older VMs ? Do you have better idea ?

    Yes. Don't.
    I don't think generics are needed in dynamic languages. While templates are
    useful generics are here simply to avoid a cast because all of us of the
    former C++ crowd were tought that a cast is bad (because RTTI didn't exist
    and when it did it was excensive).
    Please read my other postings as to why generics don't solve much, and I
    definetly object to adding generics without a usability study that PROVES that
    they are useful.

    Other than that I share an opinion with some pro generic folk that simply say
    that there should be a shift. There should be a new language based on the
    Java ideas (call it JavaNG) that has very similar API's, but no deprecated
    methods, no AWT, cleaner IO and immutable date. In this language you can
    implement generics from scratch without compatability issues. Since the
    languages would be very similar the source code for the VM can be unified and
    probably some of the libraries.

    Why is everyone in such a hurry to patch Java badly, we're doing fine without
    generics for the past 6/7 years....
     
    > > 3. Autoboxing again is here to cut down on typing...
    > > 4. Why add static imports is beyond me.
    > > Every SINGLE one of these features offers NO benefit whatsoever
    > > to the language neither in performance nor in readability or
    > > maintainance (every benefit gained in readability is offset
    > > by the fact that your reading something that isn't realated
    > > to whats really happening).
    >
    > Saying that this changes do not improve readibility of Java language is at
    >least not objective.

    I never claimed to be objective, I am a manager/developer/consultant that has
    to deal with these things every day.
    The problem with static imports is that they make the benefit of encapsulation
    harder to leverage:

    When I see a block of code that contains:

    methodName();

    and I want to understand this methodName(). All I have to do is Ctrl-F and look
    through the file. If the method isn't there its in one of the base classes.
    With static imports I need to start digging in more classes (don't think people
    won't statically import everything). One of the main problems we had in C++
    was when someone defined in some header a small macro with a generic name
    such as find(). Try to search through a million lines of code for a global
    function with that name. Everything is simple until its scaled up to really
    large projects where it becomes unmanageable.
  18. I don't think we should supply another tool

    > strictly because people choose to write
    > none object oriented code. Might as well
    > add support for functions and goto.

    Ironically, staeless session ejbeans (the only ones to use i am told) look a lot like non-object-oriented functions to me, even though they are herded in groups. Come on, I had structures (value objects) and methods to pass them into (EJB services) in plain C twenty years ago, and RPC instead of SOAP. Aren't be busying ourselves not knowing on what to spend CPU cycles and network bandwidth? :-)

    --VS.
  19. I don't think we should supply another tool

    > > strictly because people choose to write
    > > none object oriented code. Might as well
    > > add support for functions and goto.
    >
    > Ironically, staeless session ejbeans (the only ones to use i am told) look a lot
    >like non-object-oriented functions to me, even though they are herded in groups.
    >Come on, I had structures (value objects) and methods to pass them into (EJB
    >services) in plain C twenty years ago, and RPC instead of SOAP. Aren't be busying
    >ourselves not knowing on what to spend CPU cycles and network bandwidth? :-)

    While yes, stateless session beans are a bit on the none OO side (they are
    still objects and still use an object oriented API and have a bit of container
    state).
    You don't even need to wander into EJB's to get this approach, you can go to
    the servlet API as well....

    Whatever works best IMO.
  20. Voting against RFE's[ Go to top ]

    Shai Almog wrote:

    > Every SINGLE one of these features offers NO benefit whatsoever
    > to the language neither in performance nor in readability or
    > maintainance (every benefit gained in readability is offset
    > by the fact that your reading something that isn't realated
    > to whats really happening).

    Good point !

    One of the reasons C++ did not appeal to me at all and Java did was the unnecessary complexity of the language. But I have noticed that many people actually _like_ unnecessary complexity, as it gives them an opportunity to show of their language expertise !

    > I only wish that there was a way to vote against RFE's in the
    > sun bug parade.

    And I wish Arthur van Hoff would still be around at Sun to stop this seemingly inevitable pollution of the Java language (before Java came out he managed to keep out quite a few of these so called improvements as well).

    Cheers, Luc.
  21. Re: BAD ideas[ Go to top ]

    Firstly, I would like to say that entirely agree with your comments about simplicity... that is to me a key attribute of Java, and one that Sun should strive to maintain.

    However...

    > 1. ENUM's are the absolute worst.

    Why is it so bad to have a small number of known possible values for a type. What is your proposed alternative?

    > 2. Generics are just plain wrong.

    I have trouble understanding what is plain wrong about something that improves type safety for collections. Yes, there are still situations where class-cast exceptions can occur, but they are much reduced.

    The important thing to note is that incorrect types will never be able to be added to a typed collection, which is an order on magnitude better than the current situation where you only find an error when you try to get the object out.

    Have you ever tried figuring out which piece of code was responsible for adding an incorrect type to a collection - no fun at all, I can assure you. Assertions can help (for those who use 1.4).

    As an aside, why, why, why did Sun not make the 1.4 compiler just strip out assertions when it is being run in 1.3 'mode', rather than refusing to compile the assertions? Extremely unhelpful.

    Did you know that it is still possible to get a
    ClassCastException (or equivalent) when using generics in Java?


    Which circumstance did you have in mind?

    >3. Autoboxing again is here to cut down on typing.

    I was initially opposed to autoboxing, having seen some articles about issues with it in C#, but when I investigated further, they were due to extra features in C# that do not exist in Java. At the end of the day, as long as both the programmer and the compiler are clear about what is the effect of a piece of code, is it bad to reduce verbosity?

    >4. Why add static imports is beyond me.

    Agreed. Think the cost in potential abiguity at least matches the gain in improving terseness.

    /david
  22. Re: BAD ideas[ Go to top ]

    Firstly, I would like to say that entirely agree with your comments about

    >simplicity... that is to me a key attribute of Java, and one that Sun should
    >strive to maintain.

    Good.
     
    > However...
    >
    > > 1. ENUM's are the absolute worst.
    >
    > Why is it so bad to have a small number of known possible values for a type.
    > What is your proposed alternative?

    Please take a look at my other comments, its not the type safety I'm against
    but the very existance of this outdated concept of hardcoding all the
    posibilities. We use databases and encapsulation to provide this functionality
    better (as in faster, with dynamic implementation and more elegant code).

    > > 2. Generics are just plain wrong.
    >
    > I have trouble understanding what is plain wrong about something that improves
    >type safety for collections. Yes, there are still situations where class-cast
    >exceptions can occur, but they are much reduced.

    The implementation is problematic (if you will follow my other posts).
    And they simplify the simple while doing nothing regarding the reall
    problems.

    Templates are useful in C++ but generics arn't templates and neither one is
    really needed in Java which is a dynamic language.
     
    > The important thing to note is that incorrect types will never be able to be
    >added to a typed collection, which is an order on magnitude better than the
    >current situation where you only find an error when you try to get the object
    >out.

    This isn't true. You will be able to add untyped data and you will get class
    cast exception when linking against binary classes.

    This will simplify whats really simple like a collection of Strings/Numbers,
    and this really isn't necessary. It will leave everything else complicated
    (collections of Polymorphic objects).

    > Have you ever tried figuring out which piece of code was responsible for
    >adding an incorrect type to a collection - no fun at all, I can assure you.
    >Assertions can help (for those who use 1.4).

    Surprise I voted for assertions.
    They were a small impact and they provide a great benefit. Generics are a
    very large impact, they will be forced upon people who don't want to use
    them (if an API returns a generic collection you have no choice). And they
    won't work correctly. The very minor benefit of dubiously simplifying simple
    collections (while making the syntax awkward) isn't worth it.
    The only reason this got this far is because C# has it.
      
    > Did you know that it is still possible to get a
    > ClassCastException (or equivalent) when using generics in Java?

    >
    > Which circumstance did you have in mind?

    I gave an example. Every generic collection can be cast to a none generic
    collection for compatability so we can pass it into a method that doesn't
    work with generics (probably older code) in which case that method may modify
    the collection in an illegal way causing great confusion to the user.
     
    > >3. Autoboxing again is here to cut down on typing.
    >
    > I was initially opposed to autoboxing, having seen some articles about issues
    >with it in C#, but when I investigated further, they were due to extra features
    >in C# that do not exist in Java. At the end of the day, as long as both the
    >programmer and the compiler are clear about what is the effect of a piece of
    >code, is it bad to reduce verbosity?

    Yes, to some degree. I don't think people are clear about those things.
    In C++ constructors and cast operators will be invoked invisibly just as the
    compiler bends over backwards to try to do what it thinks you want.
    This caused no end of debugging.

    I very much oppose the idea of a compiler deciding it knows what I mean, this
    might cost me a little bit of typing. But the advantage is that beginners will
    maintain the understanding of the separation between the primitives and the
    Objects which is crucial to understanding Java and its performance.
  23. Re: BAD ideas[ Go to top ]

    but the very existance of this outdated concept of hardcoding all the
    posibilities. We use databases and encapsulation to provide this functionality
    better (as in faster, with dynamic implementation and more elegant code).


    Oh yes - we tried holding possibilities in a DB. Just ended up having to duplicate some of the state possibilities into the code where decision making is required on options in the DB.

    So you end up with code/DB duplication, which need to be enforced/tested using Unit Tests.

    The issue is that the world is imperfect - subclassing for all required types restricts dynamicism, storing in the DB restricts static decision making. Two forces pulling in opposite directions, with no easy compromise.

    There may be scope in dynamically writing subtypes at runtime using the DB data, but then statically overriding general operation for specific types (either using equality, instanceof or overriding polymorphic methods) remains highly problematic.

    This isn't true. You will be able to add untyped data and you will get class
    cast exception when linking against binary classes.


    Your issues are all based around linking types collections with legacy libraries. However, if there is a type expectation in the libraries that isn't documented, then the libraries are broken anyway - that is nothing to do with generics.

    I really think you are mis-attributing the problem here....

    It will leave everything else complicated
    (collections of Polymorphic objects).


    If you are storing objects in a typed collection where you are relying on object being subclasses (having more information), then you are breaking polymorphism.

    The whole point about polymorphism is that all of the objects should be interchangable - if I create a LinkedList<Number> collection, and then subsequently rely on casting an object from that collection to an Integer to use Integer specific features then I am breaking polymorphism...

    ...specifically, I am writing stupid code and am looking to create problems for myself.

    Surprise I voted for assertions.

    To be blunt - I would have grave concerns about your judgement had you voted against ;-)

    /david
  24. Generics[ Go to top ]

    Regarding Generics, I've implemented type-safe containers by simply subclassing a List and overring the appropriate methods to check the type of the Object being added, and added convenience methods to get a type-casted return type on retrieval functions. This becomes more difficult, but not impossible, to extend to its Iterators and so forth.

    The issue at hand is not that it is a new capacility in the language, but that it speeds up the work. Developers will no longer have to implement such type-safe Collections on their own, nor rely on code-generators to do it for them.

    However, these generics won't offer me the sort of parametric-polymorphism I've been drooling about since I read Tim Seeny's article on it years ago. I want to be able to subclass an entire framework, and override one of its constituent classes, and have all other inherited code refer to my new class instead of the old one. THAT would be power.
  25. Generics[ Go to top ]

    Regarding Generics, I've implemented type-safe containers by simply subclassing

    >a List and overring the appropriate methods to check the type of the Object being
    >added, and added convenience methods to get a type-casted return type on
    >retrieval functions. This becomes more difficult, but not impossible, to extend
    >to its Iterators and so forth.

    Please read my other posts explaining both why generics won't work and why they
    are redundant. The proposed implementation just doesn't work.
  26. Autoboxing[ Go to top ]

    Regarding autboxing, one thing you gain (speed of development) is also a loss (loss of performance). This is not an absolute, but consider the case where you want to use int's as a key in a HashMap. Autoboxing would convert each int to an Integer, and internally, the HashMap could be calling .hashCode() and .equals() like mad. However, if someone wrote their own IntHashMap (which I've done), you would use the int itself as the hashcode, and use the equality operator instead of a .equals() method call. This would be quite a bit faster. But autoboxing will tend to obscure this difference at the surface.
  27. ClassCastExceptions on Generics[ Go to top ]

    Did you know that it is still possible to get a
    ClassCastException (or equivalent) when using generics in Java?


    Just double checked - trying to add an object of incorrect class to a 'typed' collection is caught by the compiler.

    I can see that the generics implementation may still allow some ClassCastExceptions, but I am interested in what situations you envisage it happening.

    /david
  28. JDK1.5 Features[ Go to top ]

    IMHO, I think that the inclusion of enums, and autoboxing are great features to be added to the java platform.
  29. Why add static imports ?[ Go to top ]

    what if two statically imported classes have methods with same name and signature ? I guess it would be impossible to do such import....
  30. Handle it the same way[ Go to top ]

    You have thats ame problem now if two packages have the same class name and you import them as .* -- however, there is a rule in the language specs which says that one import has precdence over the other. I can't remember which (is it the first or last?), but I recall encountering this myself years ago. That's why, with rare exception, I import every class exlicitly. These sorts of naming conflicts are much more apparent then,
  31. ClassCastExceptions on Generics[ Go to top ]

    Did you know that it is still possible to get a

    > ClassCastException (or equivalent) when using generics in Java?

    >
    > Just double checked - trying to add an object of incorrect class to a 'typed'
    >collection is caught by the compiler.
    >
    > I can see that the generics implementation may still allow some
    >ClassCastExceptions, but I am interested in what situations you envisage it
    >happening.

    Since generics maintain compatability you can call "none generic" code which
    adds an element to your now "seemingly regular" collection. This will cause
    an exception.
    This isn't a rare use case, when people run into it they will look
    for someone to hang from a flagpole since this is really not obvious
    to people who don't understand how generics are implemented.
  32. ClassCastExceptions on Generics[ Go to top ]

    Shai wrote:
    Since generics maintain compatability you can call "none generic" code which
    adds an element to your now "seemingly regular" collection. This will cause
    an exception.


    Just tried calling the generic add on a subroutine that had been passed a 'typed' LinkedList. Got the following:

    <pre>Note: mypack/Test.java uses unchecked operations.
    Note: Recompile with -warnunchecked for details.</pre>

    Ading the -warnunchecked flag yields the following:

    <pre>mypack/Test.java:39: warning: unchecked call to add(E) as a member of the raw ty
    pe java.util.LinkedList
            list.add( new String("Bad!"));
                ^
    </pre>

    Also tried reassigning a standard collection to a 'typed' collection. Got:

    <pre>mypack/Test.java:39: warning: unchecked assignment: java.util.LinkedList to java
    .util.LinkedList<java.lang.String>
            LinkedList<String> ys = list;
                                    ^
    </pre>

    Which looks to me as if they cover this as long as you don't ignore the warnings(!)

    /david
  33. ClassCastExceptions on Generics[ Go to top ]

    <pre>Note: mypack/Test.java uses unchecked operations.

    > Note: Recompile with -warnunchecked for details.</pre>
    >
    > Ading the -warnunchecked flag yields the following:

    A. You need to add a specific flag.
    B. Large projects have a ton of warnings due to the liberal use
    of deprections. If we want to maintain 1.3 compatability there
    are some deprecated methods we need to use.
    C. Reflections and most dynamic code won't provide any warnings.
    D. Warnings are often ignored by the same people who will be bitten
    the worse by this problem.
    E. Warnings in Java appear only on rebuild and are very easily
    missed and lost. The person compiling that code the first
    time will see the warning and understand, the one who actually
    runs into the problem will never see the warning!
    F. If a library performs this type of cast for compatability or
    due to a requirement we won't see any warning since the library
    is binary.


    Warnings should not be used in place of errors. What we have here
    is an object that no longer respects its contract, thats an
    error!
  34. ClassCastExceptions on Generics[ Go to top ]

    A. You need to add a specific flag.

    Ermm, yes... and?

    B. Large projects have a ton of warnings due to the liberal use
    of deprections. If we want to maintain 1.3 compatability there
    are some deprecated methods we need to use.


    Use of a decent IDE would allow to control your warnings and have important ones flagged as errors.

    C. Reflections and most dynamic code won't provide any warnings.

    Yep, agreed. I have had a quick look at their proposed changes to reflection, but there don't seem to be an implementation in the generics examples.

    Changes to reflection would be good, but would presuambly break backwards compatibility...

    D. Warnings are often ignored by the same people who will be bitten
    the worse by this problem.


    I'm sorry - but if you ignore a warning and then are taken by surprise by an error that results from it, you're on your own...

    ... a long time ago I worked with someone who turned off all warnings (had a couple of thousand of them - didn't know what they meant - didn't care). His project collapsed under the weight of bugs.

    E. Warnings in Java appear only on rebuild and are very easily
    missed and lost. The person compiling that code the first
    time will see the warning and understand, the one who actually
    runs into the problem will never see the warning!


    Use a decent IDE.

    F. If a library performs this type of cast for compatability or
    due to a requirement we won't see any warning since the library
    is binary.


    Yes. The important question though is 'What is the library doing to the collection'. If it is doing something that breaches the generics contract, that it is still breaching the unwritten contracts between the two pieces of code.

    If your unit testing is as good as you say, that library should have already blown up your test! Or don't you have unit tests on these libraries? In which case, all you said about having unit tests that ensure that incorrect data can never be inserted into collections would be completely incorrect...

    Warnings should not be used in place of errors. What we have here
    is an object that no longer respects its contract, thats an
    error!


    Problem is (like you say) is backward compatibility for existing code. (Otherwise deprecated should be an error!)

    /david
  35. ClassCastExceptions on Generics[ Go to top ]

    A. You need to add a specific flag.

    >
    > Ermm, yes... and?

    People will just ignor it. Just like deprecated methods etc... The problem is
    that warnings aren't repeated in later compiles only rebuilds.

    > B. Large projects have a ton of warnings due to the liberal use
    > of deprections. If we want to maintain 1.3 compatability there
    > are some deprecated methods we need to use.

    >
    > Use of a decent IDE would allow to control your warnings and have important
    >ones flagged as errors.

    Using Eclipse are we?
    I myself don't use an IDE but most large projects would have a large amount of
    warnings as I said and you develop a habit of somewhat ignoring them after some
    point. Sure, when integration arrives you go through each one, but that might
    be too late.
    Anyway we are assuming highly confident developers who probably also know about
    the way generics are implemented in Java... The problem will hurt the most the
    relative newbies.
     
    > C. Reflections and most dynamic code won't provide any warnings.
    >
    > Yep, agreed. I have had a quick look at their proposed changes to reflection,
    >but there don't seem to be an implementation in the generics examples.
    >
    > Changes to reflection would be good, but would presuambly break backwards
    >compatibility...

    Nothing!! Is worth breaking compatability.
     
    > D. Warnings are often ignored by the same people who will be bitten
    > the worse by this problem.

    >
    > I'm sorry - but if you ignore a warning and then are taken by surprise by an
    >error that results from it, you're on your own...

    There is a convention in Java regrading what constitutes a warning and what
    constitutes an error. Unlike C++ where warnings are up to the compiler vendor
    in Java Sun was pretty clear that everything that causes "real" damage is an
    error. The moment a contract is broken its an error, you can't place a long
    into an int without explicitly saying so (in C thats a warning).
    EVERY other warning in Java doesn't break anything! Deprecated methods work!
    Everything works regardless. Up until now warnings were just general and Java
    used errors for placing long into an int without a cast.
    This is the first and AFAIK the only warning that will probably cause an
    application to break (you can make an argument for Thread.stop() but that
    should work as the API specifies).
     
    People ignor warnings because they were never used for anything critical in
    Java. Furthermore they will look at the warning and decide it is ok. Only later
    will the problem appear (possibly to a different programmer) and by then the
    warning would have been forgotten. I remember this exact scenario, from C++
    and these are the exact problems that Java up until now avoided. While Java
    has its warts it NEVER knowingly added a broken feature to begin with.

    > ... a long time ago I worked with someone who turned off all warnings (had a
    >couple of thousand of them - didn't know what they meant - didn't care). His
    >project collapsed under the weight of bugs.

    True, I am working on a project that has 30 (I'm linking external code that
    needs to compile against some deprected servlet methods, don't ask ;)
    anyway I doubt if I will notice 1 more or less and I usually notice these
    things.
     
    > E. Warnings in Java appear only on rebuild and are very easily
    > missed and lost. The person compiling that code the first
    > time will see the warning and understand, the one who actually
    > runs into the problem will never see the warning!

    >
    > Use a decent IDE.

    I'm guessing you use Eclipse, I can't stand it myself. I find its error handling
    to be terrible. Anyway Java is a standard not an idea or a product, you can't
    fix things by providing a GUI. Check out JBoss vs. the RI, JBoss is much
    easier to use despite having no decent GUI while the GUI of the RI is just a
    buggy mess (in J2EE 1.3).

    > F. If a library performs this type of cast for compatability or
    > due to a requirement we won't see any warning since the library
    > is binary.

    >
    > Yes. The important question though is 'What is the library doing to the
    >collection'. If it is doing something that breaches the generics contract,
    >that it is still breaching the unwritten contracts between the two pieces of
    >code.

    Yes it is, but you don't have any control over the quality of the software
    you get from vendors. Furthermore, it might be using an external library
    itself or possibly extracting data from you via a callback. The possibilities
    for unpredictable failure are endless.
    When I get a class cast exception I get a specific line in which the failure
    occured and I know the problem. With Generics I will get an exception from the
    internals of a collection and possibly a third party vendor which I have no
    clue of where to start.
     
    > If your unit testing is as good as you say, that library should have already
    >blown up your test! Or don't you have unit tests on these libraries? In which
    >case, all you said about having unit tests that ensure that incorrect data can
    >never be inserted into collections would be completely incorrect...

    I said that it will solve simple cases not complex cases as the ones I
    described. Yes I might have sounded a bit overconfident with that ;)
    Anyway I'm not saying unit testing won't find this (it probably will) but then
    we will have a much harder time finding the problem. I myself would probably
    know what to do but I doubt most people would understand why a supposedly
    type safe collection throws a ClassCastException?
     
    > Warnings should not be used in place of errors. What we have here
    > is an object that no longer respects its contract, thats an
    > error!

    >
    > Problem is (like you say) is backward compatibility for existing code.
    >(Otherwise deprecated should be an error!)

    Huge difference, deprecated methods WORK and they work as close as possible to
    the 1.0/1.1/1.2/1.3 impelementations. Collection casting doesn't work like
    the collections that worked in 1.2/1.3/1.4....
  36. ClassCastExceptions on Generics[ Go to top ]

    I'm guessing you use Eclipse, I can't stand it myself. I find its error handling to be terrible.

    OK, I'll bite - terrible error handling? Go on, I'm intrigued...

    When I get a class cast exception I get a specific line in which the failure
    occured and I know the problem.


    Yes - the problem is that your system and the library are working to different contract specifications!

    At the end of the day - if the data coming out of the library is as bad as you say, I would treat it as an external data source and add a validation/cleansing layer before attempting to work with the data.

    With Generics I will get an exception from the
    internals of a collection and possibly a third party vendor which I have no
    clue of where to start.


    Clear the innocent and punish the guilty!! It would be a terrible situation knowing which line is was that was actually responsible for the problem! ;-)

    Thing is, you seem to think that by not having generics, it cures the problem - it doesn't. It just moves it somewhere else....

    > Problem is (like you say) is backward compatibility for existing code.
    >(Otherwise deprecated should be an error!)

    Huge difference, deprecated methods WORK and they work as close as possible to
    the 1.0/1.1/1.2/1.3 impelementations. Collection casting doesn't work like
    the collections that worked in 1.2/1.3/1.4....


    Officially deprecated says 'All bets are off... this may or may not work'. Yes, they may still work, but the contract that says they have to is no longer there.

    I've encountered one issue with a feature from 1.0 that was deprecated breaking in 1.4 (closed - will not fix). Think it was ID 4624678, but I can't check, as the bugbase is not serving documents at the moment.

    And the generics warning only indicates that the code might not work, and to check closely as to whether it will or not....

    /david
  37. ClassCastExceptions on Generics[ Go to top ]

    I'm guessing you use Eclipse, I can't stand it myself. I find its error

    >handling to be terrible.

    >
    > OK, I'll bite - terrible error handling? Go on, I'm intrigued...

    Well its a matter of taste, I used WSAD quite a bit for an IBM project and
    the concept of errors where you see all errors and warning for the project
    and the deployed code (which BTW has warnings in it that you should ignor)
    was simply impossible for me. Maybe I need to get used to their way of doing
    things but I doubt I'll ever be able to.
    While I used IDE's very extensively in the past, their features today can't
    keep up with my needs. Only the fastest IDE's have autocomplete which comes
    close to be useful (with my typing speed) and other than that they generally
    hold me back. Its nice to deploy with a right click but they actually make
    code maintainance harder (since they generate code once and then try in
    vain to keep it in sync).

    Anyway I digress, the point I was making is that we can't rely on IDE's to
    handle language level features and fix something thats broken. Please no
    flame on this (since its a bit offtopic): especially not with the sorry crop of
    current Java IDE's.
     
    > When I get a class cast exception I get a specific line in which the failure
    > occured and I know the problem.

    >
    > Yes - the problem is that your system and the library are working to different
    > contract specifications!
    >
    > At the end of the day - if the data coming out of the library is as bad as you
    >say, I would treat it as an external data source and add a validation/cleansing
    >layer before attempting to work with the data.

    The libraries code isn't necessarily bad, just different. And why should we
    build compatability layers for code written in Java. If you do that then
    you might as well give up on the whole downcast and settle for generics that
    are not downcastable.

    > With Generics I will get an exception from the
    > internals of a collection and possibly a third party vendor which I have no
    > clue of where to start.

    >
    > Clear the innocent and punish the guilty!! It would be a terrible situation
    >knowing which line is was that was actually responsible for the problem! ;-)

    Yes, I'm willing to forgive bad coding and broken contracts when it comes
    to an API implementation since that isn't a sweeping change that will break
    everything and be forced on people.
    I am not willing to accept that type of breakage in the language level.
    Big difference, a bad API/Library is fixable/replaceable.
     
    > Thing is, you seem to think that by not having generics, it cures the problem
    >- it doesn't. It just moves it somewhere else....

    Sorry if I said that, I don't deny the existance of the problem generics means
    to solve. I said two distinct things:
    1. Generics is slightly effective in the simple problems only and for so little
    a difference it isn't really necessary (this is debatable).
    2. Generics can't be backwards compatible and the current implementation is
    broken (this is a fact). I think this warrants either stopping the current
    JSR completely or at least rewriting it so generic classes cant be cast to their
    none generic counterpart.

    You could use special wrapper objects to simulate the casting behaviour, and the
    JIT could know about them and optimize them away. This will allow both 100%
    compatability and will eliminate the problem we have.

    ClassCastException
    java.util.Collection<Integer>...
    java.util.CollectionWrapper
    ....

    Just brainstorming here but how come this didn't come up in the JSR.
     
    > > Problem is (like you say) is backward compatibility for existing code.
    > >(Otherwise deprecated should be an error!)
    >
    > Huge difference, deprecated methods WORK and they work as close as possible to
    > the 1.0/1.1/1.2/1.3 impelementations. Collection casting doesn't work like
    > the collections that worked in 1.2/1.3/1.4....

    >
    > Officially deprecated says 'All bets are off... this may or may not work'.
    >Yes, they may still work, but the contract that says they have to is no longer
    >there.

    The moment this happens I bet Sun will turn that specific deprecation into an
    error. If not I will be the first one yellig foul.
    Its not that I care much about methods that were deprecated in 1.0 but
    I definetly need the strong distinction Java has between errors and warnings
    (as it has between types).

    > I've encountered one issue with a feature from 1.0 that was deprecated
    >breaking in 1.4 (closed - will not fix). Think it was ID 4624678, but I can't
    >check, as the bugbase is not serving documents at the moment.
    >
    > And the generics warning only indicates that the code might not work,
    >and to check closely as to whether it will or not....

    This is really bad, do you remeber the specific method/feature and the reason
    they gave. Some internal behaviour can't be simulated 100% which is
    understandable.

    Anyway this still isn't as bad as the generics issue since as I said, even
    the API is a library (the most important one yes) but generics are a change
    to the language. Thats a much bigger deal.
  38. ClassCastExceptions on Generics[ Go to top ]

    Generics can't be backwards compatible and the current implementation is

    > broken (this is a fact). I think this warrants either stopping the current
    > JSR completely or at least rewriting it so generic classes cant be cast to
    > their none generic counterpart.

    Essentially, your key objection is that generics aren't strict enough. Many people have the same complaint about exceptions in C++. In C++, by default, a function may throw any exception. This semantics was defined for mostly backwards compatibility reasons since most functions were designed without exceptions in mind. The key motivator for the current definition of generics is similar.

    Ideally, you'd want to make all classes declare all exceptions that they use, but practically this is problematic because any method can throw a run-time exception so all methods would need to declare at least one exception. Java solved this issue by silently declaring that all children of RuntimeException are implicitly thrown by all methods.

    Java gives you the choice as to how strict you want your exception prototypes to be. Why can't it do the same for generics?

    Essentially, I'm proposing that
       class Foo<T> { .... }
    be strict by default, meaning that Foo<T> is not automatically converted to Foo<Object> or Foo. New generics code would likely use this format since you wouldn't have to worry about interacting with legacy code.

    However, if you wanted an automatic conversion because Foo<T> needs to interact with legacy libraries that know nothing of generics, you'd add it to the declaration:
       class Foo<default T> { ... }
    or
       class Foo<T=Object> { ... }
    or
       class Foo<T->Object> { ... }
    or
       class Foo<autoconvert T> { ... }
    if you're willing to add an extra keyword.

    The standard collection classes would be declared to be
    Right now, List<T> is automatically converted to List as it is needed because otherwise it would require that all Java libraries (including the Swing and EJB libraries) be adapted to templates. However, there's no reason why a StrictCollection template library couldn't be created that followed strict template typing with no auto-convert.
  39. ClassCastExceptions on Generics[ Go to top ]

    Generics can't be backwards compatible and the current implementation is

    > > broken (this is a fact). I think this warrants either stopping the current
    > > JSR completely or at least rewriting it so generic classes cant be cast to
    > > their none generic counterpart.
    >
    > Essentially, your key objection is that generics aren't strict enough. Many
    >people have the same complaint about exceptions in C++. In C++, by default, a
    >function may throw any exception. This semantics was defined for mostly
    >backwards compatibility reasons since most functions were designed without
    >exceptions in mind. The key motivator for the current definition of generics is
    >similar.

    No.
    Thats not my complaint.
    I repeated it enough times already:
    1. Broken (can be fixed by making stricter)
    2. Unnecessary (Matter of opinion, can't be fixed).

    Hardly anyone defined anything in C++ for backwards compatability... They moved
    the whole thing into the std:: namespace and made some ridiculous changes.
    But I don't think this example is similar

    The reason they chose to do it this way was to avoid incompatible byte code.
    However there is no other choice.

    If you look at the problem with generics it will occur at most when people try
    to use it under older VM's usually in closed libraries, by forcing genrics to
    be used ONLY in 1.5+ environments adoption will be slower (people waited long
    enough they can wait a bit longer to get a WORKING implementation) but
    they won't fail (ever!)
    Furthermore generics will be implemented correctly as objects on their own
    which is consistent with Java arrays being objects.

    > Ideally, you'd want to make all classes declare all exceptions that they use,
    >but practically this is problematic because any method can throw a run-time
    >exception so all methods would need to declare at least one exception. Java
    >solved this issue by silently declaring that all children of RuntimeException
    >are implicitly thrown by all methods.

    This example is incorrect.
    It assumes all I want is strictness, when what I want is language consistency.
    Why would I want strictness for a feature I don't care for and plan to avoid
    as much as possible?
     
    > Java gives you the choice as to how strict you want your exception prototypes
    >to be. Why can't it do the same for generics?

    No it doesn't. If a method throws a declared exception you HAVE to catch or
    throw that exception. If you throw your own within your own API implementation
    thats fine.
    Anyway still offtopic.
     
    > Essentially, I'm proposing that
    > class Foo<T> { .... }
    > be strict by default, meaning that Foo<T> is not automatically converted to
    >Foo<Object> or Foo. New generics code would likely use this format since you
    >wouldn't have to worry about interacting with legacy code.

    Thats a suggestion, but I have a problem with the whole idea of tainting all
    "the old code". This should be a strict 1.5+ solution and should never allow
    downcasting.
    I couldn't care less about how generics are written since I don't intend
    to use them myself, I care about the ways in which they might break my
    applications.
     
    > However, if you wanted an automatic conversion because Foo<T> needs to
    >interact with legacy libraries that know nothing of generics, you'd add it to
    >the declaration:
    > class Foo<default T> { ... }
    > or
    > class Foo<T=Object> { ... }
    > or
    > class Foo<T->Object> { ... }
    > or
    > class Foo<autoconvert T> { ... }
    > if you're willing to add an extra keyword.

    Adding a keyword (with a compiler switch to turn it on) is legitimate although
    again further clutter to a clean language.
    Anyway as I said, I don't really care about this aspect of the implementation
    since there are many options that don't break compatability.
    Anyway this looks like the hellish template code to me.

    > The standard collection classes would be declared to be
    > Right now, List<T> is automatically converted to List as it is needed because
    >otherwise it would require that all Java libraries (including the Swing and EJB
    >libraries) be adapted to templates. However, there's no reason why a
    >StrictCollection template library couldn't be created that followed strict
    >template typing with no auto-convert.

    You will need to adapt all libraries anyway. Might as well do it right and make
    sure the vendors of the libraries did it right.
  40. ClassCastExceptions on Generics[ Go to top ]

    >Well its a matter of taste, I used WSAD quite a bit for an IBM project and
    >the concept of errors where you see all errors and warning for the project
    >and the deployed code (which BTW has warnings in it that you should ignor)
    >was simply impossible for me. Maybe I need to get used to their way of doing
    >things but I doubt I'll ever be able to.


    Eclipse does provide a lot of control about how a number of warnings (and sometimes errors) can be treated. It also gives quite a lot of control over what shows up in the tasks list.

    >> At the end of the day - if the data coming out of the library is as bad as you
    >>say, I would treat it as an external data source and add a validation/cleansing
    >>layer before attempting to work with the data.

    >The libraries code isn't necessarily bad, just different.


    Aaaaaarrrggghhhh!!! That's the whole point: If the libraries are doing something different (like adding objects that are outside the range of object that you are expecting), then you should either be cleansing out the rogue objects before the collection is allowed loose into your system, or not using the library.

    /david
  41. ClassCastExceptions on Generics[ Go to top ]

    Eclipse does provide a lot of control about how a number of warnings (and

    >sometimes errors) can be treated. It also gives quite a lot of control over
    >what shows up in the tasks list.

    It does, I guess its a matter of taste. I was never able to use Emacs and to
    me Eclipse looks roughly the same (overly complex). I also never really liked
    the approach of Visual Studio which Eclipse seems to emulate to some degree.
     
    > >> At the end of the day - if the data coming out of the library is as bad as you
    > >>say, I would treat it as an external data source and add a validation/cleansing
    > >>layer before attempting to work with the data.
    >
    > >The libraries code isn't necessarily bad, just different.

    >
    > Aaaaaarrrggghhhh!!! That's the whole point: If the libraries are doing
    >something different (like adding objects that are outside the range of object
    >that you are expecting), then you should either be cleansing out the rogue
    >objects before the collection is allowed loose into your system, or not using
    >the library.

    This isn't really an option always. Anyway I think this thread is dead since
    whether the library should be removed or proxied is not really the point of the
    discussion.
    I think the points I was aiming for and ones we can agree on is:
    a. Problems will occur, since the way generics does things is different than
    the older way.
    b. It might prove very difficult to most programmers to understand the resulting
    problem triggered by the generics implementation. Rather than solve the problem
    some of them will simply workaround it without understanding what went wrong
    blaiming the bug on the library/VM.
    c. In some cases the fix might not be either elegant or simple. While we gave
    a relatively simple example there might be a case where the library vendor is
    right to add a different type (in a case of a polimorphic object).
  42. Simply saying, I agree on your point.
    I can't judge how each single feaure would have impact on the future the
    language. Maybe, they won't do any harm.
    My belief is that whatever new features should not scare off
    new comers as well as existing users. Nobody can't deny
    simplicity was one of the strongest points behind the trendmendous
    success of Java. Programming is not a hobby of technical geeks any
    more, as you all know. Java should maintain its position as simple
    and powerful enough for mixed groups of novice and experts.
    The complexity of the software has grown for years, the languahge
    should not add much more complexity to it. Unfortunately, I am not
    at the point that I can make sound judges for the sake of Java
    in all sides without technical bias. I hope people in the leadership
    positions would do. One thing I want to say to them is that opnions
    in this board mostly from people proud of their technical supremacy
    do not account for all levels of Java users including the prospects.
  43. Shai Almog:
    > 1. ENUM's are the absolute worst.

    Let's see:

     public void foo(int myenum);

    Tell me what values I should use in myenum so I get correct behaviour? The method is not documented so I don't know. When you have an answer for me, I accept your argument that enums are the absolute worst.

    >
    > 2. Generics are just plain wrong, and even worse in the way they
    > are implemented.

    Let's see:

       public Collection getFoo();

    Tell me what type objects should I expect from the collection returned from this method. The method is not documented so I don't know. When you have an answer for me, I accept your argument that generics are plain wrong. Right now Java has the "poor man's" generics where everything is Object. Cool.
     
    > Every SINGLE one of these features offers NO benefit whatsoever
    > to the language neither in performance nor in readability or
    > maintainance (every benefit gained in readability is offset
    > by the fact that your reading something that isn't realated
    > to whats really happening).

    So you are saying that my examples are perfectly good for readability and maintenace? Good luck.

    --
    Tero
  44. I think it is deveopers responsibilities to produce cleaner
    codes, not the language features. Seasoned developers first
    get a grasp of the limitations and best practices for
    the language. Your example is actually an example of short-sigted
    programmers's mistake not the lack of language features.
    What Generic-haters here argue is, I think, that keeping
    the complexity in check is the best way to reduce such a
    misuse of the language. Many ppl cry for usefulness of generics
    and enums. Those features are quite useful and powerful
    when applied appropriately.
    However, many of usefulness come from the situations that were
    created in a mind set fixed from other langauges. If such features
    are absolutely needed, then there are so many other languages
    on the shelf. Java has been powerful enough in most cases Java
    has thrived. Even though I dont believe
    couple of new features would falter the langauge in the near future,
    if Java is evolved in a way that starts to satisfy all of advancing
    feaures of Ph.D papers, it wouldn't be able to avoid the path of C++.
    I think Java is just a fine language that is obivous enough for
    the new comers to not take years to learn and simple enough to
    write the system of millions lines of codes and stupid enough to just
    do basic information processing. Isn't that what Java is for???
  45. I think it is deveopers responsibilities to produce cleaner

    > codes, not the language features.

    Agreed to a certain extent. We need to ensure that the language does not grow unnecessarily since each feature has a cost in terms of language complexity, learning time, and ambiguity. C++ has several grey areas where only language nazis can predict the result (look at some of the obfuscated C++ contests). If you have to spend more than 1-2 seconds trying to understand a line of code, the language is too complex for large projects. Maintenance, which requires a lot or re-reading the code, just takes too long.

    However, if language simplicity and the costs of adding features were the only factors that were important, we'd be all be programming assembly language. Who needs types when untyped words can do the job? Who needs variables when registries, stacks, and heaps? You can write a full J2EE application in JVM, especially if you have a JVM macro language like they do for normal assembly language. It's definitely simpler and more well defined than Java. Anything you can do in Java, you can do in the JVM. In fact, I'm willing to bet you could do more in the JVM than Java.



    Java is just syntactic sugar for patterns of JVM code. So why use Java? Simply because JVM code is too flexible so it's easier to be error-prone when programming JVM code. It also doesn't encapsulate the higher level patterns (e.g. for loop, method, inner class, etc) so programmers need to spend more time understanding the same amount of functionality. We need to take both the costs and benefits into account.

    Metadata, foreach, static import, enum and generics are just syntactic sugar. They each encapsulate popular Java patterns.

    Foreach, static imports, and enums are extremely easy to learn, add almost nothing to the language complexity or ambiguity. This minimal cost needs to be weighed against the benefits. Static imports get rid of the common incorrect pattern of inheritence of constants (i.e. If MyClass needs several constants from Constants, inheriting MyClass from Constants means that MyClass ISA Constants.). Foreach and enums reduce reduce the writing of error prone code. Is the benefit worth the (small) cost? That's debatable (I think some form of enum is). My only concern is that with the current implementation of enums is how it interacts with EJBs. If enums were simple integers, there would be no problems since integers are passed by value, but since enums are classes, there may be a few class-identity issues.

    Metadata is something that adds little complexity to the language but it's impossible to understand without knowing the context of the usage (i.e. the same tag can mean many things). To evaluate it, it needs to be compared with technology patterns it's trying to replace (e.g. 3 EJB classes for one implementation class and information in the deployment descriptor) to see if there are any real benefits. Anecdotal evidence from XDoclet (it's closest cousin) seems to indicate that it may be worth the cost, so the only question is whether it's better to incorportate Metadata into the language as a language extension, incorporate it in the J2EE library/tools spec, or let 3rd part tools like XDoclet handle the feature.

    Generics, under the current implementation, are fairly restricted, easy to understand, and interact well with legacy libraries (e.g. a List<T> can be passed to a method that expects a List). They reduce the need for casting, provide more documentation on the usage of collections, reduce the number of classes you need, and reduce the error-prone case where you add the wrong data-type to a collection. If my experience with C++ is any indication, errors messages in templated code tend to be more cryptic, although using templated code tends to be simpler and easier to explain. Is this feature worth the price? I definitely think it's worth it for the standard library collections, but whether it's worth it for general purpose programming is debatable. I'm a bit concerned, again, how generics interact with EJB code. What happens if you say your method passes or returns a generic?
  46. "JVM Code"[ Go to top ]

    Java is just syntactic sugar for patterns of JVM code. So why use Java? Simply because JVM code is too flexible so it's easier to be error-prone when programming JVM code. It also doesn't encapsulate the higher level patterns (e.g. for loop, method, inner class, etc) so programmers need to spend more time understanding the same amount of functionality.


    ---

    I understand the point you're trying to make, but the statements you're using to try to make that point are false. The JVM spec explicitly specifies inner classes and methods, and the bytecode for while and for loops is so simple and predictable that any decompiler can very easily detect and 'reverse engineer' them. This is one of the characteristics that separates the JVM from many other computing machines. Its primitives operate at a much higher level of abstraction.

    Aside from all that, pretty much every addition to the language that we're seeing in Tiger is just a small amount of syntactic sugar - even Java Generics. All of the changes, combined, make a small contribution to the improvement of the type system. I'll be nice and save my raves and rants on the weakness of Java Generics for another day.

    God bless,
    -Toby Reyelts
  47. Grey areas[ Go to top ]

    Well said!

    Some comments:

    >>> "We need to ensure that the language does not grow unnecessarily since each feature has a cost in terms of language complexity, learning time, and ambiguity. "

    If it isn't in the language, it is in J2EE and WAR descriptors.

    There's no way to ignore complexity. It is however often possible to express it in more simple terms, hiding repetitive details (patterns). One file instead of two or three or... five (.java with attributes), a pictute (a live UML diagram auto-generated from source), a set of Java classes auto-generated from an XML schema, a cool class loader, injecting code in each method for profiling / tracing / J2EE (COM+, originally) interception.

    Truly, finding these patterns and collapsing them into a robust construct is a way to combat complexity. Only I doubt that a single language can do it. At a certain level, Java itself becomes too low-level. Examples include Castor, JSP, UML (Together J), Web Services orchestration (BizTalk).

    >>> "C++ has several grey areas where only language nazis can predict the result (look at some of the obfuscated C++ contests).

    Java has its "finer" areas, too: enum little classes misgehaving in J2EE servers is one, hashCode-equals pair in HashMaps, etc. is another, not to mention data synchronisation on SMP machines.

    Why should we all stick to improving an average model of a pedal car (granted, safe for everyone) but never think of designing a bike and a jet, too. (JIT isn't jet, BTW :-))

    Well, I wrote is as a joke, but doesn't jit look like a fine piece of overengineering? Java now is primarily used on servers. Why not pre-compile byte codes once (similar to rmi stubs)? Then the whole jit runtime "database" can be disposed of, and the compiled code loaded as shared for all processes. The runtime library would be the first candidate for compilation, at the time when jdk or jvm is installed. (Guess who already does this?).

    regards,
    --VS.
  48. However, if language simplicity and the costs of adding features were the only

    >factors that were important, we'd be all be programming assembly language. Who
    >needs types when untyped words can do the job? Who needs variables when
    >registries, stacks, and heaps? You can write a full J2EE application in JVM,
    >especially if you have a JVM macro language like they do for normal assembly
    >language. It's definitely simpler and more well defined than Java. Anything you
    >can do in Java, you can do in the JVM. In fact, I'm willing to bet you could do
    >more in the JVM than Java.


    Robert,
    we agree on that, so no offence but there is no need to be cynical ;)

    Anyway my point is that Java is very successful in part due to its simplicity.
    By adding features that both clutter the language and CANNOT BE AVOIDED by
    those of us who don't want them (since they will be used by API's we need)
    well... I would personally feel dissapointed (I really don't want to use
    the word betrayed here since Sun usually listens to its customers and ISV's).
     

    > Java is just syntactic sugar for patterns of JVM code. So why use Java? Simply
    >because JVM code is too flexible so it's easier to be error-prone when
    >programming JVM code. It also doesn't encapsulate the higher level patterns
    >(e.g. for loop, method, inner class, etc) so programmers need to spend more
    >time understanding the same amount of functionality. We need to take both the
    >costs and benefits into account.

    I myself hardly ever get class cast exceptions of the type generics solve.
    I suggest everyone here writes down all of these cases in which you got such
    an exception. You will see that these cases occur when you use polymorphic
    collections, and this won't be solved by generics.
    People expect great changes for genrics but frankly generics will make the
    really easy things (single type collections) very slightly simpler, while
    not making a difference to the complicated things (polimorphic collections).
    Furthermore the fact that a compatible implementation that actually works
    is technically impossible adds a level of complexity that makes the change
    completely impossible.

    If I were to write a new language I wouldn't add generics but I guess I am
    the exception to the rule but since it can't be done correctly I think
    the majority should definetly oppose this.

     
    > Metadata, foreach, static import, enum and generics are just syntactic sugar.
    > They each encapsulate popular Java patterns.

    I didn't say anything about metadata. I might actually like it since I'm using
    XDoclet at the moment and I can't see any problem with it, but I haven't studied
    the matter to give an educated opinion.

    Sugar makes you fat, makes your teeth rot and doesn't give much in return except
    for a taste that doesn't last. This is a great example.
    I agree that languages should do as much as possible to help the programmer from
    shooting his foot in runtime, but the question is how much help is gained:

    1. Generics will help very little and make matters worse to boot (as explained
    above).

    2. ENUM's encorage people to program as they did in C/C++ (I'm not even going
    into the stupid JSR about adding printf() like functionality).

    I saw lots of people complaining about Java's performance since they programmed
    it like they were in C (using constants etc...) and got none of the advantages
    of generic OO code. Adding ENUM's would mean they would use it and NEVER learn
    how to program properly, there is no reason to add oil to the fire.


    > Foreach, static imports, and enums are extremely easy to learn, add almost
    >nothing to the language complexity or ambiguity. This minimal cost needs to be

    This "minimal cost" will be much worse:
    1. It will "legitimate" modifying the ONLY stable widely used commercial
    language that we have. This will harm one of Java's key advantages for
    large businesses.

    2. It won't be a sweeping change through the API, which will cause AWT/Swing
    like inconsistency within it causing confusion to newer programmers.

    3. It will make Java code harder to read.

    I strongly advocate the approach of James Gosling to resist every change
    and redundancy, thats what made Java great to me. Maybe its partially due
    to the "trauma" of C++'s ISO process that created this freakish language that
    has features to "work around" other features (mutable, virtual inheritance
    anyone).

    >weighed against the benefits. Static imports get rid of the common incorrect
    >pattern of inheritence of constants (i.e. If MyClass needs several constants

    If you use global constants then IMO you aren't using Java correcly. There
    is no need to add a feature to the language in order to persist a missguided
    use case, I myself haven't (neither is has anyone in any team I lead) used
    such a thing.


    >from Constants, inheriting MyClass from Constants means that MyClass ISA
    > Constants.). Foreach and enums reduce reduce the writing of error prone code.

    See my earlier post regarding this.

    > Is the benefit worth the (small) cost? That's debatable (I think some form of >enum is). My only concern is that with the current implementation of enums is
    >how it interacts with EJBs. If enums were simple integers, there would be no
    >problems since integers are passed by value, but since enums are classes, there >may be a few class-identity issues.

    Your making my case for me, there could be many integration issues we don't
    see. This might require working binary servers to be redeployed in order to
    support newer client applications...
     
    > Metadata is something that adds little complexity to the language but it's
    >impossible to understand without knowing the context of the usage (i.e. the

    As I mentioned above, I don't have a personal stance on Metadata.

    >same tag can mean many things). To evaluate it, it needs to be compared with
    >technology patterns it's trying to replace (e.g. 3 EJB classes for one >implementation class and information in the deployment descriptor) to see if
    >there are any real benefits. Anecdotal evidence from XDoclet (it's closest
    >cousin) seems to indicate that it may be worth the cost, so the only question
    >is whether it's better to incorportate Metadata into the language as a language
    >extension, incorporate it in the J2EE library/tools spec, or let 3rd part tools
    >like XDoclet handle the feature.

    Well, as I said I use XDoclet which I find to be much better than the visual
    tools so I am mostly with you on this. In my unofficial opinion I think they
    should standarize something similar to XDoclet to avoid language
    incompatability.
     
    > Generics, under the current implementation, are fairly restricted, easy to
    >understand, and interact well with legacy libraries (e.g. a List<T> can be
    > passed to a method that expects a List). They reduce the need for casting,

    This is the exact reason why they don't work ;)

    > provide more documentation on the usage of collections, reduce the number of
    > classes you need, and reduce the error-prone case where you add the wrong
    >data-type to a collection. If my experience with C++ is any indication, errors

    Why reduce code, you actually write special collections for types?
    I just use casts myself which is roughly the same amount of code (both compiled
    and as source).

    >messages in templated code tend to be more cryptic, although using templated
    >code tends to be simpler and easier to explain. Is this feature worth the
    >price? I definitely think it's worth it for the standard library collections,
    >but whether it's worth it for general purpose programming is debatable. I'm a
    >bit concerned, again, how generics interact with EJB code. What happens if you
    >say your method passes or returns a generic?

    I almost forgot to mention the cryptic nested template error messages, thanks ;)
    Regarding the interaction with EJB code... Again a great example regarding
    change.
  49. I think it is deveopers responsibilities to produce cleaner

    > codes, not the language features. Seasoned developers first

    I had this exact argument a couple of years ago.
    However your posting lacked a bit of substance as in real world examples where
    generics etc... made a difference.

    Feel free to elaborate.

    I see mostly academics in favor of generics and other features, most of the
    people who actually work on business solutions don't really want change.
    So you can claim (justifyable) that this group still uses COBOL, but it works!
    Thats very important to us, and by changing something very basic (and forcing
    us to change as well) the rug will be pulled from under our feet.

    You say that generics aren't complex, while its true they are simpler than
    templates they are neither necessary nor helpful:

    1. Templates exist in C++ because downcasting is bad. In Java casting isn't
    really bad, we don't need RTTI and have dynamic type safety. We have single
    inheritance which simplifies everything regarding casting.

    2. Generics are complex because they can be nested, imagine the compiler erros.
    Anyone who ever used STL to a reasonable extent knows that its far from simple.

    3. Generics simplify very simple problems. Joshua himself said that a vast
    majority of the collections work with simple types (String, Number's etc...)
    Is Collection<String> simpler than a cast? Not really.

    I object to adding something that hasn't been proven to solve anything.
    If it were a windowing toolkit we would sit a focus group and check whether they
    like this feature. Be your own focus group, check for every cast exception or
    problem you face and see whether generics will simplify it. I bet it won't.


    This is even without rasing the issue that generics arn't backwards compatible
    and will cause errors that will take programmers a great deal of time to
    understand. I can just imagine the forums flooded with newbie flames and rtfm's.
  50. enums are the worst[ Go to top ]

    public void foo(MyEnumType myenum);

    Class MyEnumType extends EnumType
    {
        protected void specifyEnumValue(String strValue) {
            try {
                enumValues.add("strValue");
            }
            catch (EnumValueAlreadyExistsException e) {
                // fail
            }
        public boolean setValue(String strValue, int intValue) {
            if (enumValues.contains(strValue)) {
                 try {
                     enumValues.put("strValue", new Integer(intValue);
                 }
                 catch (UnableToModifyEnumValueException e) {
                     // bork
                 }

    //...etc.


    Actually, wouldn't it be cool if we used JNDI lookups for enumerated lists, and then we could use remote enums! I'm sure if performance is a problem we could build a cache of frequently used enums, and by the time the hotspot JIT compiler takes care of it, we should be able to perform simple arithmatic, and maybe even string comparisons on our load balanced 16 way Sunfires.



    }
  51. I agree with Shai. We can argue all day on fancy language features, but at the end of the day we are making Java very complex just for the sake of competition.

    I am amaze no body cares much about the VM reliabilty and scalabilty in today's server centric applications. I like the idea of application domains in .NET, I bilieve Java folks should pay attention to issues like that.
  52. I wonder why a previous poster has been ranting so much about enums and generics. I find both of them very useful and not ugly at all. Especially generics are a major improvement over "Object"-only containers. The latter force you, if you are a careful programmer, to check each retrieval from the container against a ClassCastException. Not very beautiful, IMHO.

    Cheers,
        Henrik Klagges
        TNGtech
  53. Henrik, regarding Enums I have neather used them as numeral integers
    or "objects pretending to be ENUM's" for the past 5 years and neather
    has any developer working under me. The only place I allowed such
    constants is in J2ME programming or where an API implementation
    (bad API implementation) requires it.

    ENUM's are bad since they require switch like hardcoding (even if
    you write the code as if statements) which means hardcoding logic
    into a single class. Many C++ programms I worked with had central
    switch statements that just can't be modified since this will
    break something or other. The better approach is to use maps
    (I will ellaborate on that to another poster).

    Regarding generics my argument is twofold:

    1. Generics won't work correctly - since generics MUST be compatible
    to current code they have to "pretend" to be regular collection thus
    for binary compatability when I use:

    class NonGenericBinaryClass {
      public void methodThatAddsString(Collection c);
    }

    Collection<Integer> c;
    myMethod(c);


    I will get a class cast exception (or worse), this will be hell on
    newbies that will spend weeks debugging and on forums.


    2. Generics aren't ESSENTIAL, yes it would be nice not to perform
    casts. But ask yourself whats so terrible about casting, we still
    have type safety (in runtime no less). Even with generics you will
    still need to downcast (most of my collections are polymorphic).
    Its an additional complexity without any of the benefits simply put
    out to satisfy a checkbox feature list in front of C#.
    I hope Sun will be strong and keep Java small despite the pressure,
    if they feel generics are warranted they should start a new language
    that implements them correctly.

    Many of the people who disagree with my view of generics do agree that
    there is no way to implement them correctly without breaking compatability
    and some of these people agree that in that case they shouldn't be used
    at all.
  54. But ask yourself whats so terrible about casting, we still
    have type safety (in runtime no less).


    Because, like I said before, the Exception only occurs when you try to cast the Object after getting it out of the Collection, resulting in very had to trace errors (especially on a live or client system without diagnostics on it).

    I will get a class cast exception (or worse), this will be hell on
    newbies that will spend weeks debugging and on forums.


    You will only get a exception if to try to get out types that different from those that are in there... the usage that you outline in your post implies that the code then tries to use the collection as if it contains non-Integer objects... which is poor design, as the code that looks for other objects should be using typed collections.

    (most of my collections are polymorphic)

    Ahhhh! Here we come to the truth - you don't like generics because you don't actually use typed collections. Personally I have a big problem with heterogeneous collections (asking for trouble IMHO - I like to write robust code!).

    OK - if you don't want to use them - don't use them, but don't stop the rest of us from having them.

    /david
  55. But ask yourself whats so terrible about casting, we still

    > have type safety (in runtime no less).

    >
    > Because, like I said before, the Exception only occurs when you try to cast
    >the Object after getting it out of the Collection, resulting in very had
    >to trace errors (especially on a live or client system without diagnostics on
    >it).

    First, I find stack traces rather helpful.
    Second, if you get ClassCastException or NullPointerException in deployed
    systems then you have a pretty bad problem in your QA process.
     
    > I will get a class cast exception (or worse), this will be hell on
    > newbies that will spend weeks debugging and on forums.

    >
    > You will only get a exception if to try to get out types that different from
    >those that are in there... the usage that you outline in your post implies
    >that the code then tries to use the collection as if it contains non-Integer
    >objects... which is poor design, as the code that looks for other objects
    >should be using typed collections.

    It won't.
    That would require every single API written in Java to be rewriten.
    If you have a large code base that makes use of Collection<Integer> and you
    will want to make it work with an API that accepts Collection (if only for
    backwards compatability) you will have to either cast or copy neither one of
    which is bad since the casted object will no longer respect the object contract
    and the copyed object will need to be converted back or synchronized.
     
    The ClassCastException a person who will try to cast gets, will surprise many
    programmers and confuse them.

    > (most of my collections are polymorphic)
    >
    > Ahhhh! Here we come to the truth - you don't like generics because you don't
    >actually use typed collections. Personally I have a big problem with
    >heterogeneous collections (asking for trouble IMHO - I like to write robust
    >code!).

    A. I write robust code too.
    B. I don't remember this quote, but I guess I meant to say that most of the
    complicated collections on which I spend time are polymorphic. The Number
    and String collections are never a problem.
    C. I often use Number as a collection cast object to avoid dependency on Integer
    Long etc... This IMO if far more robust than Collection<Integer> although that
    is subjective.
     
    > OK - if you don't want to use them - don't use them, but don't stop the rest
    > of us from having them.

    If that were only the case. The reverse is true!
    By adding generics they will be forced upon us. Java (and 3rd party) API's will
    start passing generic objects and I will have to use the generic syntax in order
    to avoid the harmful cast we discussed.

    I voted for asserts and I might support Meta-Data since these API's won't burn
    the whole Java API and libraries by making them inconsistent and incompatible.
    These two changes don't change a basic element of how Java functions and are
    not patches over something that was never meant to be. These two features serve
    a purpose and actually reduce code, make it more maintainable etc...
  56. First, I find stack traces rather helpful.

    Me too. Unfortunately the stack trace in this case is for perfectly valid code that is merely trying to handle an incorrectly added object.

    Second, if you get ClassCastException or NullPointerException in deployed
    systems then you have a pretty bad problem in your QA process.


    Wow - can I live in your perfect world too? Hard experience has shown me that users have a tendency to find corner conditions that even the most rigorous testing fails to reveal. (BTW: I do try to avoid potential corner conditions and complexity for that very reaason).

    That would require every single API written in Java to be rewriten.
    If you have a large code base that makes use of Collection<Integer> and you
    will want to make it work with an API that accepts Collection (if only for
    backwards compatability) you will have to either cast or copy neither one of
    which is bad since the casted object will no longer respect the object contract
    and the copyed object will need to be converted back or synchronized.


    Ermm, are you referring to trying to pass a types collection to a generic API method, return one back or both?

    Passing a typed collection as a parameter should be fine, as long as the library isn't expecting anything other than Object.

    Using a library that creates an untyped collection is always going to be an issue (but a very obvious one - you are effectively wanting to downcast, so unless you write an adaptor method to copy the generic data to a typed collection while checking the type of each element, you are going to be on very dodgy ground).

    C. I often use Number as a collection cast object to avoid dependency on Integer
    Long etc... This IMO if far more robust than Collection<Integer> although that
    is subjective.


    Really depends whether you want/need to store Integers or Numbers! The important thing is to be consistent - if you're storing Numbers, don't try using them as Integers without checking first!

    /david

    BTW: Has anyone tried deploying EJB code using Generics in the remote interface to an AppServer yet? What were the results?
  57. This might appear twice, the forum crashed and when I tried the back button
    it wouldn't let me repost. I don't see the message now that its up so I'll
    just repost.

    > First, I find stack traces rather helpful.
    >
    > Me too. Unfortunately the stack trace in this case is for perfectly
    >valid code that is merely trying to handle an incorrectly added object.

    I disagree, the JavaDoc for the collection types specifically state that any
    object is valid. By casting down a generic collection we essentially brake
    a contract and lost a much more important element in the process.
    This is inconsistent with everything that is Java!
    I don't get a lot of ClassCastExceptions and not a single one of them would go
    away if generics were added. I bet the same applies to each and every person
    in this board.
     
    > Second, if you get ClassCastException or NullPointerException in deployed
    > systems then you have a pretty bad problem in your QA process.

    >
    > Wow - can I live in your perfect world too? Hard experience has shown me that
    >users have a tendency to find corner conditions that even the most rigorous
    >testing fails to reveal. (BTW: I do try to avoid potential corner conditions
    >and complexity for that very reaason).

    We have a strong testing policy and use JUnit rather extensively. It cuts down
    on development time significantly.
    Yes, I write code in a perfect world.

    Anyway these type of exceptions (and definetly the ones that are "helped" by
    generics) should occur in the most basic test cases. If you do get a class cast
    exception from unexpected user interaction it will probably be from a
    complicated use case (such as a polymorphic collection?).
     
    > That would require every single API written in Java to be rewriten.
    > If you have a large code base that makes use of Collection<Integer> and you
    > will want to make it work with an API that accepts Collection (if only for
    > backwards compatability) you will have to either cast or copy neither one of
    > which is bad since the casted object will no longer respect the object contract
    > and the copyed object will need to be converted back or synchronized.

    >
    > Ermm, are you referring to trying to pass a types collection to a generic API
    >method, return one back or both?

    Both, the reason to pass a mutable collection to a method is usually in order to
    get a result.
     
    > Passing a typed collection as a parameter should be fine, as long as the
    >library isn't expecting anything other than Object.

    Its expecting a Collection. Say I have a binary library that has a method

    addSomethingToCollection(Collection c);

    I have a Collection<Integer> that is referenced quite a bit and changing it to
    Collection is no longer feasable. I don't have a choice but to cast down.
    People will do stuff to avoid this (such as copying the collection) but
    no solution is even close to reasonable.

     
    > Using a library that creates an untyped collection is always going to be an
    >issue (but a very obvious one - you are effectively wanting to downcast, so
    >unless you write an adaptor method to copy the generic data to a typed
    >collection while checking the type of each element, you are going to be on very
    >dodgy ground).

    The type checking is done automatically by the generics implementation. The
    problem isn't there! We have a method add(Object) not add(Integer) yet it
    no longer accepts Objects. Thats a breach of contract. Interfaces of Objects
    are a contract between the developer and the API. Generics will change that
    contract and create a world of pain for people trying to figure out why they
    don't work. This problem does NOT exist in C++! This is simply a BAD
    implementation decision made by the developers of the generics API who knew
    generics won't be useful on their own so they made a horrible patch to try
    to make them compatible when they really aren't.
     
    > C. I often use Number as a collection cast object to avoid dependency on Integer
    > Long etc... This IMO if far more robust than Collection<Integer> although that
    > is subjective.

    >
    > Really depends whether you want/need to store Integers or Numbers! The
    >important thing is to be consistent - if you're storing Numbers, don't try
    >using them as Integers without checking first!

    Why?
    The number is the base class and if I need an integer I cast
    ((Number)obj).intValue();

    Sure I try to be as consistent as possible but IMO this is more robust and
    just won't fail as long as obj is indeed any type of number.

    This allows me to have Currency objects etc... which I need for the presentation
    layer.


    > BTW: Has anyone tried deploying EJB code using Generics in the remote
    >interface to an AppServer yet? What were the results?

    Shudder....
    Imagine the type of problems we will add since client VM versions are often
    different from server VM's.
  58. I disagree, the JavaDoc for the collection types specifically state that any
    object is valid. By casting down a generic collection we essentially brake
    a contract and lost a much more important element in the process.
    This is inconsistent with everything that is Java!


    Then you and I use collections in a very different way. Almost all my uses of collections involve storing a single class, or a set of classes of a consistent root class or interface.

    The important thing is that if the rule with the collection is that if the collection has been deemed to be a Number (say), then I should only ever assume that I'm going to get a Number out. If I assume that I'm going to get a Double, then I am breaking my own contract (and so need to check the type of the object before casting).

    By your method you could only ever assume that something is an Object - any further assumption is a breach of contract!!!

    The whole point of generic collections is so that the compiler can enforce that contract that the contents must be of a certain type.

    > Really depends whether you want/need to store Integers or Numbers! The
    >important thing is to be consistent - if you're storing Numbers, don't try
    >using them as Integers without checking first!

    Why?
    The number is the base class and if I need an integer I cast
    ((Number)obj).intValue();


    You're missing the point again. intValue() is a member of Number, so no Integer assumption is required. That's fine.

    If however, you wanted to use a method from the Comparable interface (implemented on Integer, not Number), you would have to break the assumption that the contents of the collection were all Numbers. So a test for instanceof Integer would be necessary because you are working outside of the contract that the collection has.

    This allows me to have Currency objects etc... which I need for the presentation layer.

    So your presentation layer is expecting more information than just Number???

    addSomethingToCollection(Collection c);

    I have a Collection<Integer> that is referenced quite a bit and changing it to
    Collection is no longer feasable. I don't have a choice but to cast down.
    People will do stuff to avoid this (such as copying the collection) but
    no solution is even close to reasonable.


    You're making a good case for generics!! The point is that there is no current way of enforcing that the contents of a collection should be limited to a particular type.

    You are say that mixing collection methods that enforce two different contracts (Integer and Object) is bad. YES!!! The point that that at the moment you can do it quite happily without any compiler issues at all - how bad is that? Or even realising that you're doing anything wrong...

    Interfaces of Objects are a contract between the developer and the API.

    Object contract is the lowest case contract - good developers will use a contract that enforces a higer level contract (EventListener or something) that is actually of use.

    If you are saying that the contract is Object, then Object is the most that you can assume about the contents of the collection.

    E.g. if a client app fills your collection with Objects he is in perfect compliance of your contract. However, it is highly probably that you won't be able to do any processing on that data, because you really want objects of a different type to Object to be able to do anything useful with it (you are the one that is in breach of contract because you are really expecting something more than Object).

    That's why generics are necessary - to allow a more expressive (and useful!) contract between the parties utilising a collection.

    > BTW: Has anyone tried deploying EJB code using Generics in the remote
    >interface to an AppServer yet? What were the results?

    Shudder....
    Imagine the type of problems we will add since client VM versions are often
    different from server VM's.


    Strangely enough, I have my WebServer between my EJBs and my client.

    /david
  59. I disagree, the JavaDoc for the collection types specifically state that any

    > object is valid. By casting down a generic collection we essentially brake
    > a contract and lost a much more important element in the process.
    > This is inconsistent with everything that is Java!

    >
    > Then you and I use collections in a very different way. Almost all my uses of
    >collections involve storing a single class, or a set of classes of a consistent
    >root class or interface.

    Thats not what I said!
    The container contract accepts an object and it doesn't matter how you
    specifically work. If you get a pointer to a collection interface you can add
    any object to it... Not any more! That breaks compatability. The WRITTEN
    contract (JavaDoc API) between the Java and the user.

    Think about it, the first thing you do when an API returns you class X is check
    out the JavaDoc for class X. It accepts Object as a parameter for method y()
    how lovely. You send a Long object and get a class cast exception...
    Is the JavaDoc wrong????
    Why no.

    The fact that I use a single type in most of my collections as well is not
    relevant. If you will look at that code its trivial and adding generics won't
    change much. Who gets a class cast exception over a collection of Strings or
    Numbers???? The problems occure for that 5% where the collections contain
    polymorphic types, there all the generics in the world won't help at all.

    I said before, Collection make very little difference for the simple but do
    nothing to help the complicated problems.
     
    > The important thing is that if the rule with the collection is that if the
    >collection has been deemed to be a Number (say), then I should only ever assume
    >that I'm going to get a Number out. If I assume that I'm going to get a
    >Double, then I am breaking my own contract (and so need to check the type of
    >the object before casting).

    Double is a number?
    Anyway this isn't an intersting point just an anecdote can we drop it?
     
    > By your method you could only ever assume that something is an Object - any
    >further assumption is a breach of contract!!!

    By my method unless someone changes the contract explicitly then yes.
    Just like in C++ list<string> != list<void *> it doesn't make any sense.
    A typed collection should be a new class on its own thus holding a contract
    of its own. Code shouldn't be generated explicitly but it should behave like
    a different object type.
     
    > The whole point of generic collections is so that the compiler can
    >enforce that contract that the contents must be of a certain type.

    Thats a legitimate goal, I dissagree with its usefulness and that is a
    reasonable debate.
    The point is that generics cannot be implemented in the way the JSR
    proposed in the current Java VM. Casting them down is just wrong!
    and should be deemed an error.
     
    > > Really depends whether you want/need to store Integers or Numbers! The
    > >important thing is to be consistent - if you're storing Numbers, don't try
    > >using them as Integers without checking first!
    >
    > Why?
    > The number is the base class and if I need an integer I cast
    > ((Number)obj).intValue();

    >
    > You're missing the point again. intValue() is a member of Number, so no
    >Integer assumption is required. That's fine.
    >
    > If however, you wanted to use a method from the Comparable interface
    >(implemented on Integer, not Number), you would have to break the assumption
    >that the contents of the collection were all Numbers. So a test for instanceof
    >Integer would be necessary because you are working outside of the contract that
    >the collection has.

    Sure I'll have to cast in order to get comparable but why do that?

    What contract would I be breaking? I lost you there, I don't use generics
    and even if I were casting a Number to an Integer doesn't break anything.

    I think I got that, you mean that since I have an Object that I can't cast it
    without an instanceof. Aha but the big picture....
    I have a wide contract with the collection:
    1. A collection is created empty and can be changed only via the object I
    created.
    2. A collection will maintain all the objects I add and remove all the objects
    I remove.

    I know I only added Integer numbers thus casting to Intger is OK.
    Say I passed the collection to a method, then its contract needs to indicate the
    type of objects I get back in the collection. The problem is that people don't
    document nor respect these behaviours. However the Java API should always
    respect these notions since the API is the most basic contract we all have.
     
    > This allows me to have Currency objects etc... which I need for the
    >presentation layer.

    >
    > So your presentation layer is expecting more information than just Number???

    Sometimes, not in this particular application but yes.
     
    > addSomethingToCollection(Collection c);
    >
    > I have a Collection<Integer> that is referenced quite a bit and changing it to
    > Collection is no longer feasable. I don't have a choice but to cast down.
    > People will do stuff to avoid this (such as copying the collection) but
    > no solution is even close to reasonable.

    >
    > You're making a good case for generics!! The point is that there is no
    >current way of enforcing that the contents of a collection should be limited to
    >a particular type.

    It still won't. And fixing the internal implementation of a binary library
    isn't possible. Now that you know that the library is doing that, how would
    you go about fixing this? The vendor won't fix it (soon enough at least) so
    my solution will be: "change all the code and remove the generics" this is
    assuming the problem is found. It will take them forever to find the problem
    and most projects I know will probably just work around the problem.
     
    > You are say that mixing collection methods that enforce two different
    >contracts (Integer and Object) is bad. YES!!! The point that that at the
    >moment you can do it quite happily without any compiler issues at all - how bad
    >is that? Or even realising that you're doing anything wrong...

    So you suddenly place a restriction making existing code invalid?
    Thats far worse. I'd rather have a problem I know of than a whole set of
    new problems.

    I'm surprised you don't agree with me that the casting is a bad idea.
    I can accept that people want generics (I don't agree but then I don't agree
    about many things ;) but I can't imagine that even the biggest generics
    advocates want something so broken.
     
    > Interfaces of Objects are a contract between the developer and the API.
    >
    > Object contract is the lowest case contract - good developers will use a
    >contract that enforces a higer level contract (EventListener or something) that
    >is actually of use.

    That is done by subclassing and you see within the stack trace the specific
    element that changed the contract. Furthermore the API documentation will
    usually indicate the change of contract: If you have a NumberList then the
    API will mention that. You will have to invoke new somewhere.
    If you use a library that returns a NumberList then it should indicate that.
     
    > If you are saying that the contract is Object, then Object is the most
    >that you can assume about the contents of the collection.

    See my explanation above of the full extent of an object oriented contract.
     
    > E.g. if a client app fills your collection with Objects he is in perfect
    >compliance of your contract. However, it is highly probably that you won't be
    >able to do any processing on that data, because you really want objects of a
    >different type to Object to be able to do anything useful with it (you are the
    >one that is in breach of contract because you are really expecting something
    >more than Object).

    Thats just seeking an argument. You know full well what I mean.
    There is a contract with a collection but my contract is with the client
    library and theirs is within their documentation promissing me the specific
    objects I require.
     
    > That's why generics are necessary - to allow a more expressive (and useful!)
    >contract between the parties utilising a collection.

    Expressiveness is good. But then you end up in perl/C++ or C# all of which are
    a total mess IMO. Java places most of its expressiveness in the API which is
    where the complexity should be.
     
    > > BTW: Has anyone tried deploying EJB code using Generics in the remote
    > >interface to an AppServer yet? What were the results?
    >
    > Shudder....
    > Imagine the type of problems we will add since client VM versions are often
    > different from server VM's.

    >
    > Strangely enough, I have my WebServer between my EJBs and my client.

    I ran some projects that had client VM's communicating using serialization
    or Corba to the EJB server. This is not uncommon.
  60. Hi Shai,

    >I'm surprised you don't agree with me that the casting is a bad idea.

    Oh, I do think it is a bad idea - if it being done by user (e.g. casting collection 'get' results). If it is checked by, and then added by, the compiler, then I don't see it as a problem.

    >That is done by subclassing and you see within the stack trace the specific
    > element that changed the contract. Furthermore the API documentation will
    > usually indicate the change of contract: If you have a NumberList then the
    > API will mention that. You will have to invoke new somewhere.


    Yep - that's fine. Perfectly good approach.

    One problem: How do you then pass your custom collection to these libraries that you say you need to use?!!! The only ways are

    a) To expose the hidden inner list to the library (breaks the contract as the library may add Strings to your NumberList).

    b) Implement the general List interface on your NumberList (allows everybody to drive coach and horses through your Number requirement!)

    Either way you're stuffed - bottom line is your code and the library are trying to do different things with the data. Like I said (ages ago), the problem is with conflicting contracts, not generics.


    Having said that, I do think that there you have raised an interesting point that some work might need to be done on the whole reflection side of generics. Anyway, I've got a clustering config to set-up, and I think we're about done this to death. Cya.

    /david
  61. Hi Shai,

    >
    > >I'm surprised you don't agree with me that the casting is a bad idea.
    >
    > Oh, I do think it is a bad idea - if it being done by user (e.g. casting
    >collection 'get' results). If it is checked by, and then added by, the
    >compiler, then I don't see it as a problem.

    I was refering to casting a generic collection to a regular collection.
    Generic folk are usually very much against casting (which usually doesn't cause
    much damage in Java) this is a case where damage is REALLY caused by a cast
    operation.
     
    > >That is done by subclassing and you see within the stack trace the specific
    > > element that changed the contract. Furthermore the API documentation will
    > > usually indicate the change of contract: If you have a NumberList then the
    > > API will mention that. You will have to invoke new somewhere.

    >
    > Yep - that's fine. Perfectly good approach.
    >
    > One problem: How do you then pass your custom collection to these libraries
    >that you say you need to use?!!! The only ways are

    I never said that the NumberList hid the Collection within it. IMO a NumberList
    can implement the collection interface and fail in a similar way to generics
    (since it breaks the contract as well).

    However:
    1. This is something I know about since I have to create the NumberList in order
    to do this.
    2. I will see the NumberList class in the stack trace and know who to blame.
    3. This contract change, affects me and my code ALONE, this is not a wide
    sweeping change. No one will be forced to use this list unless they use my
    library.

    > Either way you're stuffed - bottom line is your code and the library are
    >trying to do different things with the data. Like I said (ages ago), the
    >problem is with conflicting contracts, not generics.

    As I said, HUGE difference.
    Theres bad code in Libraries and then there is the language that should be
    squeeky clean.

    > Having said that, I do think that there you have raised an interesting point
    >that some work might need to be done on the whole reflection side of generics.
    >Anyway, I've got a clustering config to set-up, and I think we're about done
    >this to death. Cya.

    I have to agree, I have a delivery deadline as well and I think you see my point
    at least in general. I hope you do agree with me eventually that generics can't
    be just a small compiler change but if at all be a more serious robust change.

    Hopefully when generics start failing for people google will prove I did
    everything to stop it from happening ;)
  62. Prefer not to work for Shai[ Go to top ]

    Given the non-provisional way that Shai states his opinions, I would prefer not to work for him. And given that I disagree with his pontification regarding enums, I rather doubt I'd be given a chance. Suffice to say, however, that if he were working for me (or "under me" as he so patronizingly put it), I would not fire him for his obtuseness, because I believe that even the most closed-minded person can be reformed.

    Enums have the advantage over simple integers that the compiler catches certain errors that most of us, other than Shai, commit from time to time (and seeing the misspellings in his post, I suspect that even Shai makes a typo now and then).

    As well, the "objects pretending to be ENUMs" are a concise idiom for constructing a set of objects as if building a table.

    public class EnumLike {
      private EnumLike( int i1, String s2, ..., Border oN ){ ... }

      static public EnumLike Wash( 0, "Washington", ..., new EmptyBorder() );
      static public EnumLike Adams( 13, "Adams", ..., new BeveledBorder() );
      ...
      static public EnumLike Bush( -10, "Bush", ..., new EtcBorder() );
    }

    This gives us the ability to refer to well-known static object references (e.g. EnumLike.Wash, EnumLike.Adams, etc.) and all of the particulars of a particular aspect are retrievable from any of those objects. The alternative is to put these objects in a Map and use a different constant (probably a string, to retrieve the object of interest).

    Map NoEnums;
    NoEnums.put( "Washington", new NoEnum( 0, ..., new EmptyBorder() ) );
    NoEnums.put( "Adams", new NoEnum( 13, ..., new BeveledBorder() ) );
    NoEnums.get( "Washington" );

    I just don't see what's wrong with the "EnumLike" idiom and I admire its concision.
  63. Given the non-provisional way that Shai states his opinions, I would prefer not to work for him.

    >And given that I disagree with his pontification regarding enums, I rather doubt I'd be given a
    >chance. Suffice to say, however, that if he were working for me (or "under me" as he so
    >patronizingly put it), I would not fire him for his obtuseness, because I believe that even the most
    >closed-minded person can be reformed.


    Somehow we will manage without you.
    Programming is teamwork. If a team doesn't share a unified vision (usually in the form of a
    strong leader) a team will fail. Every single project I lead finished ahead of schedule under budget
    and with high quality. How many people here can say that? I'm a tough person to work for, but I
    do have the time to explain everything (as indication check the number of posts I bothered to
    place here), but if a person won't agree with me or worse if he tries to sneak in code that is
    not quality code... That person will be fired.

    Regarding the use of the term "under me", some of the people I manage are not employees of
    the company since we do outsourcing work and so I am not their boss but I do manage them.
    Please feal free to suggest a different term to indicate that I am not the boss yet have
    responsibility for their work (under my supervision?).
    It seems to me that you have a personal problem with my approach, frankly I couldn't care less.
    I have people standing in line to work for me in projects and my reputation is tough but
    fair, if you play by my rules.
     
    > Enums have the advantage over simple integers that the compiler catches certain errors that
    >most of us, other than Shai, commit from time to time (and seeing the misspellings in his post, I
    >suspect that even Shai makes a typo now and then).


    1. English is not my native language and I never lived in an English speaking country. I think I'm
    doing rather well with the spelling mistakes and grammer all things considered.
    2. I never said I don't have bugs/typos or coding mistakes.

    I did say that ENUM's are redundant and that using integers as ENUM's is just as bad!!!
    If you would have bothered to read my posts I never said anywhere or gave any example
    that would contain a hardcoded integer number, no room for typos of the type that ENUM's
    can fix.
     
    That if why you probably will never get a chance of working here, opening your flame thrower
    rather than trying to understand a different view. Unlike you while my opinions are firm and
    I apply them religiously, I didn't aim to insult anyone personally but tried to politly explain.

    > As well, the "objects pretending to be ENUMs" are a concise idiom for constructing a set of
    >objects as if building a table.


    I never would use anything like this example again you didn't bother to read my
    other posts or understand.

    check out http://www.theserverside.com/home/thread.jsp?thread_id=18791&article_count=107#79588

    ENUM's are a solution for a problem that shouldn't exist in the first place, the application should
    handle these problems with polymorphisem and storage solutions.
    Give me a single "real" problem that requires ENUM's and cannot be solved in a better
    way (where better is defined in terms of generic, dynamic, performance, code size).
    There isn't such a problem, except for manufactured problems where ENUM's already exist.
  64. Somehow we will manage without you.

    Of course you will, but I think it presumptuous to aver that you will manage better without the ideas of those who disagree with you from time to time? And, by the way, the janitor in our office manages without my help, too.

    > Programming is teamwork. If a team doesn't share a
    > unified vision (usually in the form of a strong leader)
    > a team will fail.
    A team needs both a strong and a wise leader and a wise person knows not to presume that he always knows best.

    > Every single project I lead finished ahead of schedule
    > under budget and with high quality. How many people here
    > can say that?
    Then you obviously haven't worked for some of the jerks I've worked for. There is no reasonable schedule that could not be made impossible by truncating the time required to complete it. When one works for people with no understanding of software development, one learns to be dismissive of the arbitrary deadlines they sometimes create. In my second job (back in 1981) the salespeople would promise programs that no one had ever even heard of, much less spec'd out, and we were told to complete the job in X months (and this was Z80 assembly!). It can be done, but it's usually not pretty.

    My point is, if you have always come in under budget, it is due in part to your brilliance (I mean that sincerely) and in part because you were given the resources. And sometimes people fail to make their deadlines (or make them only by working too much overtime) because the schedule/budget was unreasonable. And for that reason, your boast about your past successes paints only part of the picture. It does not prove your point that your strong leadership (or what I characterized as closed-mindedness) accounts for your success. You may be right, but you have failed to prove that you are right.

    And, of course, there is no need to do so here. I will stipulate that you sound very successful. But this does not, nor will it ever, validate your approach to SD mgt. I've worked for people like you (dare I say, dictatorial) and I've worked for managers who let big projects spin out of control. I have come to prefer working for someone who balances the need to control with the need to delegate responsibility and accept the diverse talents of others.

    > but if a person won't agree with me or worse
    > if he tries to sneak in code that is
    > not quality code... That person will be fired.
    Well, I doubt anyone would suggest that insubordination be tolerated, however, I will argue that even a brilliant person can be wrong from time to time. In fact, I think you are wrong regarding enums. And I would hate to have you overruling me on this because of your own sense of what's best, because:
      a) it's not that critical -- divergence on this issue would, at least sometimes, not cause the kind of unmanageability you suggest.
      b) intelligent people should be allow to disagree -- to forbid dissent is invalidating to the intelligence and experience of one's co-workers.

    > Regarding the use of the term "under me"...
    Since English is not your native language, you are perhaps less sensitive to the connotations of the particular phrase you chose. There's nothing wrong with the term "under" in this case, but it does tend to amplify the notion that you are not only supervising your employees, but are above them, that is, superior to them. My boss is not my better. I am his subordinate, but not his subject.

    > It seems to me that you have a personal problem
    > with my approach, frankly I couldn't care less.
    Well, if I worked for you it would be my personal problem. Since this is merely an online discussion, it doesn't represent a problem for me at all. The only problem here is that of trying to clearly express our views (and that doesn't seem to be much of a problem for either of us). And, yes, if I worked for you I would probably hate it. But you would never know, because part of being a good employee is hiding one's contempt for a person who has control over one's life and little regard for one's livelihood.

    > I have people standing in line to work for me in projects
    > and my reputation is tough but fair, if you play by my rules.
    And that proves, what exactly? Your point about firing people -- your point -- was intended to add weight to your opinion about the technical issues of this thread. It does not do that. And that is my point.

    Besides, where do you work? Some poor third world country? People do not choose to work for people like you when they have a choice.

    It is irrelevant that I have no problem finding a job, nor how long I have worked, nor the various satisfied employers who would recommend me. It adds no weight to my considered opinion that enums are not a bad thing in every case. I don't try to bully people into agreeing with me.

    And I think that truly strong leaders realize that.

    > 1. English is not my native language and
    > I never lived in an English speaking country.
    > I think I'm doing rather well with the spelling
    > mistakes and grammer all things considered.
    Ah, so quick to forgive his own foible and even quicker to condemn others for the mistake of disagreeing with him. I have worked with many non-native English speakers and it truly is not an issue (ask my Ukrainian wife). Hypocrisy bothers me. I suppose that's another of my personal problems: abhorrence of hypocrisy.

    > 2. I never said I don't have bugs/typos or coding mistakes.
    No, and I do understand your main point that it's a bad idea, as a rule, to substitute an enumerated type for a class type. For example, if we had a program that referenced 4 identical printers, that differed only in their network name, it would be reasonable to put these names in a String array. It would be folly to create separate classes for these printers and to require that, with each new printer, we must create a new class. However, if one printer were for barcodes, another a character-only line printer, still another a laser printer and the fourth a color printer, it would be folly to create a single Printer class containing an enumerated type to distinguish them.

    // Bad idea
    static final int PR_BARCODE = 0;
    static final int PR_LINE = 1;
    static final int PR_BWLASER = 2;
    static final int PR_COLOR = 3;
    class Printer {
      int type;
      void print()
      {
        switch( type )
        {
         ...
        }
      }
    }

    Changing this int to an enum is only slightly better -- BUT it is better. Still, I take your point that subclassing would help here. We would prefer the Printer class contain an abstract print() method. In such a case, the mechanism of virtual functions eliminates the need for the switch statement. Each subclass implements its own version of the print() method. Common functionality ends up in the superclass. Differentiation resides in the subclasses.

    However, if the ONLY method in the subclass was
      String getName(){ return "Bob's Printer"; }
    I'd have a hard time justifying the expense of loading the class and using the virtual function mechanism.
      String[] sPrinterNames = { "Bob's Printer", "Shai's Printer", ... };
    seems more appropriate. Even a switch statement seems better to me:
       switch( type )
       {
         case BOB: return "Bob's Printer";
       etc.


    Experience teaches us when to subclass and when to tabularize. I reject the doctrine that forbids tables, but then I'm not very religious to begin with.

    Going further, we are not always in control of every interface we design. In fact, there are many situations where one must interface with external libraries which demand that we use magic integer values. Any Windows programmer is familiar with this situation. Surely, we can accept enumerated types to substitute for these constants. Color constants are another case. Isn't Color.RED clearer and more type-safe than 0xff0000? Would you not concede that enums are an improvement over final ints when dealing with native and legacy software, as well as with firmware?

    At its core, what we're debating here is where type information shall be located. Must it always be located in the class hierarchy? Is there no other instance where we would choose to manage our types manually?

    I would state emphatically yes, there are greater than zero times where this is appropriate. You seem to be stating, just as emphatically, that there is never (other than the unavoidable native/legacy/firmware instances) EVER any justification for managing types manually. Sometimes I admire certainty, but this is not one of those times.

    > That if why you probably will never get a chance
    > of working here, opening your flame thrower
    > rather than trying to understand a different view.
    Now if this isn't the pot calling the kettle black. Which of us is really the more rigid in his thinking? Answer honestly now. You are the one suggesting that there is NO instance in which enums are useful. If you really believe that you can eliminate the need to interface with hard-coded integer values, then you must have next to no real world experience (and I don't believe that).

    > Unlike you while my opinions are firm and I apply
    > them religiously, I didn't aim to insult anyone
    > personally but tried to polit[e]ly explain.
    Is it insulting to suggest that I would prefer not to work with you? Did I not state my belief that even people with a closed-mind can be reformed? Perhaps it was over the top to characterize as obtuse your firm and absolute stance against something that many others value. It is rather a harsh word and, since we are not known to one another, it was impolite. But not inaccurate.

    Obtuse can mean "insensitive", and you seem that to me. It can also mean slow to perceive, and here again, your vituperative attacks upon a technique that others have employed profitably seemed to demonstrate a slowness to realize the value of the technique.

    I did not find your comment that you would fire a person for using enums to be very polite. Have you ever been out of work? Can you imagine the distress that would bring to such a person? And you would do this to somebody over a disagreement over a miniscule element of design? What if someone were to read your otherwise erudite comments and take you seriously? "Show of hands, people: Who would choose to work under these circumstances?".

    > ENUM's are a solution for a problem that shouldn't exist in the first place

      a) perhaps these problems shouldn't exist, but they do
      b) such solutions are often more concise and efficient than the alternative.

    > the application should handle these problems
    > with polymorphism and storage solutions.
    "May" handle these problems, not "should", not "must". It is impolite to state things unprovisionally. One convinces by dint of reason, not by demand. Better to coax one's readers into agreeing with you than to insist that they agree.

    Let's examine polymorphism (although, I think inheritence provides you with a stronger argument). Are these the alternatives?

    class foo {
      // Alternative 1
      // let A,B & C be legal enumerated values of the type variable.
      void method( enum type )
      {
         switch( type )
         {
           case A: methodA(); break;
           case B: methodB(); break;
           case C: methodC(); break;
         }
      }

      // Alternative 2
      method( ClassA a ){ }
      method( ClassB b ){ }
      method( ClassC c ){ }
    }

    It's impossible to state which of these solutions is better. One must know whether or not there are other data related to the types (data which are both relevant and available at the time the method is evoked). If I happen to have 3 types of fully constructed objects, then yes, polymorphism is nice and ever so slightly more efficient than the switch statement (because the method address is indexed -- a quick lookup and jump -- rather than a series of comparisons and branches).

    But what if the type corresponds to a user's choice? Imagine a radio button in a dialog in which a customer selects which method he prefers to be contacted: email, phone, fax? Somewhere I will store each of these pieces of data, but not when I ask him to choose. And someday we may use this fact to generate an email, phone call or fax, but not today -- not when the user clicks "Okay" on the dialog box. Indeed, the GUI choice we solicit may not need to persist, but may have a lifetime shorter than the current "session". Must I store this choice as a class? Is there no reason to store this "type" as a simple integer (or, better yet, a typesafe enum!)?

    > Give me a single "real" problem that requires
    > ENUM's and cannot be solved in a better
    > way (where better is defined in terms of
    > generic, dynamic, performance, code size).
    Well, you give it yourself. Your Airplane class, for example, would be silly if the only distinguishing characteristic between airplanes was its type (or, as in my Printer example, its name).

    My rule of thumb is to attempt to collect the distinguishing aspects of varying "types of instances" (I'm purposely avoiding the use of the term class) until a class is required. A class is required when these instances need to contain not just data that can be stored in a table, but behavior (code) as well (and even then, when the behavior is trivial compared to the larger body of common behavior, or when not all instances require distinct behavior, I'm tempted to (gulp) keep a type variable).

    As for performance, type variables are usually going to be more efficient. Consider how efficient it is to define constant integers and make occasional comparisons to an integer value generated by an event external to our class (or database lookup or whatever). This compares favorably to the cost of loading just one other class (with the security checks etc). It's a negligible difference, but there had better be a reason for loading that class and perhaps constructing an object of its type beyond the elimination of a switch statement.

    Let's consider the 2nd example you give in your response to Valentin...

    class MyObject {
       public void myFunction(Enum param) {
          switch(param) {
             // this is a huge bottleneck in the project
             // since this might grow very large causing
             // both performance overhead and the need
             // for multiple developers to work on a single
             // large method
          }
       }
    }

    The key word here is "might". Such a switch statement might grow very large, but in many instances it will be known with near absolute certainty to remain small. Must I abandon the obvious and simple switch statement to satisfy a doctrinaire design technique? I must if I want to work for you, apparently.

    > A better way is to split this type of functionality to
    > multiple methods and classes.

    You see, this is the kind of absolute, non-provisional statement that gets my goat. Sometimes it is better to invent classes and invoke virtual methods. Sometimes. Not always.

    Okay, now for your 3rd example...

    >>> 3. You need to perform code according to a numeric value
    and have a single entry point.

    public class LoadFile {
       private void loadObjectFromXMLData(int value) {
         switch(value) {
            case FIRST_TYPE:
               // perform code
         }
       }
    }

    should be written as a map lookup
    public class LoadFile {
       private void loadObjectFromXMLData(int value) {
         ((Runnable)actionMap.get(new Integer(value))).run();
       }
    }
    <
    Now this one takes the cake. Do yourself a favor and next time you're debugging code (I assume you still have to do that, sometimes managers move beyond this and lose touch with the vagaries of the tasks assigned to people "under" them). Do yourself a favor and step into the get() routine of, say, HashMap. Watch as it computes the hash value of the Integer value (and don't forget that the Integer object references the int value indirectly and generates a reference which has to be managed for later garbage collection). Watch as it runs through the for loop looking for a match. This will not, under ANY circumstances result in significant performance boost -- and for sufficiently small sets of enumerated values, the switch statement will win the race hands down (and int's may be stored on the stack and are never separately garbage collected).

    > While this is just as verbose as a switch statement, it
    > has the advantage of being dynamically extensible, and
    > easier to extend as a part of an API.
    The static solution has the advantage of being determinate and anybody who debugs on a regular basis can appreciate the advantage of determinacy for debugging. One can set a breakpoint on a case, one cannot do so on a get() -- well, you can, but then you get to enjoy the trip through the lookup process on your way to the execution of the run() method.

    But I suppose your suggesting that each case is replaced by a unique class whose sole purpose is to encapsulate the behavior of the case block. I guess I find this approach more verbose. Even though I have used this wherever necessary, I would hardly suggest that it was the only acceptable approach! And to do so for the Runnable example you give (admittedly, contrived for its simplicity, so it can be forgiven for its simplicity) is preposterous.

    Moreover, the switch statement is encapsulated, the actionMap solution could potentially be spread throughout the source code (potentially, I didn't say it would be done intentionally). In fact, one could implement the Runnable interface in any library, including those for which you have no source code and for which you haven't a clue as to its side effects. Obviously, you would attempt to eliminate this problem by restricting access to the actionMap (you would restrict access to the actionMap, wouldn't you?).

    Please, I beg you. Abandon your miscreant creed. You will not go to hell for using a switch statement. I won't go so far as to suggest that example 3 is lunacy, but it is certainly bizarre in the face of any simple set of enumerated values -- which most are! Each subsequent invocation of this method could cause a new class to be loaded -- how is that better than a handful of branches?

    So, let me say this politely, you have a long way to go before you have PROVEN your point and I feel sorry for anybody who actually gets fired for disagreeing with you. In fact, to recap my original point, I feel sorry for anybody who has to work under that Draconian threat.
  65. Somehow we will manage without you.

    > Of course you will, but I think it presumptuous to aver that you will manage
    >better without the ideas of those who disagree with you from time to time?

    I specifically said I am always open to listen, otherwise we wouldn't have this
    conversation would we? I read every single word you have written, yet people
    need to convince me with facts not religions or habits!
    That being said, once a decision is made then it should either be completely
    reveresed or completely followed by everyone in the team. If we try to play
    a different game and everyone has a methodology of its own the team fragments.
    Here we play to win, and we do, the only way to do this is together. If a team
    member disagrees with me and remains unconvinced then he would probably prefer
    working in another team anyway rather than working for me where he will have to
    align himself to the rest of the team.
    While I can't force everyone to code exactly like me, I try to bring them as
    close as possible to this goal. This produces huge code bases, that look as
    if they were written by a single person, heavily documented and consistent in
    their basic concepts.
    The code is immediately obvious as if I myself wrote it, since it is so
    consistent.

    >And, by the way, the janitor in our office manages without my help, too.

    Again, with degrading remarks. When you have nothing clever to say you
    choose to resort to puns supposedly on my expense rather than an actual
    argument.

    > > Programming is teamwork. If a team doesn't share a
    > > unified vision (usually in the form of a strong leader)
    > > a team will fail.
    > A team needs both a strong and a wise leader and a wise person knows not to
    >presume that he always knows best.

    I never said I know best. I am more experienced in the field than most.
    A fresh mind provides intriguing questions and we should always question what
    we know as facts. That is why I sit down with every new member and convince
    them. They try to convince me, so far I remain unconvinced while every single
    member of any team I lead (quite a few people) is convinced!
    Anyway again with the remarks supposed to attack me personally, would I even
    bother writing back for every comment you made if I was as you try to present
    me? I'd love to flame you back right now, since you arrogantly assume about
    a person you have no way of knowing? How closed minded is that?
     
    > > Every single project I lead finished ahead of schedule
    > > under budget and with high quality. How many people here
    > > can say that?
    > Then you obviously haven't worked for some of the jerks I've worked for.
    >There is no reasonable schedule that could not be made impossible by truncating
    >the time required to complete it. When one works for people with no
    >understanding of software development, one learns to be dismissive of the
    >arbitrary deadlines they sometimes create. In my second job (back in 1981) the
    >salespeople would promise programs that no one had ever even heard of, much
    >less spec'd out, and we were told to complete the job in X months (and this was
    >Z80 assembly!). It can be done, but it's usually not pretty.

    I never made people work all night or extra hours and projects run smoothly. I
    won't accept a project we can't complete in time. To do this I need total
    controll, both over the team so they put their resources in the right place
    and over the customer contract.
    Thats another perk of working for my team, the job gets done and while the
    stress is heavy at first to learn a new way of thinking, once that is done
    everything is easy sailing.

    The problem with your managers was that they weren't software developers, I am
    so when I sit with a customer I know every person on my team and his exact
    ability. I sit down and code with every person here!
     
    > My point is, if you have always come in under budget, it is due in part to
    >your brilliance (I mean that sincerely) and in part because you were given the
    >resources. And sometimes people fail to make their deadlines (or make them
    >only by working too much overtime) because the schedule/budget was
    >unreasonable. And for that reason, your boast about your past successes paints
    >only part of the picture. It does not prove your point that your strong
    >leadership (or what I characterized as closed-mindedness) accounts for your
    >success. You may be right, but you have failed to prove that you are right.

    Thanks, but no it doesn't prove the point. Its a part of a big picture.
    Since I own the company I work for I am the manager and team lead for
    the larger projects. You could say that my management skills (as in assigning resources) outway my team leader skills, but I disagree. They are a single
    package.
    I worked for many team leaders before, those that had the hands on approach
    where they knew every line of code always ran the project better. Having a
    single team work as that a team, is something I never saw until I became a
    team leader myself. This is just not done in other companies because the
    managers aren't all technical or simply don't have time to code.

    Since we deliver source code to some of our customers our release is much more
    complicated than most projects, we need to make sure that the code we deliver
    is up to the strict standards and our reputation. That makes our requirement
    for strict management and consistency even more essential.
     
    > And, of course, there is no need to do so here. I will stipulate that you
    >sound very successful. But this does not, nor will it ever, validate your
    >approach to SD mgt. I've worked for people like you (dare I say, dictatorial)
    >and I've worked for managers who let big projects spin out of control. I have
    >come to prefer working for someone who balances the need to control with the
    >need to delegate responsibility and accept the diverse talents of others.

    I can live with that, I recently fired a person who had a great deal of
    experience because we both kept fighting over everything. It started out as
    discussions turned to arguments and eventually he did what he wanted regardless.

    The way I see it, is that he had already formed ideas of his own and was
    unwilling to merge them with mine. Frankly I think people I trained who finished
    colege 1 year ago are better programmers than him because they aren't stuck
    like him in the way he learned 10 years ago.

    I think every project needs one direction, since you said these managers weren't
    technical then you naturally needed to take the technical lead but needed a
    manager strong enough to take the management lead (which you didn't want).
    A project doesn't need two heads, that only leads to trouble. A project needs
    consistency, maybe I'm too rough for some of the employees but they learn
    more here than they ever did in college. I bring them into my mind and teach
    them the way I think and solve design problems.
     
    > > but if a person won't agree with me or worse
    > > if he tries to sneak in code that is
    > > not quality code... That person will be fired.
    > Well, I doubt anyone would suggest that insubordination be tolerated, however,
    >I will argue that even a brilliant person can be wrong from time to time. In
    >fact, I think you are wrong regarding enums. And I would hate to have you
    >overruling me on this because of your own sense of what's best, because:
    > a) it's not that critical -- divergence on this issue would, at least
    >sometimes, not cause the kind of unmanageability you suggest.
    > b) intelligent people should be allow to disagree -- to forbid dissent is
    >invalidating to the intelligence and experience of one's co-workers.

    I allow disagreement when it comes to conference room issues, but when we sit
    down to code there is no room for that.
    Feal free to convince me of the need for ENUM's as practically every developer
    I ever hired tried to. If you make a single factual claim I can't rebuttle then
    I will allow it to my team members. This has been my policy all along, debate
    decide and do.

    I never overrule any employee who is interested in factual debate and reasoning.
    I don't ever "force" someone to use my methodology, but if he doesn't then he
    isn't a part of a team. I do have a problem with "briliant" people, they can
    create amazing things, but then the steps needed to turn that messy code in
    to an actuall working product far outweight the benefit. There was a guy I know
    (briliant) who wrote an amazing module we needed (I wasn't a team leader then),
    no indentation/comments whatsoever. Since it didn't work correctly fixing it cost so much... I doubt it was worth it (yes I know there are tools to indent).
    I had a problem not so much with briliant people, but with primadonnas who
    know they are briliant and are unwilling to become a part of a team. IMO they
    should be made managers on their own, since they obviously can't work under
    any strong manager.
     
    > > It seems to me that you have a personal problem
    > > with my approach, frankly I couldn't care less.
    > Well, if I worked for you it would be my personal problem. Since this is
    >merely an online discussion, it doesn't represent a problem for me at all. The
    >only problem here is that of trying to clearly express our views (and that
    >doesn't seem to be much of a problem for either of us). And, yes, if I worked
    >for you I would probably hate it. But you would never know, because part of
    >being a good employee is hiding one's contempt for a person who has control
    >over one's life and little regard for one's livelihood.

    While I don't need employees to like me, and while they are always friendly
    I know I will never really be their friend. Thats true for every boss.
    I doubt it if I will miss contempt, that employee I fired had it, I may not be
    sensitive but even a guy like myself can catch on to that.
    While firing people used to be hard, it became rather easy the moment I
    understood a few things:

    1. An employee who causes problems by either not going with regulations and
    refusing to discuss the issue to the full extent (or incapable of doing so)
    will cause the company damage in a project thus hurting our reputation.
    2. By harming the reputation our business will suffer.
    3. Business suffers I will have to fire people who don't deserve it and who
    did a great job.

    The way I see it, every person I fire is a problem, if I have any regret its
    not firing problematic people sooner. So you can say I have little regard for
    a persons livelyhood but IMO the opposit is true, I choose to be loyal to the
    livelyhood of the people who actually want to work for the team! I don't fire
    people to spite or to line my bank account with more cash.
     
    However I guess what your saying is that people will be afraid of firing if
    they disagree. Well clearly you never spoke to either my employees or myself.
    They always question me because they know they will get an ellabrorate answer
    as to why I want something in a particulart way. They often argue because they
    don't understand why I made a decision. They sometimes win these arguments!
    Sure, a newer employee might be intimidated to bring something up to me, so they
    will usually talk with their fellow employees who will either convince him or
    be convinced themselves, thus the more experienced employee who is more
    comfurtable approaching me will be the one to argue with me.

    Our office doesn't have doors or cubicals, everyone sits together in roughly
    similar settings (including myself). IMO all team members are equal in their
    treatment and sometimes the newest member can provide fresh insite into the
    problems at hand.

    > > I have people standing in line to work for me in projects
    > > and my reputation is tough but fair, if you play by my rules.
    > And that proves, what exactly? Your point about firing people -- your point
    >-- was intended to add weight to your opinion about the technical issues of
    >this thread. It does not do that. And that is my point.
    >
    > Besides, where do you work? Some poor third world country? People do not
    >choose to work for people like you when they have a choice.

    HAHAHAHAHA.
    Are you an American ;)
    You think everywhere else is third world ;)
    Yes we live in a desert thinking about blue jeans....
    This single paragraph has made everything worth while I almost wet myself.

    I live in Tel Aviv, and trust me, its nothing like any news report you ever
    saw or how you imagine it. Israel is about as western as the rest of Europe
    and up to the recession people made MORE money here than in the US!!!
    When I started off the shortage of employees was so great I had to hire people
    out of the second year of colege (who barely had 2 days a week for work).

    You need to get out of your shell a little bit and see the world, while yes
    there are poor regions everywhere in the world (even in the US) most of the
    world (even the third world of which we are not a part) has plenty of jobs
    for educated people.

    I remember US companies coming here looking to move work offshore to save costs
    and being surprised that the costs didn't go down...
     
    > It is irrelevant that I have no problem finding a job, nor how long I have
    >worked, nor the various satisfied employers who would recommend me. It adds no
    >weight to my considered opinion that enums are not a bad thing in every case.
    >I don't try to bully people into agreeing with me.

    I am a bully, intelectually. I am willing to pit my knowledge against anyone.
    You can say that I have the power to fire people which makes me a bully, but
    so does every team leader and manager. I never onced used (and never will) use
    it for someone who is willing to have a civil debate and reach a conclusion.
    A person can feel free to present a single factual example to convince me.

    > > 1. English is not my native language and
    > > I never lived in an English speaking country.
    > > I think I'm doing rather well with the spelling
    > > mistakes and grammer all things considered.
    > Ah, so quick to forgive his own foible and even quicker to condemn others for
    >the mistake of disagreeing with him. I have worked with many non-native
    >English speakers and it truly is not an issue (ask my Ukrainian wife).
    >Hypocrisy bothers me. I suppose that's another of my personal problems:
    >abhorrence of hypocrisy.

    Where was I a hypocrit?
    Again with the personal attacks?
    Anyway, I doubt your with has better spelling than I when typing in this speed?
    If so then cudos to her.
  66. [Snipped code we agree is bad]
    > Changing this int to an enum is only slightly better -- BUT it is better.
    >Still, I take your point that subclassing would help here. We would prefer the
    >Printer class contain an abstract print() method. In such a case, the
    >mechanism of virtual functions eliminates the need for the switch statement.
    >Each subclass implements its own version of the print() method. Common
    >functionality ends up in the superclass. Differentiation resides in the
    >subclasses.
    >
    > However, if the ONLY method in the subclass was
    > String getName(){ return "Bob's Printer"; }
    > I'd have a hard time justifying the expense of loading the class and using the
    >virtual function mechanism.
    > String[] sPrinterNames = { "Bob's Printer", "Shai's Printer", ... };
    > seems more appropriate. Even a switch statement seems better to me:
    > switch( type )
    > {
    > case BOB: return "Bob's Printer";
    > etc.

    Ok, if we were talking C++ then you might have had a minor point.
    Talking Java:

    1. If indeed it is only a name then I would simply create a printer with a
    string for name (but I realize this is not where you were going).

    2. Subclassing has a minor loading cost in Java, however this cost occurs
    only once and the gained performance is huge. Both Sun and IBM JIT's perform
    virtual method inlining which COMPLETELY removes the cost of a virtual method
    call making it as fast as a C++ inline method.

    3. Subclassing can be made by an annonimous class which won't cost in code
    more than a switch statement.

    Both of the approaches I suggested will be faster and require less code than
    ENUM's.

     
    > Experience teaches us when to subclass and when to tabularize. I reject the
    >doctrine that forbids tables, but then I'm not very religious to begin with.

    I use table, in the database where they belong.
    Yes experience teaches us everything, but there is never a case to using ENUM's.
    Not in an object oriented JITed language. You will only hinder the performance
    of the JIT.
     
    > Going further, we are not always in control of every interface we design. In
    >fact, there are many situations where one must interface with external
    >libraries which demand that we use magic integer values. Any Windows
    >programmer is familiar with this situation. Surely, we can accept enumerated
    >types to substitute for these constants. Color constants are another case.
    >Isn't Color.RED clearer and more type-safe than 0xff0000? Would you not
    >concede that enums are an improvement over final ints when dealing with native
    >and legacy software, as well as with firmware?

    To some degree yes, but the JNI interface can present an OO view and frankly
    I can't think of a single use I made of Color.ENUM rather I always extracted
    the color value from a database or a properties file. A real application does
    that. ENUM's won't be able to replace Color.RED since the RED int is an actual
    RGB value and an ENUM would have to map to that value.
     
    > At its core, what we're debating here is where type information shall be
    >located. Must it always be located in the class hierarchy? Is there no other
    >instance where we would choose to manage our types manually?

    No thats not we are debating. We are debating whether type information is needed
    for a patch that is no longer necessary in a modern OO language.
     
    > I would state emphatically yes, there are greater than zero times where this
    >is appropriate. You seem to be stating, just as emphatically, that there is
    >never (other than the unavoidable native/legacy/firmware instances) EVER any
    >justification for managing types manually. Sometimes I admire certainty, but
    >this is not one of those times.

    Certainty has nothing to do with it. Grep over the code I and my teams wrote
    in the past 5 years have a lot to do with it. No public static final variables
    to be seen anywhere.

    > > That if why you probably will never get a chance
    > > of working here, opening your flame thrower
    > > rather than trying to understand a different view.
    > Now if this isn't the pot calling the kettle black. Which of us is really the
    >more rigid in his thinking? Answer honestly now. You are the one suggesting
    >that there is NO instance in which enums are useful. If you really believe
    >that you can eliminate the need to interface with hard-coded integer values,
    >then you must have next to no real world experience (and I don't believe that).

    I have a strong rigid opinion which I am willing to base on facts which i
    have already put. You so far gave one bad example which I answered, your turn.
     
    > > Unlike you while my opinions are firm and I apply
    > > them religiously, I didn't aim to insult anyone
    > > personally but tried to polit[e]ly explain.
    > Is it insulting to suggest that I would prefer not to work with you? Did I
    >not state my belief that even people with a closed-mind can be reformed?
    >Perhaps it was over the top to characterize as obtuse your firm and absolute
    >stance against something that many others value. It is rather a harsh word
    >and, since we are not known to one another, it was impolite. But not
    >inaccurate.

    You didn't write "I prefer not to work for Shai" but rather recomended everyone
    avoid working for me. Thats an insult.
    I think you are the one with the closed mind who already formed an opinion about
    me and about (chuckle) my "third world country".
     
    > Obtuse can mean "insensitive", and you seem that to me. It can also mean slow
    >to perceive, and here again, your vituperative attacks upon a technique that
    >others have employed profitably seemed to demonstrate a slowness to realize the
    >value of the technique.

    I never said I was sensitive, I don't claim to be.
    I doubt I am slow to persive as I answered everything you have sent my way.
    And people have deployed applications with COBOL, the fact that people want or
    successfully use a technology does not make it appropriate to the Java languge.
     
    > I did not find your comment that you would fire a person for using enums to be
    >very polite. Have you ever been out of work? Can you imagine the distress

    No, I worked hard and discussed issues with everyone of my bosses. No one ever
    fired me. I think I know why they fired you though. I doubt a comment about
    firing an employee I hired is impolite and mentioning this has nothing to
    do with manners or netiquete, its just your own pet peeve.

    >that would bring to such a person? And you would do this to somebody over a
    >disagreement over a miniscule element of design? What if someone were to read
    >your otherwise erudite comments and take you seriously? "Show of hands,
    >people: Who would choose to work under these circumstances?".

    Having worked under cluless bosses I always loved working under someone with
    a strong sense of leadeship and technical ability. Sadly these cases were
    very rare.

    > > ENUM's are a solution for a problem that shouldn't exist in the first place
    >
    > a) perhaps these problems shouldn't exist, but they do
    > b) such solutions are often more concise and efficient than the alternative.

    I have yet to run into it once, give me a REAL example.

    > > the application should handle these problems
    > > with polymorphism and storage solutions.
    > "May" handle these problems, not "should", not "must". It is impolite to
    >state things unprovisionally. One convinces by dint of reason, not by demand.
    >Better to coax one's readers into agreeing with you than to insist that they
    >agree.

    Fine, don't agree, but give me something to debate. I gave several examples
    which you can either try to refute or try to give an example of your own instead
    you choose to attack me personally... Which one of us is closed minded.

    > Let's examine polymorphism (although, I think inheritence provides you with a
    >stronger argument). Are these the alternatives?
    >
    > class foo {
    > // Alternative 1
    > // let A,B & C be legal enumerated values of the type variable.
    > void method( enum type )
    > {
    > switch( type )
    > {
    > case A: methodA(); break;
    > case B: methodB(); break;
    > case C: methodC(); break;
    > }
    > }
    >
    > // Alternative 2
    > method( ClassA a ){ }
    > method( ClassB b ){ }
    > method( ClassC c ){ }
    > }
    >
    > It's impossible to state which of these solutions is better. One must know
    >whether or not there are other data related to the types (data which are both
    >relevant and available at the time the method is evoked). If I happen to have
    >3 types of fully constructed objects, then yes, polymorphism is nice and ever
    >so slightly more efficient than the switch statement (because the method
    >address is indexed -- a quick lookup and jump -- rather than a series of
    >comparisons and branches).

    Polymorphisem can be much faster thanks to JIT improvements.

    > But what if the type corresponds to a user's choice? Imagine a radio button
    >in a dialog in which a customer selects which method he prefers to be
    >contacted: email, phone, fax? Somewhere I will store each of these pieces of

    A user selection will need to be mapped to an ENUM? Thats redundant. Have
    a listener call the method directly.
     
    >data, but not when I ask him to choose. And someday we may use this fact to
    >generate an email, phone call or fax, but not today -- not when the user clicks
    >"Okay" on the dialog box. Indeed, the GUI choice we solicit may not need to
    >persist, but may have a lifetime shorter than the current "session". Must I
    >store this choice as a class? Is there no reason to store this "type" as a
    >simple integer (or, better yet, a typesafe enum!)?

    Your storage choice will need to be mapped to your storage topology. If you
    store to the database you can't store an ENUM and you will need to map it
    back and forth. If you store with serialization (which is bad in its own) then
    you hardly need an ENUM. Eitherway storing with ENUM's is mapping ENUM's back
    and forth which is redundant.

    > > Give me a single "real" problem that requires
    > > ENUM's and cannot be solved in a better
    > > way (where better is defined in terms of
    > > generic, dynamic, performance, code size).
    > Well, you give it yourself. Your Airplane class, for example, would be silly
    >if the only distinguishing characteristic between airplanes was its type (or,
    >as in my Printer example, its name).

    Thats untrue with new JIT's as I have demonstrated.
     
    > My rule of thumb is to attempt to collect the distinguishing aspects of
    >varying "types of instances" (I'm purposely avoiding the use of the term class)
    >until a class is required. A class is required when these instances need to
    >contain not just data that can be stored in a table, but behavior (code) as
    >well (and even then, when the behavior is trivial compared to the larger body
    >of common behavior, or when not all instances require distinct behavior, I'm
    >tempted to (gulp) keep a type variable).

    Thats a C++ approach, bigger classes. Java allows smaller classes and follows
    that approach there is nothing wrong with creating many classes.
     
    > As for performance, type variables are usually going to be more efficient.
    >Consider how efficient it is to define constant integers and make occasional
    >comparisons to an integer value generated by an event external to our class (or
    >database lookup or whatever). This compares favorably to the cost of loading
    >just one other class (with the security checks etc). It's a negligible
    >difference, but there had better be a reason for loading that class and perhaps
    >constructing an object of its type beyond the elimination of a switch
    >statement.

    The cost of loading a class happens one time, but the JIT takes away the cost
    completely which is not true regarding a switch statement which is much harder
    to optimize away.
     
    > Let's consider the 2nd example you give in your response to Valentin...
    >
    > class MyObject {
    > public void myFunction(Enum param) {
    > switch(param) {
    > // this is a huge bottleneck in the project
    > // since this might grow very large causing
    > // both performance overhead and the need
    > // for multiple developers to work on a single
    > // large method
    > }
    > }
    > }
    >
    > The key word here is "might". Such a switch statement might grow very large,
    >but in many instances it will be known with near absolute certainty to remain
    >small. Must I abandon the obvious and simple switch statement to satisfy a
    >doctrinaire design technique? I must if I want to work for you, apparently.

    Its not simpler than the other approaches once you wire your mind to work
    in an object oriented way. These other ways don't require extra code or
    cost in performance, why write something that might not scale when you
    can use the same energie to write something that will scale.
     
    > > A better way is to split this type of functionality to
    > > multiple methods and classes.
    >
    > You see, this is the kind of absolute, non-provisional statement that gets my
    >goat. Sometimes it is better to invent classes and invoke virtual methods.
    >Sometimes. Not always.

    There aren't many absolutes, I have yet to see a single use of ENUM that will
    give any advantage whatsoever. Up to that point in time there is a very strong
    reason for me to assume that it is unnecessary. Since many people tried to
    convince me and failed this has turned to an absolute, so far you are doint very
    badly as a debate, people came up with much better examples.
     
    > Okay, now for your 3rd example...
    >
    > >>> 3. You need to perform code according to a numeric value
    > and have a single entry point.
    >
    > public class LoadFile {
    > private void loadObjectFromXMLData(int value) {
    > switch(value) {
    > case FIRST_TYPE:
    > // perform code
    > }
    > }
    > }
    >
    > should be written as a map lookup
    > public class LoadFile {
    > private void loadObjectFromXMLData(int value) {
    > ((Runnable)actionMap.get(new Integer(value))).run();
    > }
    > }
    > <>
    > Now this one takes the cake. Do yourself a favor and next time you're
    >debugging code (I assume you still have to do that, sometimes managers move
    >beyond this and lose touch with the vagaries of the tasks assigned to people
    >"under" them). Do yourself a favor and step into the get() routine of, say,
    >HashMap. Watch as it computes the hash value of the Integer value (and don't
    >forget that the Integer object references the int value indirectly and
    >generates a reference which has to be managed for later garbage collection).
    >Watch as it runs through the for loop looking for a match. This will not,
    >under ANY circumstances result in significant performance boost -- and for
    >sufficiently small sets of enumerated values, the switch statement will win the
    >race hands down (and int's may be stored on the stack and are never separately
    >garbage collected).

    This is mostly removed by a smart JIT. Integer is final and the JIT has special
    treatment for the String/Number classes. The map lookup code is inlined into
    the method and the actual resulting assembler code should be as efficient if
    not more so as the switch statement. Better yet, if the keys are sequential you
    can avoid the map and use an array for the mapping and gain much better
    performance than that.
     
    > > While this is just as verbose as a switch statement, it
    > > has the advantage of being dynamically extensible, and
    > > easier to extend as a part of an API.
    > The static solution has the advantage of being determinate and anybody who
    >debugs on a regular basis can appreciate the advantage of determinacy for
    >debugging. One can set a breakpoint on a case, one cannot do so on a get() --
    >well, you can, but then you get to enjoy the trip through the lookup process on
    >your way to the execution of the run() method.

    You can set the breakpoint in the run() method just as you can on a particular
    case. There is no point in debugging a map implementation since it works
    perfectly, if you need to see the value the method received then you can break
    on the method itself and then on the apporiate runnable. Hardly trouble at all.
     
    > But I suppose your suggesting that each case is replaced by a unique class
    >whose sole purpose is to encapsulate the behavior of the case block. I guess I
    >find this approach more verbose. Even though I have used this wherever
    >necessary, I would hardly suggest that it was the only acceptable approach!
    >And to do so for the Runnable example you give (admittedly, contrived for its
    >simplicity, so it can be forgiven for its simplicity) is preposterous.

    I said that this is a simple example but I never claimed it was "the" solution.
    In fact I hardly use this solution myself, and usually settle for the first
    two solutions.
    You still haven't proven a single point.
    1. Its just as fast as a case statement depending on the type of JIT you use.
    2. Its the same amount of code when using inner classes.
    3. Its just as easy to debug.
    4. Its MORE generic and easier to extend.
     
    > Moreover, the switch statement is encapsulated, the actionMap solution could
    >potentially be spread throughout the source code (potentially, I didn't say it
    >would be done intentionally). In fact, one could implement the Runnable
    >interface in any library, including those for which you have no source code and
    >for which you haven't a clue as to its side effects. Obviously, you would
    >attempt to eliminate this problem by restricting access to the actionMap (you
    >would restrict access to the actionMap, wouldn't you?).

    I would restrict access to the action map for subclasses only via an add method.
    Dynamic code comes with a price of allowing bugs to come from all over the code.
    I said that the Map can scale if needed to be dynamic, I wouldn't expose it
    until the moment I need to expose it.
     
    > Please, I beg you. Abandon your miscreant creed. You will not go to hell for
    >using a switch statement. I won't go so far as to suggest that example 3 is
    >lunacy, but it is certainly bizarre in the face of any simple set of enumerated
    >values -- which most are! Each subsequent invocation of this method could
    >cause a new class to be loaded -- how is that better than a handful of
    >branches?

    No the new classes will be created on startup not on invocation...
     
    > So, let me say this politely, you have a long way to go before you have PROVEN
    >your point and I feel sorry for anybody who actually gets fired for disagreeing
    >with you. In fact, to recap my original point, I feel sorry for anybody who
    >has to work under that Draconian threat.

    You have a long way to go before you can PROVE your point.
    I wouldn't write what I feel about you, that would be impolite.
  67. Okay this thread is dead and unfortunately I can't email Shai Almog. But here is my 2 cents regarding enums. I will take TableModelEvent from Swing as an example:

    public class TableModelEvent extends java.util.EventObject
    {
        /** Identifies the addtion of new rows or columns. */
        public static final int INSERT = 1;
        /** Identifies a change to existing data. */
        public static final int UPDATE = 0;
        /** Identifies the removal of rows or columns. */
        public static final int DELETE = -1;

    // snip

        /**
         * Returns the type of event - one of: INSERT, UPDATE and DELETE.
         */
        public int getType() { return type; }
    }

    In the above code the type is an enum with a value of INSERT, UPDATE or DELETE. Enums help to ensure that a valid value is given and hides the underlying value. Now if I have code that listens to table model events I would have

    public void tableChanged(TableModelEvent e){
      int firstRow = e.getFirstRow();
      int lastRow = e.getLastRow();
      int col = e.getColumn();

      if(e.getType() == TableModelEvent.INSERT){
         System.out.println("Rows (" + firstRow + "," + lastRow
                                + ") were inserted");
      }else if(e.getType() == TableModelEvent.UPDATE){
         if(col == TableModelEvent.ALL_COLUMNS){
           System.out.println("Rows (" + firstRow + "," + lastRow
                                + ") were updated");
         }else{
           System.out.println("Cell (" + firstRow + "," + col + ") was updated");
         }
      }else if(e.getType() == TableModelEvent.DELETE){
         System.out.println("Rows (" + firstRow + "," + lastRow + ") were deleted");
      }
    }

    Now for your suggestions on how to avoid using enums.

    <Shai>
    1. If indeed it is only a name then I would simply create a printer with a
    string for name (but I realize this is not where you were going).
    </Shai>

    The above is using a property to separate between the different types of event. That type being an int. Using an enum type would be safer and makes it clearer. Eg. if getType() returned TableEventType then the compiler enforces it to be INSERT, UPDATE or DELETE.

    <Shai>
    2. Subclassing has a minor loading cost in Java, however this cost occurs
    only once and the gained performance is huge. Both Sun and IBM JIT's perform
    virtual method inlining which COMPLETELY removes the cost of a virtual method
    call making it as fast as a C++ inline method.
    </Shai>

    Using subclassing for event types you would have:

    public abstract class TableModelEvent{
      // same as TableModelEvent from swing but without type property
    }

    public class InsertTableModelEvent extends TableModelEvent{ }

    public class DeleteTableModelEvent extends TableModelEvent{ }

    public class UpdateTableModelEvent extends TableModelEvent{ }

    If I want to override a method in TableModelEvent to apply to all TableModelEvents then your out of luck, since you can't make the different types change which class they subclass from. Additionally, since Java only has single inheritance you don't allow TableModelEvent to be subclassed for other reasons.

    So in the case of TableModelEvent, using subclassing instead of enums reduces flexibility and increases the complexity (in construction logic and need to be aware of class hierarchy). Using inheritance for the above purpose also violates the Liskov Substitution Principle since table listeners are treating each table event differently.

    I would also like to point out that using polymorphism is the inverse of a switch statement (when used properly which is not the case above).

    OO approach:
    public void do(Thing t){
      t.do();
    }

    public class Type1 implements Thing{
      public void do(){ /* do stuff for type1 */ }
    }

    public class Type2 implements Thing{
      public void do(){ /* do stuff for type2 */ }
    }

    public class Type3 implements Thing{
      public void do(){ /* do stuff for type3 */ }
    }


    Procedural approach:
    public void do(Thing t){
      switch(t.type){
      case type1:
        // do stuff for type1
        break;
      case type2:
        // do stuff for type2
        break;
      case type3:
        // do stuff for type3
        break;
      }
    }
  68. Prefer not to work[ Go to top ]

    I've just re-read both Joshua's book and the enum proposal. Ability to add methods to enum constants seems even neater than a talking frog! :-)

    have fun,
    --VS.
  69. "1. ENUM's are the absolute worst. They make my blood boil and every
    programmer I see using them (in C++ as well) is fired on the spot.
    Programmers who try to use ENUM "alternatives" such as small classes
    or interger constants will never get promoted and need serious help
    in understanding object oriented design. No OO language needs ENUM's."

    Could you please elaborate? Do you use plain integer literals or perhaps a class for each value of the enum? I am aware of problems with both integer constants and enum classes, so there is all more reason to make them part of the language - to allow both more efficient and more robust implementation.

    Also, using symbolic names were considered a good practice since the beginning of computer programming (see Knuth's volume 1). "Integer constants" are the same as 'EQU' in assemblers, '#define' in C, 'const atype' in C++..., etc. I am confused...

    thanks,
    --VS.
  70. Valentin,
    there are several cases in which people use ENUM's, here are some
    examples:

    1. To indicate an attribute of an object (this code is somewhat
    C++ish since it relies on ENUM's being int's:

    class Aircraft {
      int type;

      private void doStuff() {
        if(type & F_15) {
           ....
        }
      }
    }

    This is real, I worked on a flight simulator that had a hard
    time since we needed to add an ENUM for each craft that completely
    botched the build everytime.
    A better solution, more extensible and efficient one is to have

    class Aircraft {
      public boolean isF15();

      private void doStuff() {
        if(isF15()) {
           ....
        }
      }
    }



    2. Another way to use ENUM's is as verbose parameters.
    The problem is that your code turns into a mess dealing
    with these ENUM's. So:

    class MyObject {
       public void myFunction(Enum param) {
          switch(param) {
             // this is a huge bottleneck in the project
             // since this might grow very large causing
             // both performance overhead and the need
             // for multiple developers to work on a single
             // large method
          }
       }
    }

    A better way is to split this type of functionality to
    multiple methods and classes.


    3. You need to perform code according to a numeric value
    and have a single entry point.

    public class LoadFile {
       private void loadObjectFromXMLData(int value) {
         switch(value) {
            case FIRST_TYPE:
               // perform code
         }
       }
    }

    should be written as a map lookup
    public class LoadFile {
       private void loadObjectFromXMLData(int value) {
         ((Runnable)actionMap.get(new Integer(value))).run();
       }
    }
    I just used runnable as a simple interface but obviously
    if you have more parameters you can use any type of interface.

    While this is just as verbose as a switch statement, it
    has the advantage of being dynamically extensible, and
    easier to extend as a part of an API.
  71. Hello Shai,

    thank you. Good examples. Some comments.

    >>> The 1st: This is not an enum.

    When it is down to logical '&', it is more like a bit set rather than an enum. In C++ a better alternative is to use bit fields. A line like

        if (jet && supersonic && engines==2) ...

    may compile into three (two in some cases) machine commands. In Java isYyyy() is a good alternative, only alas, I am afraid that the above and

        jet = 1;
        supersonic = 1;
        engines = 2;

    won't compile into a few bytes of native code (all three assignments may compile into a single instruction). Perhaps not important if you deal with only a few jets in a game, but it may be if you work with characters in a document.

    >>> The 2nd: this is just moving the responsibility up one level.

    Who is to decide which of the few methods to call? Of course if the constant is passed as the argument it may make sense; but what if we pass a uniform object, which has certain property relevant only to the callee?

    For example, jets should be process()-ed separately from turbo-props, but the caller isn't interested in what the internals of the process() method do. Why the caller should decide which one to call: processAJet() or processATurboProp()?

    (I suspect that it would be impossible to use class hierarchy inside process() to separate onces from the others, since multiple properties like that may need to be provided. Anyway, that would be just another way of encoding enums - with class hierarchies.)

    >>> The 3rd: Does not address the issue.

    This is more about how to get rid of the 'switch' statement rather than how to encode that 'value' parameter. The value needs to be provided by the caller anyway. Is it just '5' or Color.RED? Is it '3' or Calendar.APRIL?

    This is not so apparent when processing the data, but when generating the data, it becomes essential. That is, I'd rather use a symbolic constant or an enum to write (in about 100 different places):

        ... = new Fly(Fly.JET, Fly.CIVILIAN);

    than
        ... = new Fly(3,2);

    and enums just add more type-safety, for the once who mixes it like this:

        ... = new Fly(Fly.CIVILIAN, Fly.JET);

    As for the "getting rid of the switch" technique - you still need to set up the map. Is it done like this:

        actionMap.put(1, ...);
        actionMap.put(2, ...);

    or

        actionMap.put(Fly.TURBOPROP, ...);
        actionMap.put(Fly.JET, ...);

    ?

    And what happens with the code if the number is not in the map?..

    regards,
    --VS.

    PS. Ironically, in the language, which has no pointers one of the most frequent exceptions is 'NullPointerException', like in the following naive piece of code:

        if (request.getAttribute("seperate").equals("false")) ...

    :-|
  72. thank you. Good examples. Some comments.


    Thank you for a plesant discussion, last time I had this discussion was on
    the JL and it turned into a slight flamewar which was only resolved in private
    E-Mail (resolved with a disagreement though).
     
    > >>> The 1st: This is not an enum.
    >
    > When it is down to logical '&', it is more like a bit set rather than an enum. In C++ a better alternative is to use bit fields. A line like
    >
    > if (jet && supersonic && engines==2) ...
    >
    > may compile into three (two in some cases) machine commands. In Java isYyyy() is a good alternative, only alas, I am afraid that the above and
    >
    > jet = 1;
    > supersonic = 1;
    > engines = 2;
    >
    > won't compile into a few bytes of native code (all three assignments may compile into a single instruction). Perhaps not important if you deal with only a few jets in a game, but it may be if you work with characters in a document.


    I disagree, with JIT's this would work rather well. Since you hardcode return
    true within the overriden method you can get the advantages of virtual method
    inlining and have NO COST of evaluation and complete removal of the else code!!
    This means the JIT in this case can EASILY erase a completely redundant if.

    While this could potentially be done by a really inteligent JIT in the case of
    a bitwise & operation. I doubt this will even be the case.

    > >>> The 2nd: this is just moving the responsibility up one level.
    >
    > Who is to decide which of the few methods to call? Of course if the constant is passed as the argument it may make sense; but what if we pass a uniform object, which has certain property relevant only to the callee?
    >
    > For example, jets should be process()-ed separately from turbo-props, but the caller isn't interested in what the internals of the process() method do. Why the caller should decide which one to call: processAJet() or processATurboProp()?


    This example would fall into the 3rd example I gave. This case would indeed
    just move the switch bloat to a different method.


    > >>> The 3rd: Does not address the issue.
    >
    > This is more about how to get rid of the 'switch' statement rather than how to encode that 'value' parameter. The value needs to be provided by the caller anyway. Is it just '5' or Color.RED? Is it '3' or Calendar.APRIL?


    Why would you have a Calendar.APRIL?
    This is the exact use case of the second option, Calendar is widely regarded
    as one of the worst API's in Java.
     

    > This is not so apparent when processing the data, but when generating the data, it becomes essential. That is, I'd rather use a symbolic constant or an enum to write (in about 100 different places):
    >
    > ... = new Fly(Fly.JET, Fly.CIVILIAN);
    >
    > than
    > ... = new Fly(3,2);

    Me too, I would write Fly.createCivilianJet();

    > and enums just add more type-safety, for the once who mixes it like this:
    >
    > ... = new Fly(Fly.CIVILIAN, Fly.JET);

    All of the knowledge about fly should be within the class and related package
    protected interfaces. By using the ENUM/Constants you expose implementation
    detail. I don't mine if createCivilianJets() has hardcoded numbers within it
    since its only referenced within the class and is under control. Constants break
    the very notion of control. private constants are OK in my book though ;)

    > As for the "getting rid of the switch" technique - you still need to set up the map. Is it done like this:
    >
    > actionMap.put(1, ...);
    > actionMap.put(2, ...);
    >
    > or
    >
    > actionMap.put(Fly.TURBOPROP, ...);
    > actionMap.put(Fly.JET, ...);

    As I said this is just as verbose, however I can do it by

    protected void addMapedAction(String key, Runnable action);

    and then have subclasses register behavior which is what
    I refered to as the dynamic nature allowing us to redistribute
    the code. Better yet, the class names can be placed in a
    property file and loaded dynamically to allow extentions
    to your code... (we did this in many projects).

    > And what happens with the code if the number is not in the map?..

    I specifically wrote it to get a NullPointerException, which is what
    I usually want in this case. However sometimes I check for null before
    invoking if I'm interested in other functions.
     
    > PS. Ironically, in the language, which has no pointers one of the most frequent exceptions is 'NullPointerException', like in the following naive piece of code:
    >
    > if (request.getAttribute("seperate").equals("false")) ...

    Java has only pointers and no stack objects ;)
  73. Is it bad to have good ideas?[ Go to top ]

    This is not so apparent when processing the data, but when generating the data, it becomes essential. That is, I'd rather use a symbolic constant or an enum to write (in about 100 different places):

    >
    > ... = new Fly(Fly.JET, Fly.CIVILIAN);
    >
    > than
    > ... = new Fly(3,2);

    Me too, I would write Fly.createCivilianJet();

    > and enums just add more type-safety, for the once who mixes it like this:
    >
    > ... = new Fly(Fly.CIVILIAN, Fly.JET);

    This seems to be more of a sylistic difference. Personally, I wouldn't want to write several methods that all do the same thing and differ in such a way. Would you have completely different methods or would you have the "create" pass the ints to the constructor?

    What happens as you add plane types? Would you create more methods? Wouldn't this be a maintenance nightmare? Everytime you add or subject plane types you have to create or remove a method.

    I definitely don't like the static import for reasons of readability. As for the generics, even Blooch stated that he believes that 90% of the collections are used for String(and most likely objects of the same type), so I personally wouldn't mind a little less casting for such a small price.

    But I don't agree with your reasons for not having/using Enums. At best, I see a difference in style that you enforce on your subordinates(which is the bosses right, I guess), but I still haven't seen a reason that is compelling to me against taking a well worn, well used pattern, and easing our labors.

    Great discussion, though!!
  74. Is it bad to have good ideas?[ Go to top ]

    This seems to be more of a sylistic difference. Personally, I wouldn't want to

    >write several methods that all do the same thing and differ in such a way.
    >Would you have completely different methods or would you have the "create" pass
    >the ints to the constructor?

    This is way more than a stylistic difference.
    1. You have control over the point of entry for each use case.

    2. You can factor methods down to subclasses the moment the parent
    class becomes too big.

    With ENUM's you have the same problems but without a real solution, sure
    you can factor some of the huge switch statement to other methods/classes
    but then they are tightly coupled and need to know about each other. In
    a case of subclassing and adding a factory method we don't cement anything.
     
    > What happens as you add plane types? Would you create more methods? Wouldn't
    >this be a maintenance nightmare? Everytime you add or subject plane types you
    >have to create or remove a method.

    As I said, this can be easily factored into subclasses which is not the
    case for ENUM's.
     
    > I definitely don't like the static import for reasons of readability. As for
    >the generics, even Blooch stated that he believes that 90% of the collections
    >are used for String(and most likely objects of the same type), so I personally
    >wouldn't mind a little less casting for such a small price.

    I'll repeat my opinion about generics:
    "People expect great changes for genrics but frankly generics will make the
    really easy things (single type collections) very slightly simpler, while
    not making a difference to the complicated things (polimorphic collections).
    Furthermore the fact that a compatible implementation that actually works
    is technically impossible adds a level of complexity that makes the change
    completely impossible."
     
    Generics while maintaining compatability WON'T work!!!

    > But I don't agree with your reasons for not having/using Enums. At best, I see
    >a difference in style that you enforce on your subordinates(which is the bosses
    >right, I guess), but I still haven't seen a reason that is compelling to me
    >against taking a well worn, well used pattern, and easing our labors.

    I don't see a single way in which ENUM's ease your life other than using Java
    as C. As I demonstrated every problem solvable by ENUM's is solveable by OO
    code of roughly the same (or lower) complexity, which is both more generic,
    dynamic and has better performance (at least in potential, depending on JIT).
  75. Hello Shai,

    > I disagree, with JIT's this would work rather well. Since you hardcode
    > return true within the overriden method you can get the advantages of
    > virtual method inlining and have NO COST of evaluation and complete
    > removal of the else code!!
    > This means the JIT in this case can EASILY erase a completely redundant if.

    IMHO, hardly so if you scan thousands of different characters in a single loop... do you have more info about how it works?

    > >
    > > ... = new Fly(Fly.JET, Fly.CIVILIAN);
    > >
    > > than
    > > ... = new Fly(3,2);

    > Me too, I would write Fly.createCivilianJet();

    So, I have a form, which allows the user to register a plane. It has two drop downs: engine type and plane type:

        enum {glider, spring, pedal, prop, turboprop, turbofan, jet, rocket};
        enum {civilian, military, vintage};

    Questions:
        - which part of the code is responsible for converting codes into text?
        - which part of the code is responsible for parsing user input into engine type and plane type?
        - how do I map the two entered values to 24 createXxxxYyyy()?
        - how does a third-party method, e.g. sendEMailToRelevantAuthority(), determine if a plane is civilian or military?

    > Java has only pointers and no stack objects ;)

    Which is a pity, IMHO. Such thing as value objects (e.g. peers of primitive types) would greatly help to improve performance. E.g why can't we allocate a Complex or a Point on the stack, along all local ints and doubles? Well perhaps it might be possible to optimise it taking immutability in consideration?..

    thank you,
    --VS.
  76. \Sliouniaev\
    So, I have a form, which allows the user to register a plane. It has two drop downs: engine type and plane type:
        enum {glider, spring, pedal, prop, turboprop, turbofan, jet, rocket};
        enum {civilian, military, vintage};
    Questions:
        - which part of the code is responsible for converting codes into text?
        - which part of the code is responsible for parsing user input into engine type and plane type?
        - how do I map the two entered values to 24 createXxxxYyyy()?
        - how does a third-party method, e.g. sendEMailToRelevantAuthority(), determine if a plane is civilian or military?
    \Sliouniaev\

    This is a rather poor example of enum usage.

    A more typical example would be something like a 'state' variable in a state machine, an option variable, and things of that nature. As another poster mentioned, look at the instances in existing Java standard libraries that use integers, and you'll see more realistic examples. In cases like those, an enum would give you better type safety and not really cost much of anything. It's also useful if you happening to be using bitfields. The underlying code might need to break the enum safety and-ing and or-ing, but an API interface could provide something like:

        setFlag (Enum X)
        boolean flagIsSet (Enum X);

    \Sliouniaev\
    Which is a pity, IMHO. Such thing as value objects (e.g. peers of primitive types) would greatly help to improve performance. E.g why can't we allocate a Complex or a Point on the stack, along all local ints and doubles? Well perhaps it might be possible to optimise it taking immutability in consideration?..
    \Sliouniaev\

    I think a JIT can do this today BUT an optimizer generally won't do it if you pass a reference to an object to another method on another object. Once you go outside of the JITs current compilation scope, it can't know what that method is doing, and specifically can't know if you're holding a reference to the pased in object. E.G.

        Point point = Point (1, 5); // Assume this is stack allocated

        foo.doSomething (point);

    In the above example, you don't know if foo.doSomething() is going to try to hang on to that reference. If it did and you allocated it on the stack, then returned from the allocating method and the object was later dereferenced - wham!

    Returning local objects also brings up C++ bugaboos like temporaries and their lifetimes and copy constructors and the rest.

    I don't see how immutability applies - the problem is references and object lifetime.

    Also - keep in mind under the Java 1.4 allocator & GC system, heap allocation is really, really cheap. The only savings would be less garbage to collect, and the 1.4 GC is ridiculously fast on the new generation. This is little comfort to those who haven't yet gone to Java 1.4, but in time most will and will gain the benefits.

        -Mike
  77. \Spille\
    > ... It's also useful if you happening to be using bitfields.
    > The underlying code might need to break the enum safety
    > and-ing and or-ing, but an API interface could provide
    > something like:
    >
    > setFlag (Enum X)
    > boolean flagIsSet (Enum X);
    >
    \Spille\

    It is not an enum, it's a bit set. Set of possible values for a bit set is very much different from that of an enum. In addition, set of operations is completely different, too. I would not rather mix them together.

    \Spille\
    > Returning local objects also brings up C++ bugaboos like
    > temporaries and their lifetimes and copy constructors and
    > the rest.
    >
    > I don't see how immutability applies - the problem is
    > references and object lifetime.
    \Spille\

    If an object is immutable, you could return a copy of it the moment it goes out of local scope (stored in member data or retuned; it's ok to pass into another method).

    \Spille\
    > Also - keep in mind under the Java 1.4 allocator & GC system,
    > heap allocation is really, really cheap. The only savings would
    > be less garbage to collect, and the 1.4 GC is ridiculously fast
    \Spille\

    Perhaps. I also hope that it improves locality of reference to all of my complex numbers in rectangular matrixes when I multiply them. In FORTRAN and C that was ridiculosly cheap.

    regards,
    --VS.
  78. \Sliouniaev\
    It is not an enum, it's a bit set. Set of possible values for a bit set is very much different from that of an enum. In addition, set of operations is completely different, too. I would not rather mix them together.
    \Sliouniaev\

    It's a bitset in the hidden internals of the class. At the API level, it's an enum that enforces type safety and valid values. And such uses of enums in other languages is _not_ at all uncommon.

     \Sliouniaev\
    If an object is immutable, you could return a copy of it the moment it goes out of local scope (stored in member data or retuned; it's ok to pass into another method).
    \Sliouniaev\

    Assuming we don't want to get into the lifetime-of-tempoaries bugaboo of C++, then that "copy" is a heap allocation - in other words, you completely lose the benefit of the local object. Likewise - if you always pass in a copy when doing a member invocation, you again lose the value - you must do a heap allocation.

    The whole point of local stack objects is they're automatically "collected" when you pass out of its local scope. You're not generating garbage. The minute you introduce copy-the-object-to-the-heap, you've lost the whole point of the exercise.

    \Sliouniaev\
    [On java 1.4 GC..]
    Perhaps. I also hope that it improves locality of reference to all of my complex numbers in rectangular matrixes when I multiply them. In FORTRAN and C that was ridiculosly cheap.
    \Sliouniaev\

    No, this could potentially be slightly worse in Java 1.4, since objects can pretty quickly migrate through various generations (e.g. they physically move). And the array semantics of Java haven't changed either. But you can always manually index a single dimensional array as if it were multi-dimensional, so you're accessing a continugous space. In fact I'd be surprised if any heavily math intensive code wasn't already doing this.

        -Mike
  79. Bit fields are not enums[ Go to top ]

    It's a bitset in the hidden internals of the

    > class. At the API level, it's an enum that
    > enforces type safety and valid values.
    > And such uses of enums in other languages
    > is _not_ at all uncommon.

    Yes, right, unfortunately it is not uncommon.

    However if you look at the history of the thing, it started with #define-s for bit fields:

        #define PETROL 0x0001
        #define SPORTS 0x0010
        #define RACING 0x0020
        #define FAMILY 0x0030
        ...
        #define TYPE_MASK 0x01F0
        ...

        if ( (flags & TYPE_MASK) == FAMILY && (flags & PETROL)) ...

    then somebody thought "outside the box" and invented

        enum { PETROL=1, SPORTS=16, ... FAMILY, TYPE_MASK=496 }

    where a better way of using it is

        enum CarType { SPORTS, ... FAMILY }; // declare set of values

        class ... {
            int isPetrol:1;
            :3;
            CarType carType :5;
        };

    or better yet, allow the compiler to pack small enums into bit fields.

    There is no need to pack independent single- or small-bit variables into a single enum. Enum is a set of possible values for a single variable.

    Unfortunately, this slipped into C#, too, apparently because they wanted to have some independent variables packed into one int, but couldn't do the bit fields. Thinking inside the box again...

    regards,
    --VS.
  80. Bit fields are not enums[ Go to top ]

    \Sliouniaev\
    There is no need to pack independent single- or small-bit variables into a single enum. Enum is a set of possible values for a single variable.

    [...]

    Unfortunately, this slipped into C#, too, apparently because they wanted to have some independent variables packed into one int, but couldn't do the bit fields. Thinking inside the box again...
    \Sliouniaev\

    I see what you're getting at, but I think you're defining what an enum is in an overly-narrow way. And the value judgements of "thinking inside the box" and "thinking outside of the box" really aren't very useful here :-/

    You appear to be saying that adding a language feature for bitfields is better than using enums to achieve the same goal. I agree it adds some convenience - at the cost of even more language complexity, and some strange language rules (see the complete C and C++ rules on bitfields for details). Honestly, I don't see why you seem to dislike the concept of bitfields, and then start advocating use of bitfields (which is really a variant on the enum concept).

    My feeling is that enums add some convenience to the language, and a bit of additional type safety, with little added complexity to the language. I fail to see how this is a bad thing. And I personally prefer to use enums when doing bitfield-like operations, because often those bitfield values map to something external to the VM. Seeing the explicit value in an enum points to exactly what a value means. Using bitfields, you have to count how far into a bitfield a value is to try to figure out its ultimate value.

        -Mike
  81. Bit fields are not enums[ Go to top ]

    Very good points: external representation and adding complexity.

    I still find using bitwise ops to get at bitfield values a bit old fasioned (it is C, not even C++). It also exposes implementation of the object to the rest of the universe. Compare:

       MyFlags flags = new MyFlags(0xCABA);
       if (flags.canFly()) ...;

    with

       int flags = 0xBEDA;
       if ((flags & MyFlags.CANFLOAT) != 0) ...; // everywhere

    and (again, every time i need this value):

       int nEngines = flags.getNumEngines();
       int nEngines = (flags & MyFlags.ENGINES_MASK) >> MyFlags.ENGINES_SHIFT;

    I would keep enums as just a plain set of values for a single variable. The bit fields IMHO would be better done as an ordinary class (not enum), which does the bitwise bits inside itself, but packs and unpacks the bits to values via '{int|boolean} getXxx()' and '{void|MyEnum} setXxx()'.

    Oops, I just realised that an instance of that simple class is an object, not a value. It adds a level of overhead, however negligible. What could be better than a simple sweet short value type with a set of operations on it? I keep missing it (the value type), but alas, can't be done in Java!

    regards,
    --VS.
  82. Bit fields are not enums[ Go to top ]

    \Sliouniaev\
    I still find using bitwise ops to get at bitfield values a bit old fasioned (it is C, not even C++). It also exposes implementation of the object to the rest of the universe. Compare:

       MyFlags flags = new MyFlags(0xCABA);
       if (flags.canFly()) ...;

    with

       int flags = 0xBEDA;
       if ((flags & MyFlags.CANFLOAT) != 0) ...; // everywhere
    \Sliouniaev\

    That's not at all what I advocated. If you go back to an earlier post of my in this thread, you'll see my example was:

        public void isSet (MyEnum flag);
        public void setFlag (MyEnum flag);
        public void clearFlag (MyEnum flag);

    So in my code I would say:

       if (obj.isSet (CANFLOAT)) ....

    This hides the underlying bitfield implementation, and enums means people can't pass in meaningless junk. It seems to me at this point you're just making up objections out of sheer contrariness....
     
    \Sliouniaev\
    I would keep enums as just a plain set of values for a single variable. The bit fields IMHO would be better done as an ordinary class (not enum), which does the bitwise bits inside itself, but packs and unpacks the bits to values via '{int|boolean} getXxx()' and '{void|MyEnum} setXxx()'.
    \Sliouniaev\

    You mean like my examples above? They use enums, give you type safety, mean you avoid doing bit operations all over your code, and are convenient. What more do you want?

    \Sliounaev\
    Oops, I just realised that an instance of that simple class is an object, not a value. It adds a level of overhead, however negligible. What could be better than a simple sweet short value type with a set of operations on it? I keep missing it (the value type), but alas, can't be done in Java!
    \Sliouniaev\

    I'm not sure what you mean by "value type". How does this differ from an object? It almost sounds like you're talking about a single piece of data (the value?) that has behavior attached to it. Sounds amazingly like an object to me.

    Perhaps you mean "a single piece of data sitting on the stack". In that case, no you can't do that. You pay for "a level of overhead", which really and truly is negligible in most cases. What you get in return are guarantees that your program won't crash, and that you don't have to navigate complex language rules to figure out what the compiler's going to do in certain situations.

    Back to the idea of isFlagSet(), setFlag(), etc - if you declare these as final a JIT may inline these calls. The only overhead will be an object dereference to get to the value (e.g. this.value, object.value). If you believe this overhead is too high, then you probably shouldn't be using _any_ object oriented language at all.

    Seriously - you seem uninterested in seeing solutions that work, you just want to show how Java is speed crippled no matter what people say.

        -Mike
  83. Bit fields are not enums[ Go to top ]

    That's not at all what I advocated. If you go back

    > to an earlier post of my in this thread, you'll see
    > my example was:

    I see, my apologies, this is a nice way of doing it.

    regards,
    --VS.
  84. Value objects[ Go to top ]

    I'm not sure what you mean by "value type". How does this

    > differ from an object? It almost sounds like you're talking
    > about a single piece of data (the value?) that has behavior
    > attached to it. Sounds amazingly like an object to me.

    I indeed thought of "value objects". The difference is that they are allocated the same way as integers.

    For example, they are parts of the containing object, not separate blobs in memory. If I aggregate a Point and another Point and Flags and an Enum into a Shape, I still have a single object in memory, not five. Makes some difference if many such Shapes are required.

    > ... etc - if you declare these as final a JIT may inline
    > these calls ...
    > ...
    > Seriously - you seem uninterested in seeing solutions that
    > work, you just want to show how Java is speed crippled no
    > matter what people say.

    Yes. I even dare say that JIT itself is an overhead. :) As far as I remember, the original solution used to store JIT-ted code and re-use it later.

    (Well, seriously, I do like your bitfield with enums solution.)

    best regards,
    --VS.
  85. Mike wrote:

    > Assuming we don't want to get into the lifetime-of-
    > tempoaries bugaboo of C++, then that "copy" is a

    Why not re-use a huge experience of C++ in a good way?

    > heap allocation - in other words, you completely
    > lose the benefit of the local object. Likewise -
    > if you always pass in a copy when doing a member
    > invocation, you again lose the value - you must
    > do a heap allocation.

    I can either copy the value onto the stack again or pass a reference to the immutable original which is allocated earlier on the stack. If the called method is not passing the variable outside, no copying is necessary: the caller's stack will exist for the lifetime of the callee.

    Another advantage is that value objects can be packed into a continuous area in memory, which improves locality of reference and reduces working set (thus improving co-existence of multiple programs in memory). As long a reference to an isolated element inside the array is not passed out, there is no need to allocate a copy on the heap.

    > The minute you introduce copy-the-object-to-the-heap,
    > you've lost the whole point of the exercise.

    True, but it doesn't invalidate the need for stack allocation.

    > But you can always manually index a single dimensional
    > array as if it were multi-dimensional, so you're
    > accessing a continugous space. In fact I'd be surprised
    > if any heavily math intensive code wasn't already doing
    > this.

    Yep, multiplying matrices of complex numbers is an easy exersise in using The Simple Language. Oh, only two-dimensional arrays are not supported and infix notation which we learned in primary school isn't either.

    Well, I guess this is not what one should be concerned of while developing for the server side. No more stupid comments. It's been fun though...

    thanks,
    --VS.
  86. Mike wrote:
    > Assuming we don't want to get into the lifetime-of-
    > tempoaries bugaboo of C++, then that "copy" is a

    \Sliouniaev\
    Why not re-use a huge experience of C++ in a good way?
    \Sliouniaev\

    I wouldn't call it a good experience. It's a continual source of confusion to newbies, many developers continually use them incorrectly and get random crashes, and dealing with temporaries and their lifetimes is a big chunk of the complexity in the C++ standard. And all of this confusion and complexity exists strictly because of the decision to support stack-based objects.

    \Sliouniaev\
    I can either copy the value onto the stack again or pass a reference to the immutable original which is allocated earlier on the stack. If the called method is not passing the variable outside, no copying is necessary: the caller's stack will exist for the lifetime of the callee.
    \Sliouniaev\

    The compiler cannot accurately determine the lifetime of an object. The best it can do is try to play tricks with temporaries to extend the lifetime of such objects. Unfortunately, ultimately the stack area where the temp lives (or the original object) _is_ going to go out of scope, and any hapless programmer hanging onto such a reference is going to effectively dereference an object that no longer physically exists.

    Once again - immutable or not, the issue is references. If someone holds onto a reference to an object, the compiler generally _cannot know_ how long that reference is going to be held onto. When this happens, the compiler has two choices - stick with stack based object and hope for the best (usually resulting in corrupted data or an outright crash), or moving the object to the heap. In the former scenario, you've completely violated Java's guarantees and JVMs are going to be crashing left and right. In the latter scenario, you've ended up with a heap allocation anyway, and the whole exercise was a waste of time.

     \Sliouniaev\
    Another advantage is that value objects can be packed into a continuous area in memory, which improves locality of reference and reduces working set (thus improving co-existence of multiple programs in memory). As long a reference to an isolated element inside the array is not passed out, there is no need to allocate a copy on the heap.
    \Sliouniaev\

    If an object exists solely within a local scope, and is not passed to another method on another object or returned from the local scope, then a JVM is free to do a stack optimization today.

    The problem is that the number of cases where a JVM can safely do this are quite low - code has a tendency to pass references to objects outside of their scope or outside of their local compilation unit. When that happens, JVM's opt for safety over a small speed benefit.

    \Sliouniaev\
    Yep, multiplying matrices of complex numbers is an easy exersise in using The Simple Language. Oh, only two-dimensional arrays are not supported and infix notation which we learned in primary school isn't either.
    \Sliouniaev\

    Java isn't optimized to be a scientific or mathematics oriented language. Neither is C for that matter (pointer aliasing disallows a number of aggressive operations that a Fortran compiler is allowed to use, for example). You can do such programming in Java with decent performance (but not outstanding), but it's not going to be as convenient as it is in other languages.

    The best observation I can make on that is "live with it". Java does some thing s exceptionally well, and provides some extraordinary guarantees to programmers, but it is not all things to all people. I prefer to live with a fairly simple language with concrete guarantees than a be-all-things-to-all-people language like C++ which confuses even grizzled veterans, and provides few guarantees and lots of opportunities for crashes. This may disqualify the language for hard-core numerics coding, but it immeasurably eases the lives of countless developers who have no or infrequent need to multiple matrices (as an example).

    In short - you've repeatedly remarked on the performance plusses that can be gained out of languages like C and C++, and completely ignored the negative aspects of these language design choices. In the case of stack-allocated objects, a performance gain can be extracted, but the cost of that gain is IMHO far outweighed by the language complexity it involves, makes JVMs and JITs even more complicated, and raises the likelihood of your program crashing right out from under you.

        -Mike
  87. I disagree, with JIT's this would work rather well. Since you hardcode

    > > return true within the overriden method you can get the advantages of
    > > virtual method inlining and have NO COST of evaluation and complete
    > > removal of the else code!!
    > > This means the JIT in this case can EASILY erase a completely redundant if.
    >
    > IMHO, hardly so if you scan thousands of different characters in a
    >single loop... do you have more info about how it works?


    I guess you were talking about the map solution while I was talking about
    the first solution. With the map solution performance should be similar to
    the performance of the switch statement although I never tested it myself.
    Years ago I read an article that claimed that using this pattern in C++
    with STL maps is faster than a C++ switch statement.

    Technically if looking up a String in a HashMap you will run through a hash
    algorithem that won't compare strings unless it has to. Generally strings
    should be interned for performance.

    A set of huge performance advantages with this approach can be gained without
    the JIT. You can eliminate elements from the map if you know they aren't
    necessary for a particular user in runtime (imagine chaning your switch
    statement in runtime to match execution). You can lasily or eagerly create
    the map.

    The main gain however is dynamic, I allow people to extend my code without
    touching it which is very usefull for working in teams and essential for
    API's.

    > So, I have a form, which allows the user to register a plane. It has two drop
    >downs: engine type and plane type:
    >
    > enum {glider, spring, pedal, prop, turboprop, turbofan, jet, rocket};
    > enum {civilian, military, vintage};

    You are making my case for me ;)
    This data should come from a table in the database... Most of the application
    if at all should not be aware of the differences between these gets since
    most of the differences are the data such as the mesh that represents them.
     
    > Questions:
    > - which part of the code is responsible for converting codes into text?

    A select statement, or an Entity EJB or JDO you name it. If you want to you
    can even send it by LDAP.

    > - which part of the code is responsible for parsing user input into engine
    >type and plane type?

    I usually send the string values to the EJB tier and work on them there.
    Some of my colegues feel that the application context should cash lookup tables.

    > - how do I map the two entered values to 24 createXxxxYyyy()?

    You don't you have a single method that either takes a string or a number but
    this method will use lookup and so will other methods. Its the responsibility
    of the database to handle such things.

    > - how does a third-party method, e.g. sendEMailToRelevantAuthority(),
    > determine if a plane is civilian or military?

    PlaneEntityLocal local;
    local.isCivilian();

    Would work IMO.

    > > Java has only pointers and no stack objects ;)
    >
    > Which is a pity, IMHO. Such thing as value objects (e.g. peers of primitive
    >types) would greatly help to improve performance. E.g why can't we allocate a
    >Complex or a Point on the stack, along all local ints and doubles? Well perhaps
    >it might be possible to optimise it taking immutability in consideration?..

    Its not really possible to have stack objects in dynamic languages. Not an
    expert on C# but I read that while they have stack objects, the moment you
    pass them out of a method they automatically become regular objects....
    If this is indeed true then this is just about the stupidest thing I ever
    heard, furthermore people won't realise that they are paying the price and
    not gaining any benefit.

    I never saw the need for a stack object sicne most objects are passed between
    elements in the application otherwise I wouldn't make them.
  88. Is it bad to have good ideas?[ Go to top ]

    Its not really possible to have stack objects in dynamic languages. Not an

    > expert on C# but I read that while they have stack objects, the moment you
    > pass them out of a method they automatically become regular objects....
    > If this is indeed true then this is just about the stupidest thing I ever
    > heard, furthermore people won't realise that they are paying the price and
    > not gaining any benefit.
    >
    > I never saw the need for a stack object sicne most objects are passed between
    > elements in the application otherwise I wouldn't make them.

    I remember looking at C# a bit, and from what I remember, stack objects are implemented via structs. Structs are value objects like int and long so they are copied when you assign them. They can have member functions and members, like classes, but carry several restrictions. When you pass them to a member function:
         void foo(MyStruct bar);
    the member function foo() recieves a copy of the struct, not a reference. However things start to get a bit complicated if you change the definition to any of the following:
         void foo(Object bar);
         void foo(Ref MyStruct bar);
         void foo(Out MyStruct bar);
    because in any of these cases the struct is passed as a reference. I have no idea what will happen if foo() decides to hold onto this reference or what happens when you return a struct to a local variable by value. Since the C# runtime is supposed to be as secure, I'd imagine that either the struct is automatically allocated on the heap at the point it's converted into a reference or the C# runtime has some way of detecting that the stack object no longer exists and throws an exception. I personally can't see an efficient way of doing either of these safety features.

    You can find out more information here:
       http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=120
       http://www.dotnetextreme.com/articles/paramtypes.asp

    Value objects like structs have some uses and can save a significant amount of memory. If Java had value objects, the enum (under the current implementation) would be implemented as a struct and thus using them in EJBs would not lead to hairy object-identity issues.

    However, you get into a lot of hairy issues once you decide that structs can be sometimes used as reference values (e.g. their base class is Object or you pass them into methods by reference). If value objects were ever added to Java, I'd hope they'd do it cleaner than C#. IMO, it was a mistake to have structs derive from Object, and thus have reference semantics in some instances. If C# wanted to give structs reference semantics, they should have done it in a way similar to the way int and Integer are related. With generics, it's easy to define a "Struct<T>" class that can wrap all structs.

    Is this feature worth it? I doubt it. I've yet to come across a situation in Java where I had to allocate an enormous number of value objects of the same type. If I were writing such an application (they do exist) in Java, I'd do it via a wrapper class such as this:
            class ComplexArray {
                double[] m_real ;
                double[] m_imaginary ;
                ComplexArray(int size) {
                  m_real = new double[size] ;
                  m_imaginary = new double[size] ;
                }

                Complex getNth(int index) {
                  return Complex(m_real, m_imaginary) ;
                }
                //...
            }
    Yes it's a kludge, but it's easy to understand and use, and you don't need to be a language nazi to understand the finer points of value object semantics to use it. Besides, places where you have large numeric arrays like this, you rarely use raw arrays directly and instead user wrapper classes that implement features like sparse arrays or partial incremental calculations.
  89. Hello Shai,

    > I guess you were talking about the map solution while
    > I was talking about the first solution. With the map
    > solution performance should be similar to

    Yes, if the value is a string. However a map lookup will always slower than a switch over an integer within a small range (like enum).

    > > - which part of the code is responsible for parsing user
    > > input into engine type and plane type?

    > I usually send the string values to the EJB tier and

    Please... It is a stand-alone flight simulator game. :-) Yet I want my huge code to compile properly and work with engine types and plane types as separate types, not strings, not integers...

    > > - how do I map the two entered values to 24 createXxxxYyyy()?

    > You don't. You have a single method that either takes
    > a string or a number but this method will use lookup
    > and so will other methods. Its the responsibility
    > of the database to handle such things.

    I got it. From now on I always use strings for values and map lookups to switch to blocks of code. :-)

    Well if the map is totally dynamic and expandable at runtime, it's worth the effort. However if the set of code blocks never changes (e.g. a default one is executed if the lookup returned 'null'), it is very much like a switch to me, only with a lot of syntactic bitterness.

    Perhaps Java could allow strings to be used as argument of the switch and would do an internal map lookup. No syntactic somersaults would be required. (Josua?..)

    Wait a second, if the set of the strings never changes between compilations, why not map them to sequential integers at compile time (or class load time)and use a superfast integer lookup instead of the hashmap lookup?

    How would the compiler know which strings to map? Well, you tell it that this group of strings is a value set for some "type" of values.

    How would the user see the strings? Well, just override the .toString() method on the type. How would the program parse the user input? Well, just implement .valueOf() method(s).

    Oops, looks like an enum to me. In addition, you get type safety for free, it will be impossible to mistype the enum's value and you could use...

    I was going to say '==' instead of .equals(), but alas, in Java it is confusing: one has to know first if the variable holds a primitive type or an object. Well, .equals() anyway, as we also need .toString() and .valueOf(), and, unlike in some other languages, Java doesn't have methods for primitive types.

    Anyway, except extreme cases of a programs which modify their own behavior at runtime...

        Strings are poor man's enums! :-)

    regards,
    --VS.
  90. I guess you were talking about the map solution while

    > > I was talking about the first solution. With the map
    > > solution performance should be similar to
    >
    > Yes, if the value is a string. However a map lookup will always slower than a
    >switch over an integer within a small range (like enum).

    Looking up an Integer object within a HashMap should be practically immidiate
    with a decent JIT and cost slightly more than an array lookup in case the
    hash function is good.
    Better yet, if the number is sequential we don't need a Map you can use an
    array lookup like RunnableArray[param].run(). Technically this is what a
    HashMap does only it has two levels of indirection which should be very
    fast.
     
    > > > - which part of the code is responsible for parsing user
    > > > input into engine type and plane type?
    >
    > > I usually send the string values to the EJB tier and
    >
    > Please... It is a stand-alone flight simulator game. :-) Yet I want my huge
    >code to compile properly and work with engine types and plane types as separate
    >types, not strings, not integers...

    Why? So you have a single file that an entire application that takes 2 hours
    to compile requires? Everytime you make a change a team of over 30 people
    will need to sit two hours only to find out you broke their code that relied
    in some way on the structure.
    Techinically we have a database and an object should be able to persist itself
    to some degree. The code using ENUM's is always a HUGE switch statement that
    just serves as a huge bottleneck for the application.

    Anyway usually I wouldn't use or parse strings... I would try to target my
    own needs, lets take for instance the plane type ENUM. Rather than have
    an ENUM which the plane class needs to query in every function. Id have
    subclasses for each plane. When I wish to create the plane (on loading) I
    read the class name of the plane from the DB and do a Class.forName() which
    results in a working plane. This allows us to add planes dynamically which
    was a requirement we could not implement with our ENUM hardcoded structures.
     
    > > > - how do I map the two entered values to 24 createXxxxYyyy()?
    >
    > > You don't. You have a single method that either takes
    > > a string or a number but this method will use lookup
    > > and so will other methods. Its the responsibility
    > > of the database to handle such things.
    >
    > I got it. From now on I always use strings for values and map lookups to
    >switch to blocks of code. :-)

    When did I say that?
    If you need to run specific code according to a specific number/string from
    the client database use a Map/Array. If you just need to pass data then you
    use strings in the Database. ENUM's are poor mans database constant tables
    and every single large application allows you to define dynamically the
    constants that you use in the database table. This allows relational integrity
    within your database and I will bet that if you are writing a server side
    application that you simply map your ENUM's into a database table! This means
    that every time the data changes your code breaks!!! Thats just sad.
     
    > Well if the map is totally dynamic and expandable at runtime, it's worth the
    >effort. However if the set of code blocks never changes (e.g. a default one is
    >executed if the lookup returned 'null'), it is very much like a switch to me,
    >only with a lot of syntactic bitterness.

    Well I can't technically write switch statements since all the data is in the
    database. Within the database I may have a property like civilian (aircraft)
    and so I just don't run into the need to use switches. If people invested
    just a little amount of time thinking about how to do this correctly ENUM's
    would not be needed.
     
    > Perhaps Java could allow strings to be used as argument of the switch and
    >would do an internal map lookup. No syntactic somersaults would be required.
    >(Josua?..)

    NO! That would be hardcoding the strings just as bad as ENUM's.
    I think your fixating on some of the things I said, when technically I don't
    even think about NOT using ENUM's... I write code that is generic as much as
    possible and ENUM's just don't appear. There are hardly any Map lookup's for
    Integer/String's within my code since most of the right attributes are stored
    in the database.

     
    > Wait a second, if the set of the strings never changes between compilations,
    >why not map them to sequential integers at compile time (or class load time)and
    >use a superfast integer lookup instead of the hashmap lookup?

    #1 There is no such a thing as never changes.
    #2 Databases have these, they are called lookup tables and do provide integer
    values for the "database enums" which is the right place to put "enum like
    functionality" within the user data.
    #3 Since string is final the hashCode method can be inlines and string map
    lookup is rather fast. While switching over an int is faster it does a different
    thing. The map solution provides both parsing and interpretation support which
    is considerably faster than the switch alternative. Not all of your data comes
    from controlled numeric sources.
     
    > How would the compiler know which strings to map? Well, you tell it that this
    >group of strings is a value set for some "type" of values.
    >
    > How would the user see the strings? Well, just override the .toString() method
    >on the type. How would the program parse the user input? Well, just implement
    >.valueOf() method(s).
    >
    > Oops, looks like an enum to me. In addition, you get type safety for free, it
    >will be impossible to mistype the enum's value and you could use...

    I didn't get any of this, and obviously I never asked for any changes in the
    language to get MY code working more effciently or elegantly. You seem to be
    stuck in a mindframe that won't let you think outside the box, I suggest you
    take a good look at your code and don't think about how to remove ENUM's
    think about how it should have been implemented in an object oriented generic
    manner.
     
    > I was going to say '==' instead of .equals(), but alas, in Java it is
    >confusing: one has to know first if the variable holds a primitive type or an
    >object. Well, .equals() anyway, as we also need .toString() and .valueOf(),
    >and, unlike in some other languages, Java doesn't have methods for primitive
    >types.

    Technically Strings can be compared with == after invoking intern() which I
    usually do to bring performance up.
     
    > Anyway, except extreme cases of a programs which modify their own behavior at
    >runtime...

    Why, it doesn't cost neither in performance or code.
     
    > Strings are poor man's enums! :-)

    ENUM's are poor mans logic and database replacements.
  91. Shai wrote:

    > Why? So you have a single file that an entire
    > application that takes 2 hours to compile requires?
    > Everytime you make a change a team of over 30 people
    > will need to sit two hours only to find out you
    > broke their code that relied in some way on the
    > structure.

    Apparently not if enums are bound at class loading time. Incidentally, alas, I'd still need to recompile everything if my method signature changes. I mean, manually edit and recompile every method I point to with the hash map.

    > subclasses for each plane. When I wish to create
    > the plane (on loading) I read the class name of
    > the plane from the DB and do a Class.forName() which
    > results in a working plane. This allows us to add
    > planes dynamically which.

    If I wanted to add a new type of the engine to my flight simulator game, how many new classes would I need to create? Consider this in the context of a flight simulator game, where the user may create her/his own plane with a combination of a few discrete independent properties like {engine type}, {civilian|military|training|vintage}, {...}, etc. Looks like I do need a database and perhaps a team of code writers.

    ...which also somehow reminds me of absense of such a good thing as mixin classes that allow adding implementation of standard features to different trees of class hierarchies. Miss it. :-(

    > ENUM's are poor mans logic and database replacements.

    I guess we are never going to agree. You're talking about EJB and databases, I am about standalone applications running on today's ordinary computers, not expensive workstations. Since Java pretends to be a universal language, it should support some features which will make it faster and writing fast code - more maintainable.

    The language may be simple, but doing double somersaults to express a very simple construct doesn't make the use of the language simple. I'd rather use C++ or C#. Or perhaps Smalltalk or LISP or Delphi. Luckily, the .Net platform seems to make it possible. And they wouldn't sue me if I invented yet another language :-).

    That would be thinking outside the box: add constructs which help express the solution in a clear way and hide standard implementation patterns in the compiler and the runtime. Conversely, contorting the code inside out is precisely thinking inside the box. :-)

    thanks,
    --VS.
  92. Why? So you have a single file that an entire

    > > application that takes 2 hours to compile requires?
    > > Everytime you make a change a team of over 30 people
    > > will need to sit two hours only to find out you
    > > broke their code that relied in some way on the
    > > structure.
    >
    > Apparently not if enums are bound at class loading time. Incidentally, alas,
    >I'd still need to recompile everything if my method signature changes. I mean,
    >manually edit and recompile every method I point to with the hash map.

    Yes you will need a rebuild as you do with static final variables.
    Thats one of the reasons I advocate making constants private.

    My point is that one of the basic concepts on generic OO design is decoupling.
    Tight coupling works sometimes for small modules but ENUM's force tight
    coupling that won't allow your application to ever scale. This was the exact
    problem I'm describing. A small 100,000 line simulator was our initial code
    base. In time we turned it into 1,000,000 lines of code but we didn't have the
    forsite do dump the ENUM's this made changes impossible.

    I don't get people holding on to ENUM's, OTOH people still use goto in C in this
    day and age so. What I want is the establishment to treat ENUM's as it does
    the goto statement (I smell a PHD thesis ;)

    > > subclasses for each plane. When I wish to create
    > > the plane (on loading) I read the class name of
    > > the plane from the DB and do a Class.forName() which
    > > results in a working plane. This allows us to add
    > > planes dynamically which.
    >
    > If I wanted to add a new type of the engine to my flight simulator game, how
    >many new classes would I need to create? Consider this in the context of a
    >flight simulator game, where the user may create her/his own plane with a
    >combination of a few discrete independent properties like {engine type},
    >{civilian|military|training|vintage}, {...}, etc. Looks like I do need a
    >database and perhaps a team of code writers.

    No, you create one class for one problem.
    MyPlane extends BasePlane {
     public isCivilian() { return(true); }
     public isTraining() { return(false); }
    }
     
    Or you simply have GenericPlane() that reads this data from the
    database.

    I specifically said that anything done with an ENUM can be done for the same
    amount of code or less, in a generic OO way.

    > ...which also somehow reminds me of absense of such a good thing as mixin
    >classes that allow adding implementation of standard features to different
    >trees of class hierarchies. Miss it. :-(

    Are you talking about multiple inheritance?

    Try the wonders of debugging virtually inherited classes and you will see some
    of what I mean. IS A relationship is by nature singular and should be treated
    as such. Implementation inheritance is powerful but limiting and shouldn't be
    overused.
     
    > > ENUM's are poor mans logic and database replacements.
    >
    > I guess we are never going to agree. You're talking about EJB and databases, I
    >am about standalone applications running on today's ordinary computers, not
    >expensive workstations. Since Java pretends to be a universal language, it
    >should support some features which will make it faster and writing fast
    >code - more maintainable.

    I write that type of code when working with a properties file and when working
    on a cell phone (yes I have deployed code on all the Java platforms in real
    life projects).
    But I guess we won't see eye to eye, one quesion though? Why don't you use C#
    or C++ if you miss these features so much? If you do, then why make Java
    something its not, C# has already entered the market and there is no benefit
    in following later and poorly.
     
    > The language may be simple, but doing double somersaults to express a very
    >simple construct doesn't make the use of the language simple. I'd rather
    >use C++ or C#. Or perhaps Smalltalk or LISP or Delphi. Luckily, the .Net
    >platform seems to make it possible. And they wouldn't sue me if I invented yet
    >another language :-).

    Ok.
     
    > That would be thinking outside the box: add constructs which help express the
    >solution in a clear way and hide standard implementation patterns in the
    >compiler and the runtime. Conversely, contorting the code inside out is
    >precisely thinking inside the box. :-)

    People use ENUM's because that is what college professors teach...
    I have yet to see a single person that finishes colege who has a clue about
    OO development and design besides the stuff very basics.
  93. Is it bad to have good ideas?[ Go to top ]

    \Almog\
    My point is that one of the basic concepts on generic OO design is decoupling.
    \Almog\

    The purest, most OO-possible design is not always the best solution to a given problem. Sometimes a straightforward use of a simple construct like an enum very simply solves the problem better than a more OO approach. This

    Just as 100% pure OO solutions can go terribly wrong - everything over abstracted so that the code is impossible to follow and slower than a dead dog - overusing something like an enum can go terribly wrong as well. Personally, I like the idea of adding enums to Java, because it's easy to do and low in the cost of language complexity. And it doesn't violate any existing Java guarantees.

        -Mike
  94. Is it bad to have good ideas?[ Go to top ]

    \Almog\

    > My point is that one of the basic concepts on generic OO design is decoupling.
    > \Almog\
    >
    > The purest, most OO-possible design is not always the best solution to a given
    >problem. Sometimes a straightforward use of a simple construct like an enum very
    >simply solves the problem better than a more OO approach. This

    People say that about primitives as objects and about many concepts in the
    object oriented world. However they don't say that about the methodologies
    and abstractions we use to remove ENUM's. Every single one of the solutions
    I use is at least as fast as the ENUM solution (if not faster) and more OO
    (dynamic, generic extensible).
     
    > Just as 100% pure OO solutions can go terribly wrong - everything over
    >abstracted so that the code is impossible to follow and slower than a dead dog
    >- overusing something like an enum can go terribly wrong as well. Personally,
    >I like the idea of adding enums to Java, because it's easy to do and low in the
    >cost of language complexity. And it doesn't violate any existing Java
    >guarantees.

    The point is that the object oriented solutions take roughly the same amount of
    code but are far better. I don't want an ENUM construct because it will
    LEGITIMIZE this construct which is dead wrong.
    Unlike asserts which you don't have to use, ENUM's will be required by API's
    and that would mean 2 things:
    1. API's will be implemented badly
    2. I will have to use them

    Regarding the point of ENUM's being easy....

    I like to say that every ENUM has a switch... The ENUM methodology requires
    hardcoding, breaking of encapsulation and centering logic. These are all really
    bad things, the worse thing though, is that we teach them to beginners!
    101 classes allways teach ENUM's, which pretty much fixates this horrible coding
    style in young minds. So what may seem like a harmless simple solution at first
    is in fact a huge problem when I need to "reeducate" college graduates on how
    to "really" program.
    The annoying part is that the solutions of using ENUM's are only simpler when
    writing test cases and such. With real world data you need to turn string data
    into enums back and forth for every typical transaction which is both an
    overhead in performance and in logic (its practically impossible to keep table
    data and ENUM's in sync). So we are teaching people a simple way to fail when
    they get to the real world? Java is not a teaching tool or a beginner language
    it is a professional (and the best at that) clean language, and should remain
    clean.
  95. hardcoded still[ Go to top ]

    class Aircraft {

    > public boolean isF15();

    > private void doStuff() {
    > if(isF15()) {
           ....

    The problem with this approach is you can never do anything
    generically because you have to hard code the name of what
    your are interested in. How would i take input from a user
    to ask if an aircraft was a specific type? They would type
    F15 and the in the program we would do what? We would provide
    a picklist and then how do we map that back to the correct isXXX
    test?
  96. hardcoded still[ Go to top ]

    class Aircraft {

    > > public boolean isF15();
    >
    > > private void doStuff() {
    > > if(isF15()) {
    > ....
    >
    > The problem with this approach is you can never do anything
    > generically because you have to hard code the name of what
    > your are interested in. How would i take input from a user
    > to ask if an aircraft was a specific type? They would type
    > F15 and the in the program we would do what? We would provide
    > a picklist and then how do we map that back to the correct isXXX
    > test?

    Yes, not a good example. Normally you would write something like
    isFighter(), getWeight(), getEnvelope() etc... and then implement
    them in the class F15Jet. That would be rather generic and each
    method would map to a feature of the application allowing us to add
    jets easily.
  97. hardcoded still[ Go to top ]

    Yes, not a good example. Normally you would write something like

    > isFighter(), getWeight(), getEnvelope() etc... and then implement
    > them in the class F15Jet. That would be rather generic and each
    > method would map to a feature of the application allowing us to add
    > jets easily.

    Even that's not very OOish. Why do you need type related questions
    like isFighter? "Is" methods are often hidden little switch statements. Can
    you make a method that would do whatever you need to do without
    switching on isFighter?
  98. hardcoded still[ Go to top ]

    Yes, not a good example. Normally you would write something like

    > > isFighter(), getWeight(), getEnvelope() etc... and then implement
    > > them in the class F15Jet. That would be rather generic and each
    > > method would map to a feature of the application allowing us to add
    > > jets easily.
    >
    > Even that's not very OOish. Why do you need type related questions
    > like isFighter? "Is" methods are often hidden little switch statements. Can
    > you make a method that would do whatever you need to do without
    > switching on isFighter?

    Its not switching when its a single generic if.

    Thats by the book OO design.

    If I have a requirement for fighter jets I can simply ask whether
    the plane is a fighter jet and act accordingly rather than have
    a huge if on all the ENUM types.

    What would you consider as OO?
  99. hardcoded still[ Go to top ]

    Yes, not a good example. Normally you would write something like

    > > > isFighter(), getWeight(), getEnvelope() etc... and then implement
    > > > them in the class F15Jet. That would be rather generic and each
    > > > method would map to a feature of the application allowing us to add
    > > > jets easily.
    > >
    > > Even that's not very OOish. Why do you need type related questions
    > > like isFighter? "Is" methods are often hidden little switch statements. Can
    > > you make a method that would do whatever you need to do without
    > > switching on isFighter?

    BTW the properties of isFighter() etc... can be loaded from the database
    this all depends on the implementation. If we need to write a class for
    each plane then it might be best to just code its properties since the
    code needs to know them anyway. If we are building a more generic simulator
    (this is not really possible if you reach a high level of details since planes
    are very different from each other) then might as well code these elements.

    Loading ENUM's from the database is a switch to load and switch to save.

    Furthermore, even hardcoded return(true) can later be refactored to loaded
    data without modifying the API.
  100. Are enums limited?[ Go to top ]

    Could anyone tell me whether enums are in any way "limited classes" in JSR-201? If they're only some syntax-sugar extension to normal classes, I'll not agree that they're not OO. I am really often using a "type-safe enum pattern", and these enums falls mainly to two categories:

    - a mix of Singleton and Flyweight patterns (good example would be Boolean.FALSE and Boolean.TRUE),
    - state-like values of database columns (I would rather like to guard values by type-safety, than use plain ints).

    I see nothing wrong in using enums for this, and in fact using them is even more OO (I hate ints).

    Best regards,
    M..
  101. Text of the Tech Talk ?[ Go to top ]

    Are you plaaning to post TEXT of the Tech Talk ?
    Thanks
  102. Thumbs Up[ Go to top ]

    Even though Java is much superior to .NET, I really do enjoy seeing Java finally taking steps in adding essential language features that have been present in other languages including C#, such as enums, metadata, automatic boxing, "for each" loop iteration, etc…

    However C# continues to suffer from many deficiencies, like ugly events support, lack of inner classes, lack of checked exceptions (which is a total disaster…), immature APIs…

    While working in a company that is evenly split between Java and .NET development, differences and deficiencies on both sides become very evident. New JDK 1.5 is definitely a welcomed development on Java side.

    Dmitriy Setrakyan
    Fitech Labs, Inc - xNova™, Service Oriented Architecture for Java and .NET
  103. This would be a great enhancement to the Java platform therefore I think this deserves to be called Java 2.0 instead of 1.5!
  104. Java version numbers...[ Go to top ]

    There is a problem with naming it Java 2.0, which they should have forseen when they started the marketing campaign to call Java 1.2 "Java 2". Java 2.0 sounds so retro. Maybe when they get to version 2.0 they will market it as "Java 3"... and so on? Or should they call it "Java 3" starting at 1.5? If so, why not just jump to the 3.0 version number, as other companies have done?
  105. Java version naming[ Go to top ]

    Maybe they can call it "Java 2004" :)
  106. Removal of deprecated members?[ Go to top ]

    I've heard a rumor that Java 1.5 would be the first version to actually remove deprecated members, can anyone confirm? It would be nice to see some of the old ugliness go.
  107. Battle test Java (with C# :-)[ Go to top ]

    I like this bit:

        "There are many good ideas ... which are great and we're glad that people are doing them, but they're research and once they're battle tested for 10 years, well maybe they'll have a place in a production language."

    How are we going to battle test them for 10 years if the only language Java Universe supports is... Java?

    (It seems that presense of C# speeds that up a little bit, anyway. :-)

    regards,
    --VS.
  108. battle testing[ Go to top ]

    "How are we going to battle test them for 10 years if the only language Java Universe supports is... Java? "

    Ad hoc implementations of certain language constructs would provide a means for battle testing new ideas. For instance aspectj provides a way for the concept of AOP to be tested in the industry. Once the run-around implementations prove their worthiness, the concept can be incorporated into the language more effiently
    -JH
  109. battle testing[ Go to top ]

    While I find AOP very usefull concept in improving developer productivity, readibilty and maintainability of souce code, I found AspectJ sintax strange and a bit over-complicated. It is simply not in Java style.

    Mileta
  110. Removing features[ Go to top ]

    There are things I would change. For example, I think the Switch

    >statement should have been more structured. I don't think it makes
    >sense to have a fall through from the Case as was the case in
    >the C programming language.
    I use this construct *so* often!
    The only way to make this possible without fallthroughs, is to use the gogto keyword, like in C#/VB .NET - we really want this??
  111. Removing features[ Go to top ]

    There are things I would change. For example, I think the Switch

    >>statement should have been more structured. I don't think it makes
    >>sense to have a fall through from the Case as was the case in
    >>the C programming language.
    >I use this construct *so* often!
    >The only way to make this possible without fallthroughs, is to use the gogto >keyword, like in C#/VB .NET - we really want this??

    Heve you seen the Pascal case statement ? It is clean and structured. Something Java should have instead of this dirty C-like switch statement. I don't say C switch statement is bad for C, only that it is bad for Java, :)

    Regards,
    Mileta
  112. Removing features[ Go to top ]

    Alas, removing the last cool bit will make it _even more_ like Pascal (where is it now?..). There won't be anything to confuse people with any more, like this snippet of real Java below:

        static void bar() {
            for (int i=0; i<5; ++i) {
                try {
                    if (i%2==0) continue;
                    System.out.println("foo " + i);
                } finally {
                    System.err.println("bar " + i);
                }
            }
        }

    :-),
    --VS.

    PS. I saw it printed all the 'foo's before all the 'bar's. Why?...
  113. Removing features[ Go to top ]

    Nice one Valentin - you almost had me going there...

    Of course, if you change the 'System.err' to 'System.out' you'll see what you'd expect :-)

    /david
  114. Removing features[ Go to top ]

    what the h*** is "foo" ?

    I naver understood that.
  115. Removing features[ Go to top ]

    "what the h*** is "foo" ?

    I naver understood that. "

    It's part of the J2EE spec and everybody who implements it needs to get licensed 8~)
  116. Removing features[ Go to top ]

    'foo' is a 'foobar' with the 'bar' removed. :-)

    :^).
  117. Foo[ Go to top ]

    "what the h*** is "foo" ?

    It's a type of widget.
  118. foo[ Go to top ]

    Foo comes from fubar which stands for fucked up beyond
    all recognition. A military term. For some reason people
    like to spell it foo instead of fu.
  119. foo[ Go to top ]

    Foo Bar means nothing, thats the point if it.
  120. What 'foo' is....[ Go to top ]

    what the h*** is "foo" ?
    >>
    >>I naver understood that.

    See:
    http://www.faqs.org/rfcs/rfc3092.html
  121. Concurrency Libraries[ Go to top ]

    Good to see that they are still intending to get the concurrency libraries into 1.5. To me that is probably the single most important change...

    ...however a revision to the JLS to allow double checked locking to be guaranteed to work would be equally welcome.

    /david
  122. Concurrency Libraries[ Go to top ]

    ...however a revision to the JLS to allow double checked locking to be guaranteed to work would be equally welcome.


    why not a construct like this

    synchronized( object, boolean expression ) {
    ...
    }

    where the block is executed synchronized after having evaluated true the expression and taken the lock atomically with the evaluation.

    Max
  123. it sucks a lot to re start the app server all the time ....
  124. New Java language features will change good practice in API design. Most of existing APIs should be changed to fulfill new good practice.

    I can see new Collection API, but what other APIs in JDK 1.5 (like Swing, JDBC ...) will be upgraded to use new features?

    What backward compatibility problems will this produce and what compromises the solutions will introduce? I expect many dual APIs or dual programming styles for same APIs.

    What Collection API should learn Java beginner?
    Unfortunately, he should learn both new and old.

    I like new features very match and am ready to adopt JDK 1.5 as soon as possible, but I also see a lot of problems.


    Nebojsa
  125. Enums will help debugging[ Go to top ]

    I think one of the nice benefits of enums is that debuggers will be able to determine the symbolic code for a value that you are trying to view, rather than just having to show an integer value (for example). This will be quite handy in some situations.