Follow Slashdot stories on Twitter

 



Forgot your password?
typodupeerror
×
Java Programming

Java Gets Templates 121

lastberserker writes "Call them all you want - generics, parametrized types, thingamagic mumbojumbo - but (tada!) Java gets templates in 1.5 release. Nice landing after 5+ years of dancing around a bush. Competition is good, pardon my pun."
This discussion has been archived. No new comments can be posted.

Java Gets Templates

Comments Filter:
  • You know, I've never felt a need for templates. You're the one controlling what data goes into which data structure, so as long as you're not confused (and not forced to work with people who are) templates aren't necessary.

    Oh, and I was thinking of another kind of templates (web pages/content/presentation) when I read the title, but of course we have waay too many of those in Java already.

    So, what else is still missing from the language? It seems almost ready to go mainstream.

    • by jilles ( 20976 ) on Monday December 09, 2002 @04:35AM (#4842636) Homepage
      Sounds like you don't get the point. The reason templates are useful is because it reduces the amount of code you need to write for common situations in a typesafe way. This makes your code more compact (duplicate code) and less error-prone (it's all type safe and you only write it once).

      BTW. generics are old news. The prototype compiler and the proposal have been available for at least a year. On the javalobby there's a link to some additional language extensions: http://www.javalobby.org/thread.jsp?forum=61&threa d=6009 (lets hope /. gets this right). Lets hope all these goodies end up in 1.5.
      • Hmm, I think you get it more than lightspawn does, but when you said "generics are old news" I was expecting that you were about to point out that templates (as they exist in C++, Modula-3 ('generics'), and numerous other languages) are basically a kludge to work around limitations in the object model.

        The Beta programming language [daimi.au.dk] has a much better object model than Java/C++, which completely obviates the need for templates while still providing type-safety; basically, it lets you override 'data members' as well as 'function members' of your classes when subclassing.

        Of course, Beta is a bit hard to come to grips with if you first encountered the idea of an object-oriented language in the context of C++ or Java. Still, a little mind-bending can be good for one's perspective...

        • (sigh). Strong data types are for weak minds.

          -- Eldergeek

          It's a treat to beat your feet in the missedthepointand mod

        • I was referring to the fact that generics in Java is nothing new. The proposal for inclusion of generics in Java has been around for quite some time. At the time the 1.4 spec was being finalized it was nearly ready. I've been aware for more than a year now that the intention was to include generics in Java 1.5.

          I agree that probably Java's generics are a bit of a compromise between the Java object model, generics security and type safety. Arguably, C++ is more powerfull but less safe in that respect. Probably Beta does a better job at implementing generics. However, generics are not the solution to all problems. Essentially separation of concerns is not possible for all problem dimensions (which is what both OO and generics try to achieve).
      • Sounds like you don't get the point. The reason templates are useful is because it reduces the amount of code you need to write for common situations in a typesafe way. This makes your code more compact (duplicate code) and less error-prone (it's all type safe and you only write it once).

        Given how templates exist in C++, all it takes away is just few casts. Which as in comparison to templates are naturally type safe, because with templates you can only handle a certain type in the templated object, thus if in such case you use type casting, where's the problem?

        I am a C++ programmer, so don't flame me for that.
        But seriously all it reduces is few type casts.
        • It doesn't just reduce the keystrokes needed to do the type casts, it reduces their possible mis-use and therefore means that if your program compiles, it is more likely to be correct. This is good. It also means that good generic programming techniques will be used more often because they are more convenient.
      • First, templates increase the amount of code you need to write and second, I don't see how it makes the code more compact or reduces duplicate code. That is a factor of design. The compile time type checking is generics saving grace.
    • Yeah, if you're not going to screw up, then you don't need any type checking at all! However, if you want to compiler to tell you in the unlikely event that you or someone else using your code DOES screw up, static type checking is a great thing, and this allows you to do more without giving up that benefit.
    • Templates are useful for tons of things other than generic containers. Consider something like this in C++
      template <class T> T Max(T x,T y) {
      if(x>y)
      return x;
      else
      return y;
      }
      The compiler can determine at compile-time if you're comparing similar types, and error if you're not. Also, it doesn't need to do any run-time type checking to figure out which > to use.

      The Java equivalent would return an Object and take two Objects as parameters. All the type safety you work so hard to preserve is lost, and at run-time you're taking a performance hit every time this is called for a myriad of reasons.
      • The compiler can determine at compile-time if you're comparing similar types, and error if you're not. Also, it doesn't need to do any run-time type checking to figure out which > to use.

        The Java equivalent would return an Object and take two Objects as parameters.


        No, the java equivalent would use an interface, probably called "comparable" or somesuch.
        • I agree. I think that with interfaces you reuse design while templates helps reuse of code. I'm for design reuse every day of the week, even if it means more code.
          But that just my own opinion.
      • I'm confused - I thought that's why everything inherited from the Object class?

        Object Max(Object x, Objecty) {
        if(x > y) return x else y;
        }

        or some such - my java is rusty. perhaps you need to standardise on a function, say, x.biggerthan(y) and ensure it is transitive, reflexive, commutive etc...
    • So, what else is still missing from the language?
      • Metaclasses
      • Higher Order Functions
      • Multiple Inheritance
      • Multimethods
      • Integration of primitive types and classes
      • Makros
      • A GUI library that is not dog slow (Swing) or bothers you with memory management (SWT)
      • A Free implementation. Maybe a standard would help, too.
      Feel free to complete...
      • by Hard_Code ( 49548 ) on Monday December 09, 2002 @11:31AM (#4843849)
        Hey, you forgot:

        • My pet "feature" of dubious merit


        Until it has that it is obviously not complete!
        • Metaclasses (meaning classes whos instances are in turn classes) are, naturally, templates.
        • Higher order functions can be implemented using templates (see boost::function [boost.org].
        • Macroses are external to the language, use cpp at will.

        As for the rest, it would be nice, but we can continue surviving without these until 1.6 or so ;-)

        • Metaclasses (meaning classes whos instances are in turn classes) are, naturally, templates.
          How so? I'd say the only natural thing would be if they were, well, classes.
          Higher order functions can be implemented using templates (see boost::function [boost.org].
          Sure, boost is cool. However, it still feels nicer to have a language that is well prepared to pass closures around freely.

          BTW, even in Java people use poor man's HOFs, namely in form of anonymous inner classes. Hardly elegant, IMHO.

          Macroses are external to the language, use cpp at will.
          The C preprocessor is indeed external to the language, but it doesn't have to be that way. Think Lisp macros, or CamlP4 for Objective Caml, where you deal with language elements structurally, not just modify text.
      • Macros are evil. Really.
    • > So, what else is still missing from the language? It seems almost ready to go mainstream.

      Well, I don't know about most Java programmers, but the missing features that constantly bug me are:

      - Higher-order functions (Seriously, you can't live in a language that doesn't have this once you get used to programming with them!)
      - Algebraic Types and Pattern Matching (Vital for manipulating syntax trees, like in a compiler)
      - Tuples
      - Getting rid of 'null' (This is possible, in fact, easy, and would make the language much cleaner, less error prone, and even more efficient)
      - Uniform typing discipline (ie, int vs. Integer ... I think this is relieved a little bit by generics)
      - Parameterized Modules (a la SML's functors)

      There are also some bugs in the language itself, though those wouldn't really bother me day-to-day.

      - Arrays are covariant, leading to class tag checks on every array write (in the general case)
      - The description of binary compatibility is broken (It can lead to situations where recompliation of the class files either leads to a different program, or to a failure to compile!)
      - ...

      A language that makes some of these strides is called Nice [sourceforge.net] , though I've never used it.
      • I understand the rest, but I'm not sure about what you find wrong with null. Please expand on that, if you would.

        Thanks.
        • The problem with null is that it's yet another unnecessary run-time check. Suppose having a value of class Integer meant that you really had an integer object (instead of including the possibility that it is null). Sometimes we want to return a value plus the possibility of an error condition, in which case null is useful, so we'd have some other type for "possibly null" objects.

          You might have something built in to the language like this, like writing "Integer?" as the class name (the language Popcorn does this), you might also just have a powerful enough language that it can be coded up easily (SML has this with its polymorphic 'option' type).

          With the old null, you might write this:

          Integer x = something();

          if (x != null) { ... code involving x ...

          } else { ...
          }

          Note that if you pass x to another function, that function probably needs to check to see if x is null, too. Similarly, the bytecode interpreter needs to check for null whenever you do a method invocation on x. Without null, you might write (I am just making up the syntax; you might want to see how Nice does it):

          Integer? x = something();

          switch (x) {
          null: ... break;
          Integer(y): ... same code involving y ...
          }

          The important thing here is that we've statically captured the fact that we've done a null check (y would have type 'Integer', not type 'Integer?'). Now, the byte code interpreter never needs to check y to see if it's null (efficiency gain), the programmer is never allowed to use a value unless he's checked that it's null (program robustness), the potential for a function to return null is reflected in its type (modularity), and the programmer has to insert fewer checks, because once it's an Integer, it is not necessary (and doesn't make sense!) to check for nullness (saves typing).

          In my own Java programming, and experience with using other folks' Java programs, the Null Pointer Exception is much more common than the Class Cast Exception. However, in my experience with Object Oriented Programmers, the love of "null" runs deep, so it might be a harder sell than generics!
    • Oh, and I was thinking of another kind of templates (web pages/content/presentation) when I read the title, but of course we have waay too many of those in Java already.

      If that is what you think of when you hear "templates" in reference to programming languages, perhaps you need to become more familiar with the world of Computer Science (not computer programming -- there is a difference). Anyway, that sentence gives the impression that you don't spend enough time deep in code to make any experienced comments about language features.

      You know, I've never felt a need for templates.

      This is either flamebait, you don't know what the real principles of system design are (see the Computer Science comment above), or you don't have enough experience to be speaking. Perhaps a combination of the three.

      You're the one controlling what data goes into which data structure, so as long as you're not confused (and not forced to work with people who are) templates aren't necessary.

      Parameterized containers are just one use of templates, and obviously you haven't found the others. Programmers with a lot of experience are usually very excited when they learn about templates, because they can immediately see where they would be really useful. If you can't, then you need to do more reading than speaking (insert sagely counsel here ending with "young padawan"). A function needs to be written twice, once for 8-bit characters and once for 16-bit characters. Templates make it possible to write (and, more importantly, maintain) just one version of the function that handles both situations. And it will also nicely handle the situation of 32-bit characters just fine if that situation ever arises.

      Even in the case of simple parameterized containers, templates do a lot more than you give credit for. First, it isn't always YOU that puts stuff in the container. Did you know that some programs aren't written by just one person? Yes, really! So sometimes somebody else misunderstands what goes into your nice generic vector named "nuts". It compiles ok, and works most of the time, but once in a while an exception now pops up. Hey, how did this walnut get into my peanut vector?

      Second, when extracting items from the vector, there is no need to cast the type. And remember that casting actually has a runtime cost -- the system has to verify the type.

      It [the Java language] seems almost ready to go mainstream.

      Alright, if that isn't flamebait, I don't know what is.
  • by Wrexen ( 151642 ) on Monday December 09, 2002 @04:27AM (#4842616) Homepage
    Does this mean Java will get operators soon? Back when Java was introduced, lack of templates was called a "feature", just like the lack of operator overloading. Have the designers seen the light?
    • c++ folks are used to use operator overloading with templates together. The sample code 3 posts above does just that.. the "ab" assumes the "" is overloaded for the chosen type.

      Java ain't complete 'till C# compiles on it?

      (if Java is gonna have weird cool features added, I'd like to vote for what I read in the Eiffel doc the other day: design by contract, with pre and post conditions and class invariants. )
    • Nooooooo (Score:3, Insightful)

      by Khazunga ( 176423 )
      Please don't. Operator overloading is one of those cool features that tend to create write-only software. I don't want the meaning of '+' to be different every time I look at it in someone else's code. And please, don't come up with the string concatenation example.

      <irony> 1+1=3 for large enough values of 1 is the most I can concede in operator deviant behaviour. </irony>

      • Please don't. Operator overloading is one of those cool features that tend to create write-only software. I don't want the meaning of '+' to be different every time I look at it in someone else's code. And please, don't come up with the string concatenation example.

        The meaning can be the same, or different - it depends on the body of the function, not its name. Just like, say, toString() can do what you expect it to - or something else entirely. The language should not be expected to prevent you from defining functions named toString() just because they don't perform the function you think they should. Why should it be any different with operators?
        • Re:Nooooooo (Score:5, Insightful)

          by Khazunga ( 176423 ) on Monday December 09, 2002 @07:15AM (#4842941)
          The language should not be expected to prevent you from defining functions named toString() just because they don't perform the function you think they should. Why should it be any different with operators?
          Operators, to be usable, should be very terse. Three characters maximum is a good recommendation. Most operators are one or two characters.

          With that short a definition, the operator's meaning must be inferred by the reader's culture. + is the arithmetic sum operator. We know what it does after working with it for years.

          Methods, on the other hand, can have extremely verbose names. That is one of the good things on the Java coding guidelines. Names are verbose. There's no strcmp. There's String.compareTo. If the compare is case insensitive, there's String.compareToIgnoreCase.

          Objectively, you are right. There's no guarantee a function performs what its name implies. However, if a function's name is incorrect, I can smack the developer on the head. If an operator's name is incorrect, the developer may have done it right, since having an operator named multiplyTransposeAndNormalize is awkward. It's the whole concept of operator overloading that is wrong.

          • by Anonymous Brave Guy ( 457657 ) on Monday December 09, 2002 @09:20AM (#4843187)

            Sorry, but I'm going to rant now, because every time I see this ill-informed argument it really annoys me.

            Operator overloading is a fact of life when you are working with generics. Suppose I want to write a generalised summation method, which adds up all the elements in a list, whether those are int, float, SomeComplexNumberType or whatever. Question: what well-known and easily understood notation would make sense to use when writing this method? Should I write another method called add that has several versions, for each type I'd like to add up? Or maybe it should be addTo? After all, by your own argument, verbose and descriptive names are the way forward. But what if someone else provides a fixed-point type with a method called sum instead? Or maybe a static method taking two fixed-point values called sumOf? Do you see my point here? If everyone uses + to mean +, then writing such code is easy. If everyone uses different notation, which is forced if you don't allow operator overloading, then what you get is unmaintainable crap that cannot take advantage of generics in many of the most useful ways.

            Java already has operator overloading anyway. You have + to concatenate strings. You have a conversion operator called toString. You have / that divides real numbers, but takes the integer part of the result for integral types. The only difference between these and what you have in a language like C++ is that in Java, you can only take advantage of this concept where the Java designers want you to, whereas in C++, you can write your own types at full strength as well.

            Yes, operator overloading can be abused. So can method naming (and no, you can't smack the developer on the head, if he happens to work on the other side of the world and you're stuck using his library). But op overloading is more than mere syntactic sugar, where generic programming is involved. There are accepted standards for how we write certain concepts such as addition or strict ordering, and operator overloading is necessary to allow user-defined types to meet those standards, and thus to allow well-written generic code to take advantage of parameterised types and such to best effect. Without it, you've got a fabulous canvas, yet nothing but coarse paintbrushes to draw with.

            Alas, as is so often the case, I fear the Java community has been too quick to think it understands, and to go for the buzzword feature without investigating the supports deeply enough. Parameterised types are a good start, and I'm glad to see them included, but I suspect that with experience, there'll be some serious enhancements in a couple of revisions' time...

            • by nojomofo ( 123944 ) on Monday December 09, 2002 @10:46AM (#4843566) Homepage

              I don't necessarily disagree with everything you're saying here, but a few things drew my attention....

              You have a conversion operator called toString

              Um, no. You have Object.toString() which is a method, not an operator.

              There are accepted standards for how we write certain concepts such as addition or strict ordering, and operator overloading is necessary to allow user-defined types to meet those standards...

              It sounds like you're talking about why operator overloading is necessary for C. For one, "user-defined types" don't exist in Java. Second, I don't agree with what you're saying. What about Lisp? Do you think that Lisp is a poor language because you don't add two numbers by saying 1 + 2? Lisp breaks your "accepted standards for how we write... addition".

              • For one, "user-defined types" don't exist in Java.

                I think he means "classes". Why should '+' work for the java string class, but not for a user defined string ?

                Second, I don't agree with what you're saying. What about Lisp? Do you think that Lisp is a poor language because you don't add two numbers by saying 1 + 2?

                There are accepted standards for what '+' means. Even in LISP. The fact that the lisp programmer writes (+ x y) instead of x + y is not relevant -- the point is that it makes sense to have x+y or (X x y) mean the same thing ("add these things together) for user-defined types (like big numbers, high precision floating point numbers, quaternions, finite abelian groups, matrices) as it does for built-in types.

              • Um, no. You have Object.toString() which is a method, not an operator.

                Perhaps my terminology isn't the norm in the Java world, but nonetheless, what you have is exactly the same as a conversion operator in other languages. It is a means of implicitly converting between types. Except that in Java, you can only set that up for conversion to a String implicitly. (Don't even get me started on why all classes should have to provide this method in the first place, or on the common root class flamefest.)

                It sounds like you're talking about why operator overloading is necessary for C. For one, "user-defined types" don't exist in Java.

                Really? What's a class, then?

                Second, I don't agree with what you're saying. What about Lisp? Do you think that Lisp is a poor language because you don't add two numbers by saying 1 + 2? Lisp breaks your "accepted standards for how we write... addition".

                Lisp has an accepted standard of its own: (+ 1 2) is the sum of the numbers 1 and 2. The point is not a universal notation, but a consistent notation within the language, which allows you to write a generic method once that can work with any suitable type without further modification.

                Your example is particularly ironic because Lisp's S-expressions are a prime example of exactly the sort of uniform syntax I'm advocating here.

                • Seems to me that the whole crux of what you don't like about Java (at least as relates to this subject...) is that there is a fairly marked distinction between primitive types and classes. They behave differently. They are used differently. Yes, Strings do use the + operator and there is implicit toString() calling, which ar an exceptions (side note: I have no idea what you mean when you say "Except that in Java, you can only set that up for conversion to a String implicitly"). If you're that much of a "purist" that this is a problem for you, then maybe only Lisp is uniform enough for you.

                  But really, as others have pointed out, what does it mean to add a primitive to an object (of a perhaps arbitrary class) or two different objects? Why is it really so wrong that you have to define in a method what happens when you add them?

                  • My objection isn't just that primitive types and UDTs work differently, although that is a fundamental cock-up that should long since have been fixed. My main objection is that we already have a sensible way to represent these concepts, and it's absurd to go around reinventing the wheel, and in a somewhat arbitrary way at that, rather than going with the obvious.

                    Is it really wrong that a multiply-and-add operation on two matrices be written as M = A * B + C? Or that a new date should be calculated with seasonEnd = seasonBegin + seasonLength? Why is it in any way better to write something like:

                    • M = A.Multiply(B).Add(C)
                    • M = Matrix.Sum(Matrix.Product(A, B), C)
                    • M = MultiplyAndAdd(A, B, C)

                    or any of the zillions of other possible permutations? Do you honestly feel that this is less subject to abuse, or less error-prone?

                    And why shouldn't my parameterised tree container, and the algorithms that operate over it, be able to work with int and float data, as well as BigNumber and FixedPoint values? Why should I have to write it all twice (at least)?

                    Operator overloading is much cleaner, reduces the programming effort required to develop parameterised data structures by a factor of at least two, and consequently reduces error rates. The only point I've seen against it that is true is that there is scope for misleading operator overloads to be provided. It isn't hard to see the conclusion, if only you sit down and look at it objectively.

                    Oh, and the implicit conversion thing relates to the fact that I can convert an object into a string just by context ("some " + myObject + " thing") but I can't implicitly convert to an int for analogous summation purposes, say.

              • Operator overloading seemed good at first until: Dog d1 = new Dog(); Dog d2 = new Dog(); Dog d3 = d1 + d2; Just because you can do something, doesn't make it right. The 2% of coders that can use it correctly will have to suffer because the rest can't. M
            • Suppose I want to write a generalised summation method, which adds up all the elements in a list, whether those are int, float, SomeComplexNumberType or whatever. Question: what well-known and easily understood notation would make sense to use when writing this method?


              In Java, operators already only apply to primitives anyway, with the exception of the + operator, and then only when in a string context (ok ok, there is 'instanceof' and 'new'...i'm not sure if these can be meaningully considered "operators" as they are reserved for very specific uses). Collections also only apply to objects. It already doesn't make sense to be able to perform certain operations on arbitrary objects. E.g., what does the addition operation do with operands of Bicycle type and the Color orange? If you are going to use generics for collections, you are already going to declare them to use some homogenous base class. In your case it would be something like Addable, which would have an add() method or whatever. Or perhaps just Number, from which you get primitive values, and add them with the primitive + operator. At some point you have to draw the line in defining things. Performing arbitrary operations on arbitrary objects at best makes no sense, and at worse can be very very dangerous.
              • With respect, I think you miss the point as well. The fact that Java treats primitive types differently from those derived from Object is already a serious thorn in the side of many a programmer. This sort of generic feature could provide a systematic, uniform way of dealing with such types, banishing the need to use bastardisations like Integer to a much smaller range of applications. This, IMHO, is a Good Thing.

                You're quite right, of course, that it doesn't make sense to try to add an apple and the colour purple. What you're ignoring is that you simply wouldn't provide an addition operator taking a Bicycle and an Orange, and thus trying to do add them with a generic function could and should result in a compile-time error, or at least a run-time error if you're relying on late binding. There is no problem here; at worst it's the same as what you've got if you do the same thing in non-generic code now.

            • Suppose I want to write a generalised summation method, which adds up all the elements in a list, whether those are int, float, SomeComplexNumberType or whatever ...

              I believe Java generics don't support primitive types, only classes and interfaces.

              Should I write another method called add that has several versions, for each type I'd like to add up? Or maybe it should be addTo?

              The problem you pose is real: We should have a standard way of adding to instances of a certain type. However, IMHO the best solution isn't to add operator overloading, but rather to standardize an addition interface:

              interface Addable {
              public void add(Object other);
              }
              And of course you can also make it generic to avoid downcasts.. :) This is similar in concept to Comparable, and doesn't resort to operator overloading, which is, to Java, nothing but syntactic sugar.
              • I believe Java generics don't support primitive types, only classes and interfaces.

                Oh, dear. I read about that when the proposals first flew around a while back, but I confess I thought they'd changed it, and didn't really check in detail this time.

                That's a shame, because now one of the few really good things that was going to come of this hasn't.

                However, IMHO the best solution isn't to add operator overloading, but rather to standardize an addition interface:

                We already have one of those: it's called the + operator. :-)

                But seriously, your approach is fundamentally flawed in at least one totally unnecessary way: it requires a different interface to be implemented for each relevant method, so a numeric class might well have to implement more than a dozen interfaces just to do the basics (and still wouldn't be compatible with primitive types, unless you're going to provide that interface for them as well). Presumably your parameterised functions or types are also going to list all the interfaces they require of each parameter type explicitly as well?

                This is similar in concept to Comparable, and doesn't resort to operator overloading, which is, to Java, nothing but syntactic sugar.

                But Comparable has always been a bit of a dark hat in a room full of white suits. It's there exactly because the need I'm talking about exists, but for some reason people I've never fathomed Java people don't seem to like operator overloading.

                The question is, at what point does this break down? Do you provide interfaces for LessThanComparable, StrictlyLessThanComparable, EqualityComparable, InequalityComparable, GreaterThanComparable and StrictlyGreaterThanComparable, to correspond to the various equality and inequality operators? (Do you make the primitives provide them as well?) Do you try for more abstract concepts, such as Ordered or StrictlyOrdered? The latter is probably better style, but then you lose an element of precision that might be important when working with arbitrary types. Perhaps you start with an interface for each method, and then create more abstract, compound interfaces derived from them? But now, my poor little class that just wants to compare two int members for an ordering, is supporting multiple layers of interfaces, several at a time, and providing an artificial method, just so I can sort it?

                Thanks, but I'll take operator overloading and proper generics any day.

                And by the way: I'll think about admitting that operator overloading is mere syntactic sugar just as soon as you show me a class that works like a function, so I can pass it in to a generic algorithm. :-)

          • Yeeeeeeeees (Score:1, Insightful)

            by Anonymous Coward

            But sometimes the terse name is the right one to use. The standard examples come from maths programming. If you have a Complex number class, then it is far more natural to write

            Complex c1;
            Int i;
            Complex c2 = c1 + i;

            Rather than
            Complex c2 = c1;
            c2.addInt(i);

            Of course a method is usually the best place to put functionality. But not always Blitz [oonumerics.org] is a great maths library using templates and operator overloading when necessary to produce a very powerful and usable system.

            Other examples are the iostream library and STL in C++.

            The ability to overload the <operator allows the STL to use primitive types and user defined types in the same algorithms.
      • > Please don't. Operator overloading is one of those cool features that tend to create write-only software.

        No, this is write-only software.

        a = BigInt(xyz);
        b = BigInt(pdq);

        a.add(b.div(3))

      • I'm a mathematician. I do arithemetic operations with types that aren't built in to the language. And they aren't all exotic -- things like vector addition. (no, not the misnamed java.util.Vector.) If x,y,z are n-dimensional vectors, how to you code w=x+y+z? I want the code to look the way it does for builtins:

        Vector w=x+y+z;

        Otherwise, the math gets _badly_ obfuscated and buried in minutia. I have yet to use a language that allowed it. (Yes, this is a pet peeve.)

        And I don't buy that it won't be clear what "+" means in each case. It means the addition operation that makes mathematical sense given the operands. If that isn't clear to you, you aren't going to get the code no matter how it's written.

        Example time. The addition code is written for binary (2 argument) addition, because you shouldn't have to write more than. Assume addition code also allocates the memory or invokes the constructor for the result, because it gets *really* ugly if it doesn't.

        C: You have to use a name instead of "+", and you have to manage the memory. I wrote a few thousand of lines of this stuff as a grad student.

        double *temp = vectoradd(x,y);
        double *w = vectoradd(temp,z);
        free(temp);

        C++: You can use "+", but you still have to manage the memory. [It's possible to do better if you overload "=" to do reference counting. But if you don't like overloading "+", you really won't like that.]

        Vector temp = x+y;
        Vector w = temp+z;
        ~temp();

        Java: You don't have to manage the memory, but you are back to using names:

        Vector w = x.add(y).add(z);

        If these examples don't seem very messy, see what (a*x*x+b*x+c)/(d*x*x+e*x+f) turns into if you change the variables from doubles to some object type -- say representing complex numbers. And remember that that's pretty simple as math expressions go.

        Here's what I propose: don't let the programmer overload "+" arbitrarily. But for classes which implement certain kinds of mathematical entities, have a set of methods they must implement with the types that make mathematical sense. E.g. if class foo claims to be a vector, it must implement

        public foo add(foo, foo)
        public foo scalarMultiply(double, foo)
        public foo scalarMultiply(foo, double)

        Then overload the standard arithmetic operators with these methods. It should be possible to make it work well for mathematical objects, but unpleasant for anyone who wants to tries to cheat the system.
        • Here's what I propose: don't let the programmer overload "+" arbitrarily. But for classes which implement certain kinds of mathematical entities, have a set of methods they must implement with the types that make mathematical sense. [...] It should be possible to make it work well for mathematical objects, but unpleasant for anyone who wants to tries to cheat the system.

          And how, exactly, do you propose to work out who is "cheating the system" and whose use is quite legitimate? Is the use of + to concatenate strings acceptable to you? What about other string-like classes? How about for adding date/time and time period classes?

          At the end of the day, you can never anticipate every use to which such a feature could usefully be put. You have two choices: try, and provide something that is sometimes useful but usually frustrating, or leave the choice to the informed developer, and let them do what they will with it. The fact that C++ is still here is testament to the fact that the second approach works. I can't think of a single language that tries to restrict the programmer this way that has lasted more than a short period.

          • I've already included string concatenation with + -- the set of all finite strings from a given alphabet forms a semigroup under concatenation.

            But you're basically right. I don't know how many mathematical types -- or properties -- I would want to add. It would probably be a few dozen, and undoubtedly more in the second release.

            I don't want my languages telling me what to do any more than you do. But that's not where I'm going. I need both overloading and automated memory management, and I need them in a compiled general purpose OO language. But I only need overloading in a specific context where it really makes sense. I'd be quite happy with a design-by-contract setup which requires that the class fulfill (within roundoff error) the appropriate mathematical definition. E.g. to be a semigroup, you have to have the operator be associative. That is, (a+b)+c == a+(b+c).

            And that shouldn't trigger the (legitimate, IMO) complaints that overloading-heavy code is write-only.

            • I think we're on the same wavelength, but just a couple of points are worth mentioning...

              Firstly, it's almost invariably not true that (a+b)+c == a+(b+c) from a numerical analysis point of view. The problems of limited precision render such mathematical niceties, well, niceties. While I appreciate that it would be nice to program in a higher level language where such mathematical contracts were used, none of those under discussion around here will ever qualify.

              As for overloading-heavy code being write-only, I couldn't disagree more. Code where operators are overloaded usefully (viz. typical mathematical types, string concatenation, etc.) is far more readable than the equivalent with longhand methods being used all over the place, particularly in a language such as Java that has no free functions. The only time such code becomes write-only is when the operators are overloaded in a misleading way (for example, having unexpected side-effects) and that's no different to the effect of choosing a bad name for any other function, or variable, or type.

              • I am aware of roundoff error. That's why there's a parenthetical "within roundoff error" in my previous message. :)

                I don't have a much experience reading other people's code with overloaded operators. But I think overloading would help clarity if, and only if, the overloaded function is enough like the builtin version of the operator. At a minimum, the semantics need to be analogous and the presence or absense of side-effects needs to be the same. Overloading "=" to implement reference counting doesn't qualify in my book. (This is closer to what you just said than to what I initially proposed.)

                After all, in many languages the builtins are essentially overloaded -- int+int isn't the same thing as double+double.
        • C++: You can use "+", but you still have to manage the memory. [It's possible to do better if you overload "=" to do reference counting. But if you don't like overloading "+", you really won't like that.]

          Vector temp = x+y;
          Vector w = temp+z;
          ~temp();


          Not only is that invalid C++ code, but you seem to be complaining about a non-existant problem. Your class should look something like this:

          #include <stddef.h>
          #include <assert.h>
          #include <algorithm>
          #include <iostream>
          class Vector {
          double * d_; size_t nElems_;
          public:
          typedef size_t size_type;
          Vector( size_type n ) : d_(new double[n]), nElems_(n)
          { std::fill_n( d_, n, 0.0 ); }
          Vector( const Vector& v ) : d_(new double[v.nElems_]), nElems_(v.nElems_)
          { std::copy( v.d_+0, v.d_+nElems_, d_ ); }
          double& operator[]( size_type i )
          { assert( i < nElems_ ); return d_[i]; }
          Vector& operator=( const Vector& v ) {
          if( v.nElems_ > nElems_ ) {
          double * tmp = new double[v.nElems_]; delete[] d_; d_ = tmp;
          }
          nElems_ = v.nElems_;
          std::copy( v.d_+0, v.d_+nElems_, d_ );
          return *this;
          }
          Vector& operator+=( const Vector& v ) {
          assert( v.nElems_ == nElems_ );
          for( size_type i = 0; i < nElems_; ++i ) d_[i] += v.d_[i];
          return *this;
          }
          size_type size() const { return nElems_; }
          ~Vector() { delete[] d_; }
          };
          Vector operator+( const Vector& lhs, const Vector& rhs )
          { Vector tmp(lhs); tmp += rhs; return tmp; }

          int main() {
          Vector a(10); Vector::size_type i;
          for ( i = 0; i < a.size(); ++i ) a[i] = i;
          Vector a2 = a + a;
          for ( i = 0; i < a2.size(); ++i ) {
          if ( a2[i] != a[i] + a[i] )
          std::cerr "a2 is not a + a" std::endl;
          } // Note: no cleanup necessary here
          }
          • It looks like you're right and I was wrong.

            It's been a while, but I believe I was manipulating pointers to objects to avoid all copying. The application was computationally intensive, but it was probably silly of me anyway.
            My C++ experience isn't extensive, and the implementation wasn't exactly modern.
      • I really don't get that argument. Take this example:
        Foo a = get_a ();
        Foo b = get_b ();

        Foo c = a.plus (b); // readable, no lookup needed.
        Foo d = a + b; // unreadable, need to look up "+".
        Why is the assignmed to c inherently more readable than the assignment to d?

        • Why is the assignmed to c inherently more readable than the assignment to d?
          Example: Foo is a type where for c=0, the plus operation results in infinity (convoluted example, I know). How does plus() handle that case? Does it throw an Exception? Does it return a NaN? Does it return Infinity? Can you have all three choices available? How do you distinguish them?

          With +, you can't verbosely specify the behaviour and implement all three cases -- see my other post in the thread. With the method notation, you can have:

          • Foo.naturalPlus()
          • Foo.integerPlus()
          • Foo.bigNumberPlus()
          Note that I don't assume that method notation is the best for all cases. I'm stating that 95% of the uses of operator overloading, to use operator notation for user-defined types, fall into this kind of traps, and make code terribly difficult to read.
  • Comment removed (Score:3, Insightful)

    by account_deleted ( 4530225 ) on Monday December 09, 2002 @05:13AM (#4842714)
    Comment removed based on user account deletion
    • (so, for example, I could declare a SortedList type, where only types that implement Comparable can be used)

      List<Comparable>
      would probably do that for you

      Disclaimer: I didn't actually check the spec, but int the page of the article there is nothing that indicates that is has to be a class and not an interface or abstract class

      • Re:How sad (Score:3, Informative)

        by Hellkitten ( 574820 )

        Damn I hate replying to myself

        It seems I may have misunderstood the parent post. Reading through it again I believe he meant something like

        class MySortedList<Comparable Element>{
        void insert(Element e) {
        /* now we can do this: */
        int i = e.compareTo(another_element);
        /* because we can be sure that e implements
        comparable */
        }
        }

        which it seems the specification doesn't support, and it should have. (to be really useful)

        • And where is it that you need templates in there?

          Don't get me wrong here, I'm a C++ (and Java) programmer myself, and I do use templates every so often, but seriously that's not the thing you need templates for. If you already have a common interface for the storable items that provides you the stuff you need you really don't need the template at all.

          I've seen all sorts of people write all sorts of heavily templated code over the years and I must say that the need for them (besides some heavy trickery and ioccc uses) there's been little accomplished that couldn't have been done equally well using other means.

          I never understood why was it so much easier to use templates and rely on the fact that the class has said compareTo method than it is to then declare that your class implements interface Comparable for example.

          Besides implementing templates for java all in all escapes me. Although it may strip away few casts, but I wonder wether that really makes things better.
          • One of the major plus points of templates is precisely that they don't require you to implement a particular interface by name. Thus they can adapt to any types provided by other parties that provide the necessary interface functions without explicitly saying that they derive from some known base class.

            And yes, stripping away the casts is better. It reduces a major class of bugs from run-time to compile-time, and that is a Good Thing.

            • That's how templates in C++ work. It's not how generics in Java work.

              In Java, if you specify that any class T can be used, you can call only methods declared in Object on variables of type T. If you want to call other methods, you must constrain the type to a subtype of Object.

              • That's how templates in C++ work. It's not how generics in Java work.

                I did mention that myself, if you check. :-)

                In Java, if you specify that any class T can be used, you can call only methods declared in Object on variables of type T. If you want to call other methods, you must constrain the type to a subtype of Object.

                And this is where the approach now taken in Java is seriously inferior: there goes your type safety. How, pray tell, are you going to mandate that some third party library developer must implement a suitable interface in any class they provide, such that you can write generic methods to work with a whole family of types that support the interfaces you need, without knowing in advance what they are? Must they implement a single-method interface for every method in their class, and must you specify explicitly which methods' interfaces are required for your generic function? I don't think you've thought this through far enough.

                • I have to admit, I don't get your points at all.

                  Why do you say "there goes your type safety"? Can you explain in detail why Java generics are not type safe?

                  I also don't follow the vague example you give about the third party developer. I can't recall any situation I encountered like that when using C++ templates. Can you give a more specific example?

                  • Why do you say "there goes your type safety"? Can you explain in detail why Java generics are not type safe?

                    It's not that they are necessarily not type-safe, not in the way that the current containers are because you have to perform a potentially wrong downcast to use them.

                    However, suppose I develop the world's greatest sorting algorithm, and I want to write a generic implementation for it to sort arbitrary sequence containers of arbitrary types. There are inevitably certain minimal requirements: I must be able to traverse my container in a suitable way for my algorithm to work, the types must support a suitable ordering relation, and so on.

                    As I understand it, several people in this thread are advocating the use of interfaces to ensure that only suitable types get passed to my sorting algorithm, thus ensuring type safety. The problem with that is what happens when someone comes along with a new container or sortable type that provides the necessary methods, but doesn't explicitly use that interface. Now my "generic" sorting algorithm can't be used, purely because of a naming issue. (I realise there are certain standard interfaces defined for things like comparison in Java, but obviously for types and algorithms in general that won't be the case.)

                    The requirement to implement interfaces explicitly is simply an unnecessary bar to the use of generics. In other languages, from C++ to SML, you can achieve similar effects without ever explicitly naming your interface. Instead, the algorithm simply fails to compile if it's used with types that don't match the way the algorithm uses them. Added to the presence of operator overloading, which standardises many fundamental arithmetic and logical operations from the start, writing generic algorithms that really are quite general is significantly easier.

                    Further, the concept of an interface as defined in languages like Java is inadequate to enforce useful constraints in practice anyway. The suggestion has been made, and refuted, many times in the C++ world, and alternative approaches to document and enforce constraints within template code have been developed instead.

                    The only alternative that I see as Java's generics stand today is to define all your generic algorithms to work with any Object, and go back to downcasting, but then you might as well never have bothered with generics in the first place.

                    Thus your two alternatives are either an interface-based system, which is type-safe but unnecessarily restrictive and less efficient, or to use generics only for type-safe containers and to write your generic algorithms in terms of Objects, which leaves open type safety loopholes.

                    Ultimately, implementing generic algorithms will always suffer because one man's search method is another man's find. It is helpful to offer methods of standard names to make generalising code easier, but clearly you can't have a standard interface for everything in a general purpose library that may be put to any use. I advocate the use of operator overloading, because the sorts of calculations performed by built-in operators tend to be useful in a wide variety of contexts. Beyond that, if your generics only deal with the methods that are actually presented, whether or not they're explicitly identified by a formal interface, at least you keep the range of application as wide as possible. If you need to go farther still, you're into the land of intermediate classes (such as the iterators in C++'s standard library) to standardise an interface by force. In that case, you can always implement a named interface there, but of course there's an inherent performance hit in doing so, and you really want such intermediate classes to be so lightweight that you don't even realise they're there under normal use.

          • You are right, there is no absolute need for templates. But if they are going to implement them they should do it right, and that mean beeing able to force one or more interface(s) and/or a base class as the template type. After all the reason was stronger type safety

            e.g. for a collection class you could just as easily just use that interface or base class as the parameter, and document that all object in the collection should be the same class

            It's basically an extra bit of syntax to generate compile-time errors instead of run-time errors, letting stupid programmers know earlier:)

          • I never understood why was it so much easier to use templates and rely on the fact that the class has said compareTo method than it is to then declare that your class implements interface Comparable for example.

            To answer your question, if you don't mind a C++ focus, may I suggest that you read Andrei Alexandrescu's "Modern C++ Design", Addison-Wesley, Boston, Mass., 2001, ISBN 0-201-70431-5. Among other things, it offers a way of facilitationg the explicit coding of design pattern implementations.

        • Re:How sad (Score:4, Informative)

          by bunratty ( 545641 ) on Monday December 09, 2002 @02:53PM (#4845359)
          You should be able to write this as:
          class MySortedList<Element implements Comparable> {
          void insert(Element e) {
          /* now we can do this: */
          int i = e.compareTo(another_element);
          /* because we can be sure that e implements comparable */
          }
          }
  • After years of discussions, Sun aknowledges that, although life is possible without generics, it is often better with them.

    Now, how many years do we have to wait until they do the same with the good old enum type?

    Pascal
  • by magnum3065 ( 410727 ) on Monday December 09, 2002 @07:20AM (#4842949)
    Doing mainly C++ development I've learned to love the STL and most recently the Boost [boost.org] libraries and I've long regretted that Java didn't support templates. It always confused me that with as much emphasis was placed on strong typing in Java that there was so much need for casting.

    Although I'm glad to see the introduction of templates, I'm also concerned about how some of the problems I've encountered with C++ templates will be avoided. The biggest problem I've encountered has been the lack of interface checking.

    For example the templated function for_each(begin, end, function) iterates from 'begin' to 'end' calling 'function' on each item inbetween. However there is no mechanism to specify that the type of passed to 'begin' and 'end' must have an equality operator and an operator* and 'function' must take one parameter of the type returned by *begin. This can cause very strange compiler errors when a user tries to pass a variable that doesn't support the proper operations to be compatible with the function. These errors actually appear to occur within the templated code, not the user-written code and can make determining the cause of these errors very difficult.

    The Boost Concept Check [boost.org] library provides a way for programmers writing templated C++ code to enforce the interface requirements on the templated parameters in a way that gives more informative error messages. However this is rarely used, even in the Boost libraries. The documentation on the Boost Concept Check [boost.org] gives a good example of the kind of errors that C++ programmers dread.

    In order for Java templates to be successful they will need to provide some manner of enforcing requirements on the interface necessary for the templated code to work and provide useful errors at compile time if it doesn't.

    • Recent versions of GCC ship with a version of the Boost Concept Checks embedded in (and adapted to) libstdc++. You can turn it on with a #define, or turn it on all the time with a switch to the 'configure' script. The docs [gnu.org] explain how.

      My own copy of GCC has the checks turned on permanently. Very useful.

    • If you read the spec [jcp.org] you will find that they have implemented a method for interface checking. You can require that a template parameter have a certain base class and/or implement a set of interfaces. Here is an example:
      interface Iterable<T> {
      Iterator<T> iterator();
      }
      interface List<T> implements Iterable<T> {...}
      interface Set<T> implements Iterable<T> {...}
      class Test {
      void <T,S implements Iterable<T>> printList(S s) {
      Iterator<T> it = s.iterator();
      while (it.hasNext())
      System.out.println(it.next());
      }
      }
      The careful reader will also note that they fixed the requirement that >'s have to be seperated by whitespace.
    • I've experienced the exact same problem you're describing when using C++. However, I believe there are two important differences between Java and C++ that will reduce its effect with Java:
      • STL usually requires relatively simple things from template types: equality/comparability operators, copy construction, etc. These issues are already addressed in Java: All Objects support equality (using equals()), there's an interface for comparing objects (Comparable), and copy construction is simply not needed because of simpler memory allocation.
      • In my experience, C++ tend to use templates where an interface would suffice. Sometimes this is a symptom of premature optimization (everybody knows templates are so much more efficient than inheritence with its virtual calls..). Other times, its caused by lack of understanding. Usually, however, it's because of the dreadful tendency of C++ programmers to use the minimal number of classes necessary, and using an interface would entail writing a whole new class to accomodate it..

        Anyway, Java already has a long tradition of using interfaces properly (it even has its own keyword :), and I believe Java programmers better understand its proper use. Hence, overusing templates is less likely to occur in Java.

  • by Anonymous Brave Guy ( 457657 ) on Monday December 09, 2002 @09:36AM (#4843234)

    Since no-one has yet pointed it out that I can see, it should be noted that what we're talking about here is parameterised types, and to a limited extent, parameterised methods. This is still quite some way from what you can do with serious generics in other languages.

    There is an obvious comparison with C++ templates here, and although those are not the best generics around themselves, they do have a few very useful tricks up their sleeves. In Java, you can now do parameterised containers, and to a limited extent you can do generic algorithms, although the lack of things like operator overloading cripples these from birth. You can't, AFAICS, do some of the funky stuff with traits classes, and things like template metaprogramming, expression templates and Andrei's tricks combining templates and inheritance -- the stuff that's used in several of the best C++ libraries today to give them an edge -- are out of the question for now.

    That's a shame, because one of the great things about C++ templates is that using them is pretty easy, but there's quite a bit of power under the hood for people actually implementing class and function templates, such as the designers of those libraries. That means improved performance and/or flexibility for Joe Developers everywhere, even if only a few people know and use the features under the hood.

  • by MobyDisk ( 75490 ) on Monday December 09, 2002 @10:00AM (#4843329) Homepage
    Too late:
    Sun ignored requests from the developer community to extend the Java core language. Now they finally listen, after Microsoft copied Java with C# and added generics [microsoft.com]. This is why Java has gone from the hottest thing since Starbucks, to yet another language. They didn't listen to their user base until 2 years after it was too late.
    Lessons learned:
    This is also why Microsoft is so successful - they constantly innovate, rather than sitting on their market dominance. I foresee Sun suddenly trying to play catch-up with new core Java features. I will enjoy reading the spin Sun puts on this, after saying for years that none of these features were necessary.
    • by addaon ( 41825 ) <(addaon+slashdot) (at) (gmail.com)> on Monday December 09, 2002 @11:39AM (#4843882)
      Sun (or at least the people I've spoken to at Sun, who do represent their company) never said that generics weren't necessary. They said, with surprising honesty, that no one had yet come up with an implementation of generics that made sense for the virtual machine. The current implementation of java with generics has been available for around 18 months (externally for what, 12 months?), and has been a compromise implementation, giving a highly requested feature at some cost, perhaps, in the potential beauty of the implementation. The reason that generics weren't included with Java 1.0 is that no one could agree on how to do them; Sun has since realized that they won't be perfect, regardless, but that it's time to push them out the door. Probably, their publication of this stuff is prompted by C# (which uses, more or less, the same flawed-but-usable implementation). But I really do respect Sun's restraint in trying to make it as good as possible.

      --
      • by DmitriA ( 199545 ) on Monday December 09, 2002 @09:00PM (#4849476)
        Wrong! C# uses a RADICALLY different implementation of generics - Java opted for 'erasure' approach because they needed to preserve backward-compatibility. So that means that all generic type information is removed by the compiler/translator and that code is replaced with polymorphic subtyping with casts (essentially, using the same collections of Objects but everytime you insert or retrieve an element, it will do a cast) - thus, horribly slow runtime performance.

        Next version of C# will support generics in the VM and that will remove the need for casts and allow you to do other nifty stuff like polymorphic recursion, getting specific runtime information that Vector is really that and not a Vector - in Java, you would have to look at the actual elements to determine that.
        In fact, Microsoft Research people that presented a paper on generics in .Net at PLDI '01 claim that this is the first ever implementation of generics with support in the VM itself. But I think if Sun had the time to do it in Java in the beginning, they would've opted for a similar design, but since they hadn't and now they can't go around changing all the VMs and losing compatibility with all the code that is out there, that wasn't an option for them
      • How precisely is java's new generics design flawed?
    • by pmz ( 462998 )
      This is also why Microsoft is so successful - they constantly innovate, rather than sitting on their market dominance.

      Sure they do. Microsoft is extremely good at seeing what other people are doing and, then, copying, buying, or squashing it to meet their agenda. In the case of C#, they first inhibited Java with their VM "embrace and extend" scheme, and then took Java, copied it, renamed it, and added a few things.

      I guess you could call standing on other peoples shoulders innovation, but that is a relatively weak use of the word. Microsoft is more like the business partner that is your friend right up to the point of stabbing you in the back and taking credit for your work.

      As for real innovation, I often wonder what "killer apps" were stifled over the years by Microsoft. Like weeds in a garden, Microsoft is always there...
      • Don't turn this into a pro-MS or anti-Java thread. The point is that everyone lauded Sun for creating Java, then they got lazy.

        I explicitly said that Microsoft embraced and extended Java. But all innovation is improving on existing ideas and adding your own. From the Franklin stove to alternative-fuel cars, to programming languages. The point is laziness. It took Sun 5 years to add templates to Java. In that same time span, Microsoft duplicated everything Java had, and more. Like it or not, that's a road to success.
    • This is also why Microsoft is so successful - they constantly innovate, rather than sitting on their market dominance
      <sarcasam> Oh, so that would explain why Outlook Express has improved *so much* since version 4.</sarcasam>

      I like OE. It has a clean UI, but it really hasn't changed since I started using it.

      • the rules system is too simplistic
      • it doesn't include the original author's name in an automatically forwarded email
      • going from next to previous message is awkward
      • memory management on newsgroups is inefficient
      • there should be plugins for binary decoders
      • I can't edit a list of file extensions which are "dangerous", so I have to open the settings window, flip to another tab, uncheck the "protect me from dangerous attachments", then save the attachment and go back in and re-enable the setting.

      The only really neat feature they did add was the junk filter, and that got removed thanks to some moron e-card quasi-spammer.

    • Look at processors. Sun leapfrogged HP, DEC and IBM with Sparc way back when. HP came back and did it to all of them; now IBM. In technology, there is always a feature/power/flexability leapfrog cycle where one vendor (including MS) pulls out ahead, and then later on another does the same. No news there...
  • Bjarne was right! :) (Score:2, Interesting)

    by Bish.dk ( 547663 )
    So it turns out that Bjarne was right in his interview [att.com] with Visual C++ Developers Journal in June 2000:
    Very little in Java is new to a student of programming languages, so there has been little effect on the C++ definition. In that area, Java is still playing catch-up (for example, I think it is just a matter of time before Sun will add a template-like mechanism to Java).
    -- Henrik
  • Don't forget to visit the Adding Generics Forum [sun.com] for more detailed posts about generics and other new features being added to Java.
  • For the impatient:

    The preliminary spec for generic types in Java is here [jcp.org].
    The Sun prototype compiler can be downloaded here [sun.com].
    And a forum for discussion of Java generics is also available [sun.com].

    You might also want to check out CodeGuide [omnicore.com]. This is AFAIK the only IDE which already supports Java generics as described in the spec (and is an awesome IDE for traditional Java as well).

    Enjoy!

    -- kryps
  • Great. Finally Java gets one of the features people so desparately need. Admittedly, Java is very cleanly designed, but I really find Java programming painful. Templates were one thing that was missing. Macros are another. Does Java have regular expressions these days?

    And really...the more of those missing features get added to Java, the more it gets to look like that other object oriented language with a syntax like C's...I believe it is called C++. Yes, I know objects are optional in C++, but they are in Java, too. int, float, etc. are simple types. Java is big, bloated, slow (yes it is) and a pain to program due to missing features. Once the missing features are added, and the speed is brought on par with other languages through compiling to native code, it will be just like C++. It won't be more portable, either. As far as I am concerned, Java is an expiriment, a failed experiment, to be exact. Go Python!!

He has not acquired a fortune; the fortune has acquired him. -- Bion

Working...