Submitted On 05-MAR-1998
HolgerK
The pizza language extension provides parameterized
classes und runs nicely in the JRE.
<a href="http://wwwipd.ira.uka.de/~pizza/">Take a
look</a>
Submitted On 14-MAY-1998
cd_smith
I'm not sure what Eiffel's "bounded" genericity is, so this may be a
repeat of ldwg's comments.
Please don't do the C++ hack where I can write a templatized method that calls
methods on an object when they may or may not be there. A parameterizable
class should declare some kind of minimal interface or class that needs to be
extended/implemented by the actual used class. Thus, current java.util classes
would declare themselves as parameterized on class Object, whereas I may
require that all objects in my new collection implement Cloneable (because some
operation in my collection requires that I clone them). It could, of course,
use the class to create a collection of a more specific type when I use it.
More usefully, I could create a collection which requires that elements
implement my own interface of advanced things I need to do.
As long as this requirement were fulfilled, I could support templates in Java.
If not, I'd rather have to downcast.
Submitted On 14-MAY-1998
ldwg
Generic classes with bound genericity (not the unbound version of C++ but
in the sense of Eiffel) is the most important feature I really miss in Java.
(Bound) generic classes would
<OL>
<LI>tremendously decrease the "conceptual overhead", because
you would not
have to create a new interface for your XYZVector but would reuse a
Vector(XYZ) instead.
<LI>increase performance, because many dynamic type checks during
downcasts
become redundant (as in "a = (XYZ)myEnumerator.nextElement()")
<LI>increase type-safety, because you could rely on the fact that a
Vector(XYZ) contains only objects which grant you the interface XYZ.
</OL>
The pizza language does provide generic classes (and other niceties like
high order functions) but it translates those constructs to plain bytecode
using the aforementioned design pattern with specialized subclasses and
downcasts. It therefore does not gain performance and does not provide
genuine type-safety if no source code is available --- after distribution
you cannot guarantee that ordinary objects are added to your Vector(XYZ)
which has been translated to a XYZVector still containing the inhomogeneous
methods to add/remove Objects. These inhomogeneous inherited methods could
be used by an application and would not be prohibited by the compiler.
What we really need is a byte code level solution. I think it is possible
to design the generics such that the old API remains source code compatible
if an omitted parameter is automatically set to the upper bound
(so "Vector" is Vector(Object)).
Submitted On 21-MAY-1998
jdmarshall
I think a good starting place for an implementation
of this would be to define a new data type that
corresponds to the parameterized type, which the
system classloader could use to quickly generate
the needed implementations of the class from a
classfile.
By tweaking a few rules of the JLS, you could
then dictate that all classes containing
PT's must be abstract. At instantiation
time, the appropriate (concrete) inner class
is loaded, for all situations where the need can
be predicted at compile time, or dynamically
created for code that relies on dynamic class
loading. A simplistic implementation should have
to do little more than a search and replace-type
operation on precompiled code.
Submitted On 21-MAY-1998
cd_smith
I'm not sure anything like this would be necessary to support parameterized
types. Maybe I'm wrong, but I think it should be simple, in the case of what I
described above, to implement parameterized types in the VM using only an
extension to the syntax of signatures.
If a generic container is written to hold only instances of Super, and
instantiated elsewhere to hold Subs, then it is compiled initially as a simple
collection of Super. The only difference in the class file would be that the
signature of the classes and methods would be somehow altered to indicate the
parameterization.
Compilers compiling code that uses this class (and instantiates it to hold Sub
instances) would use it just like it does now with Vectors, but there would be
no need for the checkcast instruction because the compiler can guarantee that
the (implicit) cast will be valid.
This would provide a simple implementation of parameterization with minimal
changes necessary for the virtual machine. I'm sure there are other issues,
but I can't think of them right now.
Submitted On 08-JUN-1998
ldwg
Cd_smith's definition of bounded genericity is fairly accurate ;)
The "bound" is just a class or an interface that is required for a
given
parameter, e.g. Cloneable or Ordered, e.g. in
public class OrderedSet<Ordered Element> extends Set<Element> { ...
}
But I see two problems concerning the introduction of generic classes in Java:
a) Changes of the syntax in the core libraries invalidate existing sources
b) Changes of the byte code require new byte codes and thus new run-time
environments
While a) can be "worked around" by a convention that any missing
class argument defaults to the given bound (so "Vector" stands for
"Vector<Object>"), b) is much more difficult: One *has* to
include additional
type information into the byte code to be checked by the verifier. This is
because one *cannot* rely on the validity of the compiler - just think of
hand-written byte code. To be able to omit the superfluous downcasts (in
the example, from "Object" to "Ordered") the verifier has
to check that all
parameter types are correct and thus needs the additional type information.
So for generic classes we have to
- change the syntax, improve the parser and rewrite nearly all major packages
- change the byte code, improve the code generator and type checkers (in the
compiler and class loader), and rewrite some parts of the interpreter
as well as just-in-time-compilers.
These might be the reasons why Sun is not too enthusiastic about adding
genericity, which is a pity.
Submitted On 09-JUN-1998
cd_smith
You are, of course, right. I'd forgotten about possible implications for
verifying code. I don't really know enough about verification to understand
all the issues here, but I'm sure they are significant.
Submitted On 10-JUN-1998
jdmarshall
ldwg:
It would be possible to write a classloader that
would accept classfiles that contain parameterized
typing information (ie, new additions to the classfile
specification, and JLS) and emit a Class object that
has been resolved to a perfectly normal JDK 1.1 standard
before the verification phase. I don't see how B) is an
issue, or why A) needs to be. You need to modify the
classloader, the classfile format, and perhaps new, but
you don't need to add new bytecodes.
Submitted On 10-JUN-1998
ldwg
jdmarshall:
Of course, A) does not need to be, that's what I am telling ;)
But Sun would have to rewrite some libraries to benefit most from
the new capabilities, e.g. Enumeration, Vector and all uses thereof.
The brand-new java.util.Collection of JDK1.2 would have to rebuilt,
too. Of course, the old sources would remain compatible, but users
would want to use the old mechanism as they are used to.
You are right in that you can produce 1.1-compliant code by
creating a class "VectorOfDummy" or "Vector$$Dummy" from an
instantiated class "Vector<Dummy>" and just use it as is.
Maybe I misused the term "byte code", I refered to the
classfile format and not the opcodes. I disagree about the
distinction between class loader and verifier since the check
of the vadility of a certain instantiation (e.g. a declaration
of a Vector<Dummy>) is clearly not a job for the class loader
which might nevertheless create any required (and approved) class
afterwards.
It is indeed not necessary to rebuild the main interpreter, my
fault :-|
Submitted On 25-JUN-1998
jdmarshall
ldwg:
I'm sure that'll really break a lot of people's hearts :)
I think it was fairly odd to even bother with a
collections API in the absence of parameterized types.
More to the point, removing all that casting on all
the listeners, all the hashtables of Strings or Dates
or URLs, etc, scattered throughout the code will
improve overall performance of the JDK. Frankly, I'm
amazed by how few people are voting for this one.
Submitted On 01-JUL-1998
97jaz
Well -- I did vote for this, since it seems to
be the "parameterized types" feature request, but
I want to stress that I am *not* in favor of the
C++ system. ML has the right idea.
Submitted On 12-JUL-1998
cd_smith
Okay, now you've got two of my votes.
22 and still counting! :-)
Submitted On 15-JUL-1998
jonathanfinn
This is a good intelligent discussion. Take a look at this MIT proposal for
Java PT's, at http://www.pmg.lcs.mit.edu/papers/popl97/popl97.html (I don't
think anyone's mentioned this). It looks well thought out.
Of course we need parameterized types and also asserts (these are my top 2
votes). For some reason there's a bit of a voting bandwagon for asserts - I
think PT's are much more important and I'm only vote no. 23! Are we the only 23
people who feel queasy having to cast every time we get an element from a
Vector??
Submitted On 16-JUL-1998
ldwg
I think the problem is not that many people do not see the need
for generic types, but that many people do not see the bug vote.
To vote for generic types, you must feel an urgent need and
actively search for the topic. Only topics in the top-25 will
remind people to deal with the problem.
I will try to convince some collegues to use their votes...
The Pizza group recently started a new project called generic java (GJ).
The project's home page is www.cis.unisa.edu.au/~pizza/gj.
Have a look at the participants, they are true experts in the field
(two of them stem from JavaSoft; nevertheless, GJ is not "official").
And no wonder, they did pretty fine, they even provide versions of
some util classes and the 1.2 collection stuff. The decision was to provide
complete compatibility with the legacy code (that is, a Vector is
byte-code-compatible with a Vector<Object>). The price to pay is the
remaining need for downcasts on byte code level and some small
inconveniences. The compiler seems to work fine, but does no optimization
(at the moment) and support tools (such as gjdoc) are still missing.
Nevertheless, a frequent and wide-spread use of GJ will probably make Sun
think faster.
Submitted On 17-JUL-1998
fbrueg
When you look at what features third party language extensions or tools provide,
IMHO it becomes quite self-evident that parameterized classes (along with
assertions, my other vote) should really be in the language. Unnecessary
casting just feels *bad*!
Submitted On 20-JUL-1998
MichaelFranz
As soon as assertions get into the language, PT's will get all three of my
votes.
I just happen to give asserions priority because they help trap all kinds of
programmer errors, not just casting errors.
As virtually everyone in this thread would agree, having to continuously cast
is not only dangerous, it causes unnecessary work for developers.
It seems that the entire world has forgotten what Java was originally conceived
for: TV Remotes and washing machines.
As far as I understand it, assertions were dropped because of time constraints
(comment JGosling) and multiple inheritance (probably PT's too) was dropped in
order to keep the runtime system small.
These are simply not issues for an OS390 or even a PC.
On a more constructive note: A good Eiffel->bytecode compiler could solve
some of these problems.
Submitted On 24-AUG-1998
jdmarshall
Apparently we won't be getting anything of this
sort in JDK 1.2. However, Hotspot does appear
to alleviate some of the run-time ugliness of
constant casting, if not the design time ugliness
of code snippet repetition.
If you read enough of the teasers for Hotspot,
one of the purported features has to do with code
of the form:
if (reference instanceof classname)
classname castedObject = (classname) reference;
The above code has two conditional checks to determine
if the second line of code will fail. The dynamic
compiler in Hotspot takes the initial check as gospel
and does a (not-so-)blind cast in the second line.
(This assumes Hotspot has deigned to recompile the
code, which is not guaranteed to be the case)
It's still just a stop-gap measure, if you ask me.
If parameterized types existed in the language,
the benefits of this little feature would diminish
greatly.
Submitted On 09-SEP-1998
IanHaggard
My votes right now are for decent Linux support,
but as soon as they address that, all my votes are
going here. While I agree that language-level
support for assertions would be nice, it's
possible to do your own. On the other hand,
generics/templates are a LOT harder to do without
language-level support. Moreover, genericity has
all the benefits of assertions or design-by-
contract in addition to its other uses -- it makes
your code and interfaces clearer and it fixes bugs
(at compile time, no less!). If you feel like I
do, I encourage you to post something to this
effect on the assertions discussion.
As far as bound/unbound genericity, I definitely
prefer bound, despite having a C++ background.
But if we're doing bound genericity, then we need
to be able to have signatures, not just
interfaces. In other words, lets say that I have
an algorithm (such as RSA) that works only on big
numbers, such as BigInteger or BigDecimal. How
can I genericize that algorithm so that it could
take either a BigInteger or BigDecimal? What I
want to do is create an signature like:
signature BigNum {
public BigNum add(BigNum);
public BigNum multiply(BigNum);
public static BigNum valueOf(long);
// etc.
}
generic class MyGenericAlgo
[MyNum implements Number signs BigNum]
{
MyNum recalculate(MyNum);
}
But right now, all we have is interfaces, and
I can't make a BigInteger retroactively
"implement" the BigNum. And moreover, there's no
way to specify a static member in an interface.
Anyway, what I'm trying to say is that while I
support bound genericity, I would prefer unbound
genericity in the absence of signatures. While
interfaces are very nice for object-oriented
programming, they are totally inadequate
for generic programming.
Submitted On 10-SEP-1998
ldwg
The subsequently addition of superclasses (or superinterfaces)
for existing classes is a severe problem. It is, however, not
necessary to introduce new types of interfaces when we require
"structural conformance" of interfaces for type parameters.
This requirement is not as strict as proper subtypes. An example:
interface Ordered<T> { public boolean less(T); }
OrderedSet<E implements Ordered<E>> { ... }
Without structural conformance, any element type E for the
ordered set would have to implement Ordered. Structural
conformance only requires that E defines a public method
"boolean less(E)".
Unfortunately, this mechanism does not fit well with interfaces
as polymorphic types. On the other hand, the introduction of
a new type of classes leads to a huge amount of reengineering
which I doubt is appropriate.
Submitted On 16-SEP-1998
chriskl
Just extend the Vector class to make something like 'IntegerVector'. Then keep
everything the same, just override the add methods to do type checking and then
pass the request to super.add...
Submitted On 18-SEP-1998
jdmarshall
I always worry about people who say 'why don't you just...'.
Besides, you're not extending Vector, you're repeating the
contents of the class, modulo the cast checks. If you don't see
why code repetition is bad in a software development environment,
then I'm woefully prepared to help you...
Genericity does have a useful place in a 'modern OO language',
and the most efficient and type safe way to accomplish that is
with parameterized types of some form, be it very limited or
otherwise.
Submitted On 29-SEP-1998
opinali
I want generic types, but let's lern the lesson of C++-versus-Eiffel: generic
types _demand_ stronger, sophisticated typing features (e.g. covariance,
"like" tagging). Pushing generic types into Java's current typing
strength is creating new headaches.
Submitted On 29-SEP-1998
bram3
I would like some sort of parameterization of
possible exceptions as well.
I have a place in my code where an interface's
methods may or may not throw an exception. For
the most part, creating a shared subclass which
has abstract methods with no exceptions declared
works fine, the problem occurs when a class uses
the common interface and just lets all exceptions
pass through. In that case, I have to resort to
using two identical pieces of code, one which
uses the more generic interface and throws
excepitions, and one which uses the excepion-free
subclass and throws none.
Submitted On 10-OCT-1998
stuartG
I am changing my two votes for "Covariant return types" to votes for
this one. It seems to have more support and includes covariant return types (I
believe). I think the best transition approach is to start with a JLS change
along the lines of the "Generic Java" project. Then start changing
the VM to make it more efficient.
Submitted On 12-OCT-1998
jorendor
Someone said: "...the introduction of a new type of classes leads to a
huge amount of reengineering which I doubt is appropriate."
I feel obliged to point out that the introduction of "signatures", as
defined above, would not require much reengineering. It is a compiler-only
change. The addition of "signatures" is much, much cleaner than
using real Java interfaces. An interface would be reflected in the bytecode; a
signature need not be. Also, the use of "x implements Izz" to mean
something other than "x actually explicitly implements Izz" is a very
bad idea IMHO.
The big question is whether to go the extra step and make changes to the
bytecode interpreter. A few fairly minor changes could fight the code bloat
that generic types can cause.
I'd be happy either way.
I'm astonished nobody's pointed this out yet, but when C++ compiles templates,
it does *not* let you "call methods on an object when they may or may not
be there." If you try and make such a call, the compiler will flag it as
an error. If a C++ compiler is well-written, it can generate error messages
that are identical to the nice messages you'd get from a bound-generic system.
C++ templates are great, but the learning curve goes awfully high. A bound
approach is more appropriate in Java.
I also agree that the Collections API is a joke, except inasmuch as Collections
might be incorporated into a generic framework.
Submitted On 16-OCT-1998
ldwg
Just my two cents again...
Unlike "syntactic sugar", type-related enhancements are not
"compiler-only"
if you require type-safe dynamic class loading.
Omitting signatures on the bytecode level means that the class loader cannot
dynamically check the conformance of class interfaces.
A well-written C++ compiler will indeed report errors during instantiation
of template classes. Unfortunately, they are reported rather late and can
point deeply into (inaccessible) library code. Explicite type bounds do not
only make things clearer but also allow instant checks.
Submitted On 19-OCT-1998
OlsonB
Does anyone else feel that templates mainly cause bloat
because of the code they write for you that you never see?
Interfaces are enough. I wish I could vote against this one.
Submitted On 24-OCT-1998
puzza
I get sick of casting! I'd like some compile-time safety.
It would be especially good to be able to specify a class and all its derived
classes in the template.
Submitted On 25-OCT-1998
sigjes
Why is not inner classes enough?
Let the generic (container) class have an inner class. The type of inner class
is set by a constructor parameter and stored in an instance variable.
Then run-time checking (essential!) is done as any run-time type checing, with
subclasses allowed. No new bytecodes !
The compile-time checking would be a pure Java Language & compiler
extension. In my opinion it is nice, but less important as stong type-checking
is always done at run-time by JVM.
An ugly version of this can be built in Java 1.2. Let the inner class be of
type Object, but check type of any new objects using operator instanceof. The
overhead is quite low. (Better implementations possible in Bytecode.)
Something similar may be done on parametric interfaces.
Changing Bytecodes and JVM can not be justified.
Submitted On 26-OCT-1998
jorendor
I think I'm replying to several people here,
so...
> Unlike "syntactic sugar", type-related
> enhancements are not "compiler-only" if
> you require type-safe dynamic class loading.
There are two answers: (1) have a generic class
compile into a special "generic class" file
(not a normal Java class) which the interpreter
uses to instantiate Java classes as needed. This
would require an upgrade of the Java runtime,
bytecode verifier and all.
(2) Compile a generic class at
compile-time into intantiations. Give the
instantiated classes mangled names, just like
inner classes. This is a compiler-only change,
even if signatures get involved and so
forth. The current bytecode verifier would
verify the generated classes, because they are
normal Java classes at the bytecode level. And
the generated classes would not have the
unnecessary casting required with Vector et al.
Type 1 avoids code bloat. Type 2 avoids
compatibility problems.
You seem to be saying that a type 1 solution
would be an "enhancement" but a type 2 solution
is merely "syntactic sugar". But both provide
the same functionality to the programmer! Sun
could come up with a syntax for generics first,
and *then* decide whether to go with a #1 or #2
implementation.
Again, either one would be fine with me as long
as we got *something* in the language *soon*.
> Then run-time checking (essential!)
[snip]
No, it's not. In the case of a Vector-like
data structure, all type checking can be done
once at compile-time and again at
bytecode-verify time, and no further checking
is necessary. Runtime type checking is a
needless waste of time--both run time and
programmer time.
> A well-written C++ compiler will indeed
> report errors during instantiation of
> template classes. Unfortunately, they are
> reported rather late and can point deeply
> into (inaccessible) library code.
Current compilers usually say something like
"no matching method for Fooz::compare(Fooz)
at line 23481"
But the compiler could just as easily say
"can't use template 'sort' with type 'Fooz';
'Fooz' would need a method Fooz::compare(Fooz)"
...if the compiler had been written that way.
And the compiler can catch this early if it
wants to. There's nothing in the standard
preventing a compiler from tracking what a
template requires from its parameters.
--
jason
Submitted On 27-OCT-1998
sigjes
>> Then run-time checking (essential!)
>[snip]
>No, it's not.
I didn't distinguish between run-time and bytecode verify-time. The separation
is merely an optimization, although included in the spec.
We both agree that executing bytecode should be type-safe.
I still can't see why type-checking could not be performed by bytecode in the
generic class. The same checks would need to be done
by a modified bytecode verifyer anyway, so speed penalty may not be large.
Submitted On 28-OCT-1998
sigjes
Another viewpoint:
The original request was for strong typchecking at compile-time. It seems he is
working with mission-critical applications, where type-errors stopping
operations is unthinkable.
If so, then everything needs to be checked at compile-time. No dynamic class
loading possible. And the compiler needs full type information also from
third-party libraries, somehow.
Submitted On 04-NOV-1998
David Silver
The MIT proposal for parameterized types shows that Java programmers would reap
a performance benefit by avoiding run-time type checking, in addition to the
inherent syntactic short-cut (no explicit down casts) and compile time type
saftey.
Also, the MIT proposal details a possible implementation without extending the
JVM. Although the performance is not as good as extending the JVM, it provides
an easy migration path.
Submitted On 05-NOV-1998
shecter
Even more important to me than parameterized
types is an elegant solution to the Java
Interface / MI 'problem'. The 'Jamie' project
has a very nice solution: multiple automatic
delegation. With this idea, good design is made
easy, and the point about MI or not MI is
basically moot. See:
http://www.list.org/jamie/
Submitted On 06-NOV-1998
noutram
This is similar to 4173702, could we merge the two?
Submitted On 10-NOV-1998
steveshort
I agree with the request for parameterized types.
I have been down the road suggested by the workaround,
i.e. creating my own typed container classes, but this
is a real drag. I no longer do this simply because of
the extra work involved - and have lost the type
safety that I'd like.
Submitted On 10-NOV-1998
strachaj
GenericJava appears to provide a good migration path whilst maintaining
backward compatability so come on Sun - we need better performance!
Submitted On 11-NOV-1998
jwj
In comp.java.lang.programmer I had argued for generic types. During the
discussion, two things became clear to me:
(1) The GJ approach was nice, but not sufficient. Ground generics need to be
first class objects, one has to be able to reflect them, to downcast to them
etc. GJ does not allow this, which is why I prefer the approach of PolyJ
(www.pmg.lcs.mit.edu/polyj) in this respect.
(2) I am not sure that subtyping constraints (the way GJ does bounded
genericity) is really flexible enough. Again, for an alternative, look at
PolyJ. Or Ada, for that matter, where one has to pass the manipulation
functions along with the types when instantiating a generic package.
Introducing parametric polymorhpism to the Java type system is an important
design step. I wish that the guys at Sun look at the various implementation
alternatives more carefully than they did when they implemented the AWT.
Submitted On 16-NOV-1998
jdcjdc
Here's part of what parameterized types should
provide:
class Foo
{
...
}
class xxx
{
void someMethod()
{
// create a vector of Foos
Vector<Foo> vec = new Vector<Foo>();
Foo temp = new Foo();
// check at compile-time that temp
// is of class Foo or a subclass of Foo
vec.addElement(temp);
Foo temp2;
// 1. check at compile-time that LHS, (i.e. temp2) is
// of type (or subtype) Foo.
// 2. explicit typecasting not needed
temp2 = vec.elementAt(1);
}
}
This does not need code duplication (as C++ does).
The Java compiler can thus easily assure type-safety. I
don't see what the big deal is in implementing
this feature into the compiler.
Note that C++ also allows ints, longs and other
types as parameters which cause considerable
code bloat (due to duplicate code generated by
the C++ compiler). There are some advantages to
this method (mainly speed), but the disadvantages
outweigh the advantages.
So, I'd settle for just type-safety provided
by parameterized types. Note that for this
ease of implementation, only descendents of
Object can be used for parameters. Using
primitives like 'int's or 'float's will
result in code duplication.
Submitted On 23-NOV-1998
cyrild
Check out Polyj http://www.pmg.lcs.mit.edu/polyj/
It looks really cool, although I understood
all the differences to C++ . (where clause)
Submitted On 23-NOV-1998
cyrild
You get my vote.
I checked out
<a href="http://www.cis.unisa.edu.au/~pizza/gj/"> Gj
0.6</a>
It's not Open-Source, and it's not a preprocessor.
Submitted On 23-NOV-1998
strachaj
Check out Virtual Types in Kresten Krab Thorups article on the subject. It's in
postscript and dvi
and postscript at: http://www.daimi.aau.dk/~krab/resume.html#Publications
It's a very elegant implementation of a form of parameterized types they call
'Virtual Types' which only changes the compiler slightly - no runtime changes
necessary.
Let's vote for 'Virtual Types' instead!!!
Submitted On 23-NOV-1998
artlum
As far as I can see, it will be impractical to do C++ "templates" in
Java, as different object code needs to be created depending on whether you
want the template to work with objects, arrays or primitives. C++ can handle
this by using the preprocessor at compile time. Java cannot do this as it is
run time based. So before we start, I think we need to distinguish between
"templates" and "generics". Many C++ users fail to see the
difference. Generics to me means "type safety".
On this premise, perhaps we need to restict any system of generics in Java to
things which work with Objects and arrays of Objects, no primitives or arrays
of primitives.
This simplifies things greatly. At the practical level it means the compiler
can just look for references to "Object" in method parameters and
return values, performing static type checking as appropriate during the
compilation.
If we don't restrict ourselves to objects then we open a big can of worms.
Imagine a classloader trying to adapt the Vector class to accept integers and
you'll see what I mean. New code would have to be created on the fly to deal
with the integers, and this isn't pretty. You'll get massive code bloat as each
paramterised class instance makes new code for itself, you'll probably need
operator overloading to be able to write things like generic quicksort, you
might even need the source code to be able to do it at all!
Restricting ourselves to objects seems sensible and gives us the required
static type checking
with a minimum of fuss, it doesn't need any new bytecodes, just a new
classloader (and this is only needed for the case when a generic-ised class is
passed to a method).
Examples:
Suppose we declare a Vector of MyObject:
Vector<MyObject> v = new Vector();
Case 1: Calling methods of Vector which return Object.
The code:
MyObject o = v.elementAt(0);
Is converted by the compiler to the equivalent of:
MyObject o = (MyObject)v.elementAt(0);
This saves typing and makes the code look neater.
Case 2: Passing things to the Vector
The code:
v.addElement(o);
Is converted by the compiler to the equivalent of:
v.addElement((MyObject)o);
This gives us a lot of static type safety. It makes it impossible to store the
wrong sort of object in v.
case 3: Passing v as a parameter to other methods.
Suppose we call a method with v as a parameter:
foo(v);
The method needs to be defined as something like:
void foo(Vector<>) {
}
This means that foo expects a "typed Vector" as a parameter. If you
try to pass a "vanilla" vector then you'll get a compile time error.
The classloader then needs a mechanism to let foo() know the type of Vector
being passed, and foo() needs to do typechecking inside as in cases 1 & 2
above.
You could (of course) also define foo as:
void foo(Vector<MyObject>) {
}
This restricts foo to working with a Vector of type MyObject.
<hr>
I think these simple changes would give us the static type safety which is
currently missing from Java without breaking much. Trying to add generics which
can deal with both objects and primitives would appear to cause more problems
than it's worth.
Submitted On 30-NOV-1998
s871161
if KEEP debuger protocol and 64Bit addressing then able to allocate Big object
is TEMPLATED Array only.
so before 64 bit support, prease support template.
Submitted On 10-DEC-1998
phillip2
This absolutely gets one of my votes. The
tension between generic (and therefore resusable)
code and compile time safety that exists in java
is really not good at all. The delegation solution
is nice enough I suppose but is only any good
if you all of your methods for affecting the
data are in the delegated class. As soon as you
want to use code external to the delegate then
the system fails. Some method for genericity
is vital if Java is not to throw away many of
the advantages that come with strong typing.
I cant comment on how easy the different
mechanisms are to implement or even very much
which mechanism is best but Java really needs
this badly. At the moment Java is a bit of a
"half-way" house solution, which is what C++ was
10 yrs ago....
Submitted On 15-DEC-1998
jdcjdc
I want to point out that Java is different from
C++ in that all Java classes are derived from
a single class 'Object'. This is not so with
C++. Languages like PolyJ add complicated syntax
to Java (the 'where' clause). A much simpler (and
elegant) solution is possible.
Here is a sample:
// dots added to preserve indentation
class Base
{
. // Base's way to add
. int add(int a, int b)
. { blah blah... }
}
class Descendent extends Base
{
. // yet another way to add
. int add(int a, int b)
. { blah blah blah... }
}
// Note that both Base and Descendent are
// derived from the 'Object' class
// this class allows you to only add objects
// of type 'Base' and its derived classes
// like 'Descendent'
template <Base T>
class MyVector
{
. // anObject can be of type 'Base' or
. // 'Descendent' or any derived class of 'Base'
. // The added object will not lose its identity:
. // a 'Base' object will remain as 'Base'
. // a 'Descendent' object will remain as 'Descendent'
. void add(T anObject)
. { ... }
. T elementAt(int index)
. { ... }
}
class xxx
{
. // comparision of old java and template techniques
. void test()
. {
. Base base = new Base();
. Descendent desc = new Descendent();
. // plain old vanilla vector
. Vector vec = new Vector();
. MyVector<Base> vecBase = new MyVector<Base>();
. // similar to: MyVector vecBase = new MyVector();
. // To use only Descendent and not Base use:
. // MyVector<Descendent> vecDesc = new MyVector<Descendant>();
. // compile-time check: base is of type 'Object'
. vec.add(base);
. // compile-time check: base of type 'Base'
. vecBase.add(base);
. vec.add(desc);
. // compile-time check: base of type 'Base'
. vecBase.add(desc);
. // get objects
. Base b;
.
. // type-casting needed
. b = (Base)vec.elementAt(0);
.
. // no type-casting needed
. b = vecBase.elementAt(0);
. Descendent d;
.
. // type-casting needed
. d = (Descendent)vec.elementAt(1);
. // type-casting needed!
. d = (Descendent)vecBase.elementAt(1);
}
Although type-casting has not been eliminated,
it is reduced for most of the cases. This is
better than PolyJ's method, which is slower and
breaks polymorphism.
Submitted On 30-DEC-1998
sorotokin
More specifically: I vote for PolyJ (MIT proposal).
Also I do not like casting from DerivedFromT[] to
T[]. It is nessesary in Java without parameterized
types (for things like Vector.copyInto()),
but is bad because it defers some type
checking for run time. Just realize that simple
a[i] = b almost always involves some type
checking! (In addition to boundary checks).
How can you can claim "almost C++" speeds
with that!?? PolyJ can be done very efficiently
and also "where" clause is very nice idea.
Submitted On 31-DEC-1998
duale
I think you guys are retarded. JAVA _DOES_NOT_
need templates!!!!! Get it through your thick
heads!!! Templates are a hack for programmers
too damn lazy to implement interfaces on objects
and primitive date types.
The fact of the matter is that parameterized
types are so friggin complex, both to read
and write and compile and build, that they
would add a huge amount of overhead to any
compiler. You goofballs might think polyj
and pizza are good starting implementations
of templates, but those compilers are purely
at the prototype stage!! Upon close inspection
you will find them severely limited and broken.
JAVA does not need templates. If class X
needs methods Y on class Z, then class X should
ask for those methods in interface I, and class
Z should explicitly implement interface I.
There should NOT be a hack such that class
Z only has to have the methods I by name and
class X could use this, thereby removing all
compiler-time checking and what not.
If you're building a huge complex data-structure
based system or whatever where templates are
a must-use, then write C++ code!!! But don't
corrupt the clean JAVA language spec just
because you want JAVA to have every goddamned
language feature created, because then JAVA
will wind up being another ADA or even worse,
C++.
JAVA _WORKS_. I have never had any need for
templates or multiple inheritance, and anybody
who thinks they need that garbage doesn't know
what OO truly is.
Submitted On 31-DEC-1998
jessh
Generic classes -are- sorely missing from Java.
It is, of course, important to do them -right-,
but even C++'s templates can be easy to re-use
and avoid code-bloat -- if someone carefully
designs the template classes. Java should do
better, especially in the ease of design category.
I believe a solution that does not require VM
modifications, but could optionally benefit
from them would be ideal (e.g. an approach
designed for specialized JIT'ing of generic
classes).
A final comment: though they can certainly be
handled in a different fashion from objects and
arrays (to avoid code bloat in the latter cases),
a parameterized type mechanism for primitives -is-
necessary. This could be purely compile time with
full code bloat as there aren't that many
primitive types in Java and the programmer is free
to factor out type-invariant code into helper or
base classes.
Submitted On 02-JAN-1999
jdcjdc
The template feature is extremely powerful and easy,
and has spread like wild-fire to a lot of languages
(Ada, C++, Eiffel, ML etc). Java does almost
everything that C++ does with a much easier
syntax.
I don't think Java needs all template features,
mainly primitive data types (int, float...).
If these primitive data types are added using the
C++ compiler way, code bloat will result, else
there will be no code bloat (well, a couple more
bytes for each instance of an object). If the PolyJ
method is used compiler types, the code size will
not increase significantly, but it will be slower
(the classic time/space tradeoff). After eliminating
all primitive data types, all remaining classes
are subclasses of Object. In C++, there is no single
root class like Object. Therefore, code bloat cannot
be avoided. However, the root Object in Java
makes template implementation trivial. Look
at this oft-repeated snip:
Vector vect;
SomeClass inst;
...
// inst is downcasted at runtime to type 'Object'
// which wastes some time
vect.addElement(inst);
...
// the element at position 0 is upcasted
// from Object to SomeClass at run time
// thereby wasting time
// Also, notice the irritating (and error prone)
// typecasting required
inst = (SomeClass)vect.elementAt(0);
With templates (generic types to be more specific),
type-checking is done at compile-time, and no
casting is required, making the program run faster.
Most programmers want to avoid extensive casting
(typecasting was intended to be used in exceptional
situations only, and not meant for common programming
pratice.)
I have found this casting 'disease' only when
using collections like Vector, Stack, HashTable.
If anyone is not already sick of casting, they
will soon be with the addition of the 'Collections'
package to the Java 2 platform.
Bottom line:
1. Type-casting is error-prone
2. Type-casting creates ugly looking code
3. Type-casting makes code run slower
4. Generic types are definitely cool and a must
for all modern programming languages.
5. Generic types will save us from subclassing
every know class a million times to add type
safety
Submitted On 11-JAN-1999
kwaclaw
Have a look at
http://www.daimi.aau.dk/~krab/virtuals.ps
Submitted On 11-JAN-1999
yminsky
I just want to add my vote of support for generics -- ideally bound generics,
i.e., using singatures. The lack of typesafety and excessive typecasting
require by Java is ridiculous -- and it's not just a problem for container
classes -- it's a problem for many kinds of extensible frameworks. Please fix
this, and soon!
Submitted On 11-JAN-1999
yminsky
I just want to add my vote of support for generics -- ideally bound generics,
i.e., using singatures. The lack of typesafety and excessive typecasting
require by Java is ridiculous -- and it's not just a problem for container
classes -- it's a problem for many kinds of extensible frameworks. Please fix
this, and soon!
Submitted On 14-JAN-1999
dleuck
1 vote for parameterized genericity (not templates). I would like to see a
PolyJ (MIT proposal) -like implementation. VM spec changes are necessary to
implement this language feature efficiently. Any hackish implementation that
object-wraps and unwraps primitives left and right is not acceptable.
Admittedly, VM changes can be problematic and cause major headaches but
sometimes scotch tape doesn't do the trick. Make the change now before it's
too late. While your at it add multiple return values (I believe James Gosling
has mentioned he liked the idea). This would also alleviate object creation
overhead (creating containers simply to hold multiple return values.)
Submitted On 25-JAN-1999
jsando
I am happy to see so much lively discussion on what is a critical missing
feature of Java. Each Vector or Hashtable I create makes me wince, knowing
that there's one [more] potential problem the compiler can't help me find. Not
to mention having to cast all over the place. Do the ideas being discussed
include something for a typed Iterator or Enumeration?
Submitted On 26-FEB-1999
kriff
I've switched my vote from assertions to templates.
This is something that would be really useful to
have.
Interfaces aren't enough. To implement a typed
interface similar to Iterator<A> in Java today
would need a seperate interface (and implementation)
for each actual type we're interested in. For
example, you could create interfaces called
IntIterator, FooIterator, ByteIterator, etc. Each
of these would require a seperate source file
even though its the same interface with only
minor changes. Now suppose you want to add a new
method to your interface. You'd have to manually
track down each of the seperate interfaces and
make the exact same change over and over. This
is a wasteful and boring way for a programmer to
spend his time, which certainly is not what OO
is all about.
If Sun does implement these features, it must be
done without adding unnecessary bloat. Ideally,
the runtime system (ie the JVM) would be modified
to take parameterized types into account. If that's
not possible, then the compiler should insert the
required casts and bridges (similarly to GJ)
automatically. Under no circumstances should the
compiler generate seperate classes to implement
each use of a parameterized type. The cost in
file size far outweighs any performance benefit
(especially for Applets)
Submitted On 26-FEB-1999
pharmakon
This is the feature I would most like to see
added to Java. I cringe every time I have to
write an explicit cast.
Submitted On 26-FEB-1999
Danny the Kid
In refrence to suns undated "evaluation":
I don't see why Sun is trying to make a
compatibility issue here. The way I see it if
you don't specify a type for the template class
then it should becomes a template for Object...
This way old code can compile with the template
based classes. It doesn't seem like
compatibility would be at all a problem. Am I
missing something obvious here?
Submitted On 03-MAR-1999
jdcjdc
I'm interested in your opinion about this implementation
style for generic types:
Old Java style declaration for Vector:
class Vector
{
public void addElement(Object o) { ... }
public Object elementAt(int index) { ... }
}
class MyInteger extends Integer
{
...
}
// use Vector
static void foo()
{
Vector vect = new Vector();
Integer i = new Integer(5);
MyInteger mi = new MyInteger(10);
vect.addElement(i);
vect.addElement(mi);
vect.addElement(new Double(5.0));
// type-casting need to retrieve any object
i = (Integer)vect.elementAt(0);
ni = (MyInteger)vect.elementAt(1);
}
Java with generic types included:
// T can be Object or any descendent of Object
// (i.e.) any Java class other than primitive
// data types
generic <Object T>
class Vector
{
public void addElement(T obj) { ... }
public T elementAt(int index) { ... }
}
class MyInteger extends Integer
{
...
}
static void foo()
{
Vector<Integer> vect = new Vector<Integer>();
Integer i = new Integer(5);
MyInteger mi = new MyInteger(10);
vect.addElement(i);
vect.addElement(mi);
// can't do this: only Integer and classes
// derived from Integer can be added
vect.addElement(new Double(5.0)); // compiler error
// type-casting needed only to get a descendent
// of Integer
i = vect.elementAt(0);
ni = (MyInteger)vect.elementAt(1);
}
Not only does this eliminate some type-casting,
it allows the creation of a vector that holds
only integers.
Submitted On 03-MAR-1999
AWKay
This one gets all three of my votes. In addition,
I would like to vote for the GJ implementation,
since it fixes the most horrendous problems for
generic containers (instanceof and casting)
without changing anything but the compiler. I
also particularly like the fact that existing
_binary_ classes can be generalized by
changing the internal attributes in a JVM
compatible fashion.
My only gripe with the current GJ compiler is
that is doesn't have a command line switch that
allows the programmer to turn unchecked warnings
into errors.
Submitted On 06-MAR-1999
ins
From my point of view Java clearly does not need any parameterize type or such
a stupid things like template a la C++! Please, keep Java the Language clean
and simple – the most valuable asset it has. For those who very needs
parameterized facilities I would recommend mostly concentrate on design with
Java, rather than trying to use your old C/C++ tricks in new environment. Wake
up!
Submitted On 11-MAR-1999
Unland
Why don´t write a little Java-tool wich creates
classes-source from a template before compile-time?
Classes build this way are also typesafe and no
change in the Java-standard is necessary.
Submitted On 21-MAR-1999
tbreuel
Please do NOT add C++-style templates or
Eiffel-style bound genericity. I believe
both of them are ad-hoc designs with limited
expressiveness and serious technical problems.
I'd strongly recommend looking at the
SML module language for an approach to
genericity that has minimal impact on the
base language, does not instantiate templates
haphazardly, and allows for type-safe separate
compilation.
Submitted On 25-MAR-1999
tovj
Yuck!
The intensions (Compiletime type safety) of the original poster cannot be
solved. You'll need
to check type at runtime anyway, so this feature will only be bloat since you
cannot depend on it
in any reusable class design.
It is quite possible today to make an extension of any Collection class to
demand the use of Integer only.
This feature is bloat in it's purest form. People
who want generics can use pizza.
Please don't turn Java into C++.
Submitted On 30-MAR-1999
AWKay
I am appalled at the lack of understanding of many
of the individuals posting comments here. Parameterized
types _are_ important in _good_ object-oriented
programming, and they need not be C++ templates.
If you are truly an intellectual, and have an
objection to parameterization, read on and hear
me out. Otherwise, I take it you are an individual
who is simply posting comments as an emotional
response to change (the "all change is bad"
mentality).
Quick example:
void draw(LinkedList shapes)
{
ListIterator i = shapes.listIterator();
while(i.hasNext()) {
Shape s = (Shape)i.next();
gr.draw(s);
}
}
Where is the type safety in this call??? Someone
modifying this program can easily
add some instance of Foo to the LinkedList
and throw the whole thing out of whack
_at runtime_! The only way to fix it is with
a check like:
while(i.hasNext()) {
Object obj = i.next();
if(obj instanceof Shape) {
Shape s = (Shape) obj;
gr.draw(s);
} else {
System.err.println("Internal error: bad list entry");
}
}
...
Which adds significant overhead and complexity
to the routine. Also, bugs in the program are
discovered at run-time perhaps weeks after a
change is made elsewhere in the program.
A very simple, compiler-only solution to this problem
is parameterization by erasure (as is done in GJ,
see the pizza web site). This code can then be
changed to:
void draw(LinkedList<Shape> shapes)
{
ListIterator<Shape> i = shapes.listIterator();
while(i.hasNext()) {
Shape s = i.next();
gr.draw(s);
}
}
Easier to read? definitely.
Implementation? Read on:
Only one copy of LinkedList is needed, since Java
has an ultimate supertype (Object) that can be
used for that implementation at run-time. The
compiler can enforce these rules purely at
compile-time according to the stated rules of
the source code:
- You must pass a LinkedList that contains only
Shapes, or subclasses of Shape
- Elsewhere, the LinkedList will also have to
be declared as a list of Shapes, and the
compiler will dis-allow insertion of
anything except Shapes.
This has the following benefits over the first
one:
- Adds type safety at run-time with a _compiler_ fix.
The compiler complains about a Foo being put
in the list.
- Eliminates the need for most instanceof and casting
operations, which speeds up algorithms and makes
code easier to read.
- NO extra code is generated
Good parameterization need not create the nasty
code bloat of C++, and it need not be difficult to
use or understand.
If you want more information, read the information
on GJ, pizza, etc.
We are NOT asking for C++ complications. I personally
_hate_ C++ templates, but from an implementation
standpoint. From a design standpoint I see parameterization
as absolutly critical to good programming.
All three of my votes are on this feature request.
Submitted On 31-MAR-1999
jdcjdc
In case some numb skulls did not get the point, I'm
restating the previous article:
...
static void main(String[] args)
{
ListIterator<Shape> shapes;
ListIterator<Point> points;
ListIterator<Integer> integers;
}
In C++, the compiler will create 3 classes from
above code and compile them:
ListIterator$Shape, ListIterator$Point, ListIterator$Integer
All the 3 classes have the same code except that
the template type is replaced by Shape, Point or Integer.
This is the main reason for the code bloat.
Java does not have to follow this style - there will
be a single class, ListIterator.
Since all the parameter types (Shape, Point and Integer) are
descendents of Object, all calls are handled by polymorphism.
The compiler can ensure at compile-time that
objects added to the iterator belong to parameter type.
Thus there is no need for run-time checking (although it
can be provided optionally.)
Submitted On 09-APR-1999
aelberg
I totally agree that this is the biggest flaw
in the present language spec. I am not familiar with
the CS terminology; I just know that I want typesafe
collections.
Submitted On 26-APR-1999
Ray Burns
I am strongly in favor of adding parameterized types (but not templates) to
Java.
For a related issue, see bug ID 4222792.
Submitted On 12-MAY-1999
steelman
A proposal for this has begun.
Look here:
http://java.sun.com/aboutJava/communityprocess/jsr/jsr_014_gener.html
Submitted On 18-MAY-1999
jdcjdc
I hope the JSR gets approved.
IMHO, the last constraint, C8, is most
important for wide-spread acceptance.
<start C8>
C8) Good performance of generic code.
Code written to use the generics
feature should not be a lot slower
or a lot more memory-intensive than
non-generic code. Using ten percent
more space or time than
non-generic code may be acceptable;
using twice the space or time is not.
<end C8>
As far as space is concerned, there could be
hidden data members for each parametric type.
Eg:
generic <Integer X, Boolean Y>
class Foo
{
// compiler adds one member per parameter type
private Class XParameterType;
private Class YParameterType;
...
}
class MyBoolean extends Boolean
{
...
}
Now, when an instance of the class is created,
the hidden members are automatically assigned
values by the compiler code.
void main()
{
Foo<Integer, MyBoolean> f =
new Foo<Integer, MyBoolean>();
// behind the scenes, in the constructor
// of Foo, f.XParameterType is set to
// Class("Integer") and f.YParameterType is
// set to Class("MyBoolean")
}
This information does not require too much space;
4 bytes for each parameter type.
So when is this information useful? Usually never.
1) It is useful only when casting from an 'Object' or
an ascendant of Foo to 'Foo<Integer, MyBoolean>'.
2) It is useful when serializing/deserializing
an object.
3) It is useful for supporting the Java reflection
mechanism.
Other than these circumstances, checking can be
done at compile-time. In old Java, all objects
are converted to 'Object' and then casted back
to some class which wastes time. With generics,
there is no run-time casting check.
In other words, the generic class code will
execute at full speed, 99.9% of the time.
Submitted On 03-JUN-1999
jtr
So, what's going on with the generics JSR? It looks like
it failed. Can it be restarted?
Submitted On 10-JUN-1999
jdcjdc
They seem to have no problem approving silly
proposals. When it comes to major changes, it
takes them forever. I wonder if generics or
design by contract will ever make it into Java
Submitted On 14-JUN-1999
MichaelFranz
According to...
http://java.sun.com/aboutJava/communityprocess/jsr.html
...parameterized types have been "approved". Anyone know what this
means (if it means anything at all)?
I just hope they provide for Eiffel-style constrained generic types.
Submitted On 15-JUL-1999
vnitsch
Not quite sure - there is javacc wich seems "easy"
able to extend java-grammar.
instead of some predefined syntax using kind of a extendible compiler-compiler?
must be able to mix different grammars, of course :-)
Submitted On 15-JUL-1999
vnitsch
for syntax: dont hide generics in the body! no "void x(){
Vector<int> a;..}"!
take something like:
import awt.*;//and so on
import dynamic Vector {int} IntVector;
import dynamic Vector FloatVector {float};//like the "int[] x" &
"int x[]"
and then java!
by the way, since MS would like it: hold the
"(MyClass)a.elementAt(5)" option
even where not needed! Much better readable than
"m_plxvzA.elementAt(5)" !!
compiler can drop it, no runtime-overhead; I hope they hear me!
--- syntax-features of my approach (1) ---
- syntax not possible in old java, so unused.
- imports more readable, cleaner.
- rest of code is old java.
- today "easy" possible with prepros, perl, help of classloaders
and finally new compilers.
- once created, no new creator-runs needed
(faster ecl than c++, ide's without preprocessor happy :-)
---> ! using java really for templates could look like this:
(may the forth be with you :-)
--- (2) ---
import dynamic Lookup{ int, {"one",1,"two",2,
"three",3} } ThreeValues;
// ^ clever "LookupGenericCreator" can create 3 if's..
import dynamic LongStrings SomeLines {
header till END
-HTML-
-TITLE-
END
footer till END-
-/BODY
-/HTML-
END //are spikes allowed in the reply?
} ; //all this bean-source-makers like it :-)
//hear i XML?
--- features of (2): ---
- Cloning the way of Beans:
"GenVector" has "GenVectorGenericCreator.class",
which is called by the compiler on import.
- free syntax in arguments possible. Dynamic Creation.
- Can do its own stuff:
hyper-clever recursive c++ template-metaprogramming for optimized matrices?
when you can do the source-creation with some println() and normal java?
or JPHYTON :-)
- no source-changes, if we use simple "import" also for dynamics:
if there is a *GenericCreator available, it is used, so old *.class
can be extended simply be dropping a file.
- Cloning the way of activation framework :-)
- the needed classes can also be createt with GJ, PolyJ?!
- and javacc will like it :-)
problems i see:
- flexible but inconsistent Syntax of parameters. also features
- all Creators isles, no global analysis like eiffel.
but at least strong typechecks by compiler&loader.
- and the long LongString's in imports :-)
--- i prefer seperate classes, instead of automatic casts, ---
which then call the generic base.
-- as mentioned, no changes to java after the imports!!
-- space:
--- in memory they should be a few vtable-pointers more, code can be shared,
--- for the files there is a specialized ClassLoader, which can pretty compress
(name of the base and the replace-parameters).
-- speed should be better than casting.
-- hotspot
-- hotspot will inline heavy, so if you have methods with much casts
you will get one code-version for each combination.
blows code like more classes, i think.
I expect hotspot is more optimized for method-invocation than for casting.
*(classloaders? good idea! hi jdmarshall, would suggest similar.
"keyname.dynamic.smartloader.replacein.mypackage.GenVector$MyElement$Integer"
with a mypackage.GenVector as base for the smart
and additional an imp of the full name on the web-page for old loaders.
(i allways feel classloaders should have an option which
dumps its really loaded classes somewhere for minimal distribution)
also there is a plugin-way for old vm's & applets,
where the ClassLoader is not changeable: a proxy.
i've seen a proxy somewhere, which translates names in applets (not testet).
(thinks like awt.Window to safer.MyWindow, which is restrictet to max 5 open).
Submitted On 16-AUG-1999
derbyshire16
One use for parametrization besides type safe genericity without loads of
dynamic casts, is policy parametrization -- which can be a a performance boost
to certain kinds of code, including algorithm type code.
It should also be easy to implement since Java already supports and always has
supported run-time *class creation* as well as dynamic linking. In C++ the
manner of template instantiation is a serious stumbling block and a major area
where implementations differ incompatibly. Multiple or missing definition link
errors tend to pour out of the linker like water out of Niagara Falls. java can
neatly dodge those problems. The biggest work would be adding the syntax,
standardizing and specifying it, and fixing up javac. The lesser work would be
instantiation, there'd just have to be a special classloader. And flexible
class loading is already in Java too -- ClassLoader, SystemClassLoader,
URLClassLoader, user-defined ClassLoaders, resource bundle classes that are
manufactured on the fly using text properties files that have nothing to do
with .java files or bytecode... Most of the underlying framework is already
there, unlike when templates were added to the evolving C++ and it totally
couldn't fit the original linking paradigm inherited from C without all kinds
of crufty crocks and glue used to make templates work with the linker... I've
seen how several compilers do this and man is it ugly, compile, link, catch
unresolveds, compile, slow, slow, swap, swap, out of memory, out of memory ...
another forces you to use pragmas to specify one .cc file to instantiate a
template in ... evil pragma evil pragma no no NONPORTABLE CODE! ... another
uses a repository and this must be managed somehow... then we have namespacing
problems and other difficulties ... All rwquire different ways of deploying the
code...some the templates in .h; some in .cc; some in both and with pragmas...
so much for C++'s Write once, Compile anywhere.
Java has it beat.
I vote for this one.
Submitted On 16-AUG-1999
adam@organic.com
Please be sure to generics as they relate to
exceptions (not just return types).
Submitted On 20-OCT-1999
CvR
The main flaw in proposals like GJ is that they don't allow primitive
types. Surely a Vector of doubles is only useful if the doubles
don't have to be wrapped in Double class instances!
The main objection seems to be that this causes code bloat,
but I wonder if this is really so significant? I haven't seen figures
from real life, but I suspect that in many programs this is not
as significant as people suggest. Also, a smart compiler
could prevent most code bloat by only generating separate
copies for the primitive types, and one for all reference types.
Although I vote for generics, I am against the current versions
of GJ and PolyJ. Both lack support for primitive types. GJ looks
more like a hack to minimize the inpact on Java as much as
possible instead of a well-designed language extension.
PolyJ (and Pizza, in for that matter) look better designed.
Submitted On 28-OCT-1999
Jwong
I have another suggestion. Allow type-checking to be turned off and simply
rely on
method/signature matching to determine the correctness of messaging. (Ala
Smalltalk.)
Optimize toward the positive, not the negative!
Submitted On 04-NOV-1999
dkf
CvR: The problem is that adding support for primitive type
parameterisation is much nastier than just supporting it over
objects. It also leads to wanting to parameterise over methods
and stuff like that. C++ went down that road, and it leads to
a place that we *really* don't want to go...
Jwong: No. Type-checking is important. It is one of the
reasons why we do not write everything in assembler with a
macro preprocessor. You might not care about the security
and correctness of the code you use, but I sure know that I do!
Submitted On 12-NOV-1999
tipparam
I agree with CvR. Parameterized types would be more useful if they
supported primitive types. For example, look at Arrays.java of new collection
classes in JDK1.2. It has almost identical implemention of sort1() method
for each primitive array, int[], short[], long[], ...etc. This wouldn't be
necessary
if parameterized type (when they are available!) supported primitive types.
(BTW I am not criticizing the implementation of the collecion classes!)
Submitted On 16-NOV-1999
dkf
The problem with permitting parameterisation with primitive types
is that the primitive types are not related to any other types.
There is no type-containment relation with them on either side,
whereas the class hierarchy gives us a nice set of relations that
are pre-existing and fairly intuitive in practise (with the general
lack of surprise involved being a Good Thing.)
The result of this is that it permits an implementation of param.
classes that is pre-compiled (primitive types require the source
file to be rewritten by the compiler each time you use a param.
class) and it also means that you can leverage the existing
idiom of passing callbacks via implemented Interfaces. (This
keeps the change to the language small.)
Allowing parameterisation over primitive types is klunky by
comparison (since the bytecode you need to emit is utterly
different) and stems from the fact that the primitive types are
pretty clunky themselves. I can understand why they are in
there, but they make the type-system of the language much
more complex and less orthogonal.
C++ templates pretty much require completely different
implementations for each instantiation of a template, and that
is very messy. Java should, where possible, avoid C++'s
mistakes (and make its own!) and a non-blecherous param.
class mechanism is one which is actually fairly easy, since you
can do all the stitch-up work you need (not very much either)
at class-load time.
Submitted On 02-DEC-1999
gusw
Parameterized classes for compile-time type safety is something I always missed
in Java. This run-time up-casting is a catastrophe! It gets especially bad
since inerited methods are not allowed to return extended types. So consider
this a vote for adding parameterized types into Java.
Submitted On 03-DEC-1999
dkf
Just to add grist to the mill, failure to restrict the type of keys
to a hashtable cost me several weeks work, because I had one
spot where I'd exchanged the key and the value in an insert.
There were no checked errors, and the basic integrity of the
program was maintained; it just produced the wrong answer.
(Well, in fact it never terminated, since the termination condition
depended on a hash-lookup that always failed...) This little
story just serves to illustrate why type parameterisation leads
to significantly higher quality code; because it helps all us
programmers to say what we *mean* and have the computer
check it for at least some sanity... :^)
Submitted On 15-DEC-1999
jdcjdc
Primitives are a nightmare to implement in generics (the C++ template fiasco).
In C++, you have to have the C++ source code for a class to use it in a program,
the binary (.obj object) file won't do.
It's easy to support primitives using the wrapper classes: Integer, Double...
Vector<Double> v = new Vector<Double>();
v.add( new Double(1.5) );
v.add( new Double(3.0) );
double d;
d = v.elementAt(0).doubleValue(); // element # 0
d = v.elementAt(1).doubleValue(); // element # 1
This does require a bit of typing... but that is a small price to pay for
simple and clean design.
Submitted On 15-DEC-1999
sch1
No, jdcjdc, using wrappers like Integer does not qualify as support for
primatives.
Heap allocations are around 1000 times more costly than an int assignment, and
everytime you want to change the value of a single array element will require a
heap allocation ( and garbage collection of the old value ), since the wrapper
objects
are immutable. This cost is unnacceptable for a large variety of applications.
If primatives are not supported then the (many) people unwilling to pay this
price will
have to hand code or macro-generate the source for the primative collections,
then will have to maintain all versions independently or else continuously
regenerate
them.
That is silly. I am not the only one who thinks the cost of the wrapper
solution is
exhorbitant. My class named "IntVector" always has a name collision
whenever I use
it in a JComponent subclass. Guess what the Sun IntVector does?
Submitted On 29-DEC-1999
ray
The URL no longer works.
Submitted On 07-JAN-2000
dkf
I think you're out of luck since it is an order or two of magnitude
more complex to create a ClassLoader that will perform the
rewriting necessary to handle primitive types. That's the way
the JVM is implemented. Furthermore, primitives don't have
methods and are not part of any non-reflexive type relations,
so you would also require the addition of parameterisation
over arbitrary methods, etc. This is going down the same
road that lead to C++ generics, and that is a real mess. The
far more restrictive version proposed for Java does not suffer
from these other problems, but it incurs the cost of only
allowing parameterisation over Object types. There's no easy
way round this so far as I can see.
Submitted On 11-JAN-2000
hwc
Generic types will be useful even if they don't allow you to use primitive
types
but I don't see why they shouldn't.
Given the GJ model, the author specifies class X< A implements Fred > or
class Y
< A extends Fred >. This is vital if you are to avoid run time errors -
the compiler
can tell the author when he/she is trying to do something that Fred doesn't do
and tell the user when he/she is trying to use it on something other than Fred.
In the collections example, Vector< A >, A is assumed to be an Object.
Most of
the time it will be but Vector< int > needs to be coded differently.
Indeed, if the
concern if for efficiency, it *should* be coded differently.
Why not allow specialisation (a la C++)? Vector< A > matches Objects but
when
the compiler comes across Vector< int > it looks for that instead.
I realise this may make the class loader's job a little more complicated but
it's whole
lot easier than true generic types for all the reasons DKF points out.
Submitted On 18-JAN-2000
ldwg
Sure - it would be nice to use primitive types for templates to
achieve performance.
However - it would break with a language design decision made much earlier,
which was to separate "first class" Objects featuring reference
semantics
and primitive types featuring value semantics.
This was one of the decisions that made Java slow. While it was fine for Sun
to make the compiler as much optimization as these tools can provide and by
that making things for programmers easy, this does not work for value types.
Consider Strings, for instance. String objects contain a reference to a
char[], which leads to three data objects for a series of 16bit unicode
data (the String, the array, and the references data). While one could
expect a clever optimizer to remove the reference to char[], none of these
really does. This might be because the array is not private so StringBuffer
can refer to the array - which could be detected by a global analysis only
- and these are in no way ideal for just in time compilation.
Therefore the programmer should be able to give hints to the compiler
when it is feasible to use value semantics instead (types Complex and Point
are other examples). In C/C++ one would simply omit the pointer (*),
and in Eiffel there are embedded data types. In particular, the bad
performance of Strings is one of the reasons why C-written compilers
(e.g. jikes) are several times faster than any Java compiler I am aware of.
If you would want to insert primitive types as generic parameters,
and have type bounds for each of your parameters (which I believe is
important), what do you do with primitive types? For instance, how can you
express that a parameter should be a discrete numeric type (byte, short, int,
long) only? There is no notion of subtyping between them.
Now, there are several alternatives:
1) Drop the type bounds for parameterized classes and fall back to the
ugly C++ template solution, or
2) Allow primitive types as type bounds of parameterized classes thereby
violating a basic design decision and introducing an odd exception in
the type rules, or
3) Introduce value types and relate primitive types to them thereby completely
reworking the Java type system (note that in Java 1.0 there was a reserved
keyword named "value"), or
4) Leave out primitive types for templates.
I would argue for 3) but I expect 4) to happen.
Submitted On 20-JAN-2000
LiyuL
So far total runtime checking has not been able to beat compile checking in
efficiency and bug prevention. Runtime bugs are horrible and too difficult to
rule out. If java is to really make a dent in software development, I would
like to see some of these features done. Otherwise we got bloated code ran
extremely slow. The question is whether this is the philosophy of java? I
believe more in C/C++ for the efficiency that is necessary for industrial
software.
Submitted On 01-FEB-2000
hammerc
The problem is that usually a function is not written for all classes
like is a container but it can only work with certain classes e. g. a
sorting algorithm works only with items that can be compared.
So only classes which can be compared by a member function
should be allowed to work with the algorithm.
Therefore my proposal is not to introduce templates like in C++:
template <class T> void sort(T container)
but to integrate the Interface concept of Java:
template <Comparable s> voin sort(s container)
In this template only classes which implement Comparable are allowed to
be used. Thus it is clear that only classes are sorted, that can be
compared and the sorting algorithm can use compareTo.
The same concept can be used for classes. A priority queue can only
contain objects that can be compared, which means that they are
instances of a class that implements Comparable.
If a class implements Comparable and thus is allowed to be used
in this template must be checked by the compiler.
The algorithm then only may use member functions of the given
interface or class.
By that errors in the code can be located very soon at compile
time.
Submitted On 10-FEB-2000
jdcjdc
Has anyone noticed a quirk in GJ's syntax?
interface FooInterface { ... }
class BarClass { ... }
If I were to create a method that accepted two parameters,
a FooInterface and a BarClass, it would probably look like this:
void myMethod(FooInterface foo, BarClass bar)
{ ... }
But GJ has a strange syntax. For class C that accepts two
generic types:
class C<T1 implements FooInterface, T2 extends BarClass>
{...}
The words 'implements' and 'extends' are redundant for the same
reason that they are unnecessary in 'myMethod()'. The compiler
can figure out that FooInterface (or its descendant) is indeed an interface
and that BarClass is indeed a class.
The syntax should be similar to that used in methods:
class C<FooInterface T1, BarClass T2>
{ ... }
Submitted On 12-FEB-2000
eddiebenowitz
It is imperative to add generics as soon as possible. Especially with the
collection
framework, programmers need this abstraction.
Submitted On 24-FEB-2000
jimof
What state is the JCP proposal to add Generics in?
I have been waiting to hear something about them for quite
some time (Feb./Mar. '99). The proposal was closed as of
Jun. 99.
So, any *real* indications (more than just guesses) as to
when this enhancement might make it in, 1.4 perhaps? It
sure would be nice.
Submitted On 08-MAY-2000
rogerhb
When you use C++ templates the compiler actually generates
new classes as needed. There would actually be very little
needed to write a program that generated container classes
source code for specific classes. Eg, a solution to fix a
problem rather than change the Java language itself, look
to sensible source code generation to solve the problem.
Then you actually see what overhead you get, rather than
having it hidden by 'templates'.
I find it rather amusing that to solve the code bloat of
using MFC for ActiveX/COM programming you are recommended
to use ATL!
Submitted On 09-MAY-2000
priyankajain
just imagine, no more (String) vector.elementAt(i)
Submitted On 08-JUN-2000
jtr
Anyone here the "futures" part of the BOF at JavaOne? I had
to
leave the Generics in Java BOF early... hopefully the
slides will
be put up somewhere
Submitted On 14-JUN-2000
dale@sclnz.com
While I agree that the Java language should grow part of
it's success is its elegance and simplicity. Look how much
has been implemented already without templates. Some things
are needed see bug# 4144488 but this only goes to make code
simpler to read. One of the reasons C++ has templates is
that it has no top-level (root) Object type, thus to have a
generic purpose class gets more tricky. Do we really want to
see methods defined like in C++
template<class K, class V> V& Mapiter<K,V>::value()
{ if (p) return p->value; else return m->def_val; }
[ from The C++ programming language, Bjarne Stroustrupt ]
Complexity breeds complexity. The main issue here is
stronger compiler time checking of types. The generic
system used by Ada seems far more readable than C++.
http://www.adahome.com/rm95/rm9x-12.html
Here I propose a easier to read syntax...
generic class GenericStack( A )
{
public void push( A ) { .... }
public A pull( ) { .... }
public void clear( ) { ... }
public String toString( ) { ... }
}
Notice its generic not simply abstract, I see no reason
not to have both. (Inside the JVM the generic methods could
be marked as abstract. Maybe the generic keyword isn't even
needed since you have parameters on the class def.)
class IntegerStack implements GenericStack( Integer );
class StringStack implements GenericStack( String );
class Stack implements GenericStack( Object );
The java complier generates Stack.class, StringStack.class
etc. Yes it doesn't have the "flexability" of C++ but it
keeps the language simple and powerfull.
Whatever you do please don't go down the C++ template route!
And think very very carefully before changing the java
language.
Submitted On 16-JUN-2000
hmmueller
Someone wrote:
"So far total runtime checking has not been able to beat
compile checking in efficiency and bug prevention. Runtime
bugs are horrible and too difficult to rule out."
On the contrary, the use of Smalltalk in huge and numerous
projects has shown that static type checking is not
necessary (what IS necessary, is type checking in general -
C and many C++ programs dont use even runtime type checking
... one can interpret a sequence of bits as anything!).
Also SQL, Java RecordSets, many GUI frameworks and C/S
tools show that people can live with unstructured "heaps of
data" (a few Strings, arrays) instead of real types (or
rather classes).
What wouls be nice, is the (IMO almost trivial) change that
subclasses can restrict the return type of a method to a
subclass. This allows us to get rid of the casting nuisance.
HMM
Submitted On 04-JUL-2000
javabandit
First, this does NOT get my vote in its current form.
IMHO, its way too complicated behind the schenes in its
current form to be a part of the JLS.
I'm all for strong type checking when it comes to
collections. But lets keep it SIMPLE. It should NOT be
added to the language syntax itself. Its not worth the
changes to the VM.
Sun... you should do two things. Allow the definition of a
collection taking a CLASS as a parameter which defines its
type. Don't use the C++ syntax. Do this:
Vector myVec = new Vector(Point.class);
MUCH more Java-esque. Then permit the explicit assignment
of an object within a collection without a cast. Nothing
more. Just allow this:
Point p = myVector.elementAt(0);
Let the compiler do the job of ensuring that _myVector_
only has items added to it of type Point. If _myVector_
passes the type check, then bytecodes should be generated
which correspond to the following line:
Point p = (Point)myVec.elementAt(0);
Bingo. Type safety within collections. We don't need
primitive-based collections, we don't need templates, we
don't need changes to Java syntax.
All we need is stronger compile-time checking of typed
collections. Its no wonder Sun can't get anything
worthwhile into this language with all of the proposed
bloat.
Submitted On 05-JUL-2000
br29operrd
A small comment re: Javabandit's idea. How can the compiler
distinguish between those collection classes that take a
parameter of type class and exisitng java classes that take
a parameter of type class for some other reason?
Maybe use of a marker interface (like "implements
Paramterized") could be used?
Submitted On 05-JUL-2000
javabandit
br29operrd:
To me, the marker interface is the Collection interface
itself. Right now, there are no collection-based classes
that I know of which take a Class object as a parameter
anywhere.
It would be pretty trivial for Sun to add the necessary
constructors to the Collection based classes. Again, this
would only provide compile-time checking, but that's all
that was asked for in this monstrous RFE, I think.
I really feel that everyone should try to keep it simple.
Getting Java stable and keeping it that way is of utmost
importance. But risking changes in the VM and syntax is
bound to just introduce more bugs for us to contend with.
Submitted On 11-JUL-2000
pvloon
JavaBandit,
I share your concerns, the last thing I would want are C++ template nightmares
(have a look at the STL implementation if you dare! Does the 'typename' keyword
ring a bell? Have you looked at compile-time implementations of calculating constants
[ const int n = Fib<8>::fib; ] ? I sure wouldn't want *that* in the Java language).
The main concern indeed is about downcasting because a container contains Objects.
Your hint about using a <Class>.class argument seems clean, but what does it imply
for someone trying to build classes? How would one define methods returning 'strict'
types?
In your example, how would elementAt() in Vector be defined?
public class Vector {
...
private Class param;
public Vector (Class param) {
...
}
public ????? elementAt (int index) {
????? value;
....
return value;
}
What should be at the '?????' ?
In the current implementation of Vector 'Object' is there, we would like that
the class given by 'param' is there.
How would you write that down?
public ObjectOfClass(param) elementAt (int index) {
ObjectOfClass(param) value;
....
return value;
}
and then:
v = new Vector(SomeClass);
...
Point p = v.elementAt(index); // Point derived from SomeClass?
would be interpreted during compile-time like:
(Java like description of what the compiler tries to do)
try {
p = (ObjectOfClass(param))value
} catch (CompileTimeException e) {
throw new ClassCastCompileTimeException();
}
with the try-catch and cast being only 'virtual' i.e. done at compile-time
So, how would you want to do this all without changes to the language
specification?
Submitted On 13-JUL-2000
javabandit
Schapel,
Look, I am not the only one who is suggesting this
approach. Any ideas which are thought through for YEARS
aren't necessarily good ones, and any ideas which seem
simple and straightforward aren't necessarily bad ones. If
you want examples of 'good' ideas gone wrong, I'll give you
a VERY large list. Especially where computer languages are
concerned.
So pull your nose down out of the clouds for five minutes
and come talk with the rest of mankind now.
I read the GJ docs. And they pretty much do the job. Do I
think they do the job the way *I* think it should be done?
No.
Do ALL of the other Java programmers out there think they
did it the way it should be done? No.
Are ALL of the other Java programmers who disagree with
that approach idiots? In your mind... maybe yes. In
mine... probably not.
The approach I proposed has been echoed in several previous
posts in this forum. And those posts I felt were
thoughful. I'm not bringing any kind of a genius
breakthrough to the forefront by what was in my proposal.
We're not talking about table-top fusion here. We are
talking about how to bring compile-time type checking of
collections to Java without risking the stability of the
language itself, and without greatly modifying its syntax.
Some people here think GJ is the answer. Some people here
think Java needs the runtime type-checking as well
(especially for serialization -- which GJ does not easily
support) which would require substantial modification to
the JVM. Some people think that other simpler approaches
are best.
I have always figured that a simple solution is better for
most things.
In Java, you can add 2 + 2 in two ways:
First method of adding 2 + 2
=============================
int total = 0;
int firstNumber = 2;
int secondNumber = 2;
for (int i = 0; i < firstNumber; i++) {
total++;
}
for (int i = 0; i < secondNumber; i++) {
total++
}
System.out.println("2 + 2 = " + total);
** OR **
Second method of adding 2 + 2
===============================
System.out.println("2 + 2 = " + (2 + 2));
Well.. I know which one I'd choose. And I don't have to be
a mathematician to make that educated guess. ;)
-- Rick
Submitted On 13-JUL-2000
schapel
I also get the impression that the ideas presented here
recently haven't been thought through well. If you disagree,
I suggest that you go to the page
http://www.cs.bell-labs.com/who/wadler/pizza/gj/index.html
and read about the GJ extension to the Java language. This
extension adds generic types and covariant return types to
the Java language without a change to the JVM. If you see
a problem with that implementation, I'd be very interested
in your comments. If you think you have a better way of
implementing generic types, please point out the weaknesses
in GJ and explain why your proposed method is better.
But before you make any comments, realize that GJ has been
written by a group of experts in computer science and Java
and they've been working on GJ for years! If you don't put
a similar amount of effort into your proposal, we'll be
justified in telling you it hasn't been thought through
well. :-)
Submitted On 14-JUL-2000
schapel
"Java Bandit",
Please re-read my posting. I absolutely *never* said
anything remotely like "GJ is good because it's been thought
through."
Again, if you think you have a better way of doing things,
please describe it. At the same time, tell us *why* you
think your way is better.
Submitted On 15-JUL-2000
javabandit
schapel,
Okay, I re-read your posting. Here is what you said (my
apologies to the others here for quoting) :
"But before you make any comments, realize that GJ has been
written by a group of experts in computer science and Java
and they've been working on GJ for years! If you don't put
a similar amount of effort into your proposal, we'll be
justified in telling you it hasn't been thought through
well."
Well, I don't know how else to take that series of
statements. By your words, you figure that an idea
isn't 'thought through well' unless it takes the same
effort that the GJ has. Then you state that because some
people in this forum haven't spent years developing their
ideas, that others are justified in discarding them. That
is what you said.
I've already said what my idea is. And its not really
different than many alternative suggestions within this
lengthy RFE.
Assume the following statements:
Vector<String> myVector = new Vector<String>();
String myString = "Foo";
myVector.addElement(myString);
String tempString = myVector.elementAt(0);
When the compile comes across Vector<String>, it would
dynamically create a .class file which represented a Vector
that can only contain Strings. Perhaps
called "Vector$$$String.class" or something of that
nature. This .class is then used is every place that the
Vector<String> is referenced. The generated .class file
would have all of the necessary methods implemented to
return TYPED values. For instance, the elementAt() method
for "Vector$$$String.class" would return a String object
instead of an OBJECT itself.
Now, we can also get more complicated with the syntax if we
like:
Vector<Vector<String>> myComplexVector = new
Vector<Vector<String>>();
myComplexVector.addElement(myVector);
Vector<Vector<String>> tempComplexVector =
myComplexVector.elementAt(0);
In the same way, when the compiler sees
Vector<Vector<String>>, it dynamically creates a .class
file representing a collection the same way
that "Vector$$$String.class" did. If no type is specified
for the collection, then a standard Vector is used
(Vector<Object>).
What do we get from this? We get compile-time type
checking of collections. We don't have to do a downwards
cast when pulling items out of Vectors. Because we are
generating .class files, we also get RUNTIME type checking
also. At runtime, trying to add an Integer object
to "Vector$$$String.class" would throw an exception of some
sort. We also get backwards compatibility.
We could get these things with minimal adjustment to the
syntax of the language and without modifying the VM at
all. Now, this solutions does nothing to address 'const'
or 'strict', or collections of primitives which other
people in this forum want, but I feel it does address the
original issue at hand concerning typed collections.
That is my idea. I'm all ears to hear why its worse. It
didn't take years for me or anyone else to figure it out.
It's a simple approach to achieve a simple problem. I
don't see the need to complicate this issue with a bunch of
bells and whistles that we really don't need in this
language.
-- Rick
Submitted On 16-JUL-2000
schapel
"Java Bandit",
Here's a program using your scheme of compile-time type safety with generics:
Vector<String> vs = new Vector<String>();
Vector v = vs;
v.add(new Integer(3));
String s = vs.get(0);
According to your scheme, this is what the code would compile to:
Vector$$$String vs = new Vector$$$String();
Vector v = vs; // this is legal because Vector$$$String is a subclass of Vector
v.add(new Integer(3)); // this is legal because of the add(Object) method in Vector
String s = (String) vs.get(0); // this gives a ClassCastException
If you read page 1 of the tutorial on GJ, you'll find this statement:
"GJ comes with a cast-iron guarantee:
no cast inserted by the compiler will ever fail."
The point is that the type safety comes not from simply having the compiler
insert casts for you, but also ensuring that these casts don't fail.
The bottom line is: yes, your scheme is simpler than GJ, because you
removed the type safety! But without the type safety, what's the point?
It's not that GJ is good because it's been thought through, or that yours
is bad because it hasn't been thought through. The idea is that the authors
of GJ can make that "cast-iron" guarantee because they have thought
matters through. If you don't make a similar effort in thinking another
scheme through, you won't be able to make such an cast-iron guarantee,
and thus you have no evidence for claiming that that scheme is as good
as or better than GJ.
Submitted On 16-JUL-2000
javabandit
schapel,
Good point about extending Vector. The upwards cast is
indeed possible, so in that case, we'd have to extend
Object. Thinking about it now, we couldn't even extend
AbstractList because AbstractList also is not typesafe. So
for the purposes of the dynamically created generic
classes, they would directly extend object.
So then, the line...
Vector v = vs // This is legal because...
Actually won't even compile. With that said, are they any
other reason why this is not rock solid?
pnkfelix:
Good points. Except see above. I'm not saying
StringVector should extend Vector. All generated generic
classes should extend Object directly. As schapel pointed
out, extending Vector means you can upwardly cast the
Vector and add an object of a different type.
But you have pointed a side-effect to this approach. And
that is that a .class file will be generated for every
generic type declared. Although, I don't think that it
will be too much. There would only need to be one
generic .class generated for each typed collection. On
large projects, it could get more sizable, but I think its
a good trade off. For not having to change the VM
internally, or mangle the syntax.
-- Rick
Submitted On 16-JUL-2000
pnkfelix
Rick (aka javabandit)-
The problem with your proposal is that it leads to size
blowup, in the form of a seperate class for every
type-instantiation of a given generic type.
One could make each newly-generated class a subclass of the
base generic type (thus Vector$String extends Vector) and
this could cut down on the size of the individual class
file, but then there are still issues in terms of whether
the generated class file exports methods as add(Object) or
add(String)... I haven't thought through the issues with
making Vector$String a subclass thoroughly at this point,
but it doesn't seem trivial. The size of such "trivial
subtypes" may not matter, since obviously Sun has taken a
similar approach to handling support for inner classes, but
I don't like the looks of it.
There's a fairly nice report
<a
href="http://www-ics.ee.ic.ac.uk/surp99/report/caj97/intro.html">here</a>
on the various proposed designs. Its about a year old; I'm
not sure what else has been added since then.
I *do* agree that it would be a mistake to shove excessive
support for additional features in with this proposal.
An example of this are primitive type parameters. I've read
some arguments about that (such as the ones given <a
href="http://www7.software.ibm.com/vad.nsf/Data/Document2712">here</a>
) but i do appreciate Java's simplicity.
In general, GJ's approach seems good to me (which is good
since it also seems to be what Sun is going with). I used
(and hated) polyj in a software engineering course a few
years ago... it was more like "lets graft CLU onto Java
(thus "where" clauses, etc). Thorup's "virtual types" make
me gag.
-Felix
ps. one last thing. Some comments are asking why the syntax
is
Processor<N extends Number> instead of Processor<Number N>.
I personally *like* the former syntax since it consistently
allows for multiple constraints on a single type (ie,
Processor<N extends Number implements Cloneable>). But I
don't care enough about which choice is made either way, and
I have to admit the latter syntax is more consistent with
the Java way of denoting arguments (but we're not just
denoting arguments, we're also denoting a type (much like a
class declaration), which is why I can easily accept the
extends/implements syntax)
Submitted On 18-JUL-2000
schapel
"Java Bandit",
Here's a program that uses your latest and greatest proposal
for "type-safe" collections in Java:
Vector<String> vs = new Vector<String>();
ListIterator i = vs.listIterator();
// Note: This cannot be ListIterator<String> because in
// your proposal you have no way for a parameterized class
// to implement a parameterized interface; parameterized
// classes simply extend Object, as you have specified.
i.add(new Integer(3));
String s = vs.get(0);
This would be compiled to:
Vector$$$String vs = new Vector$$$String();
ListIterator i = vs.listIterator();
i.add(new Integer(3));
String s = (String) vs.get(0); // ClassCastException
Again, your proposal is not type-safe. Before you try to
quickly patch this latest hole in your proposal, I suggest
you think through how you would write a complete and
unambiguous specification, and how much work it would take
you to provide users of your scheme a "cast-iron" guarantee
that the casts that are added by the compiler are safe. My
guess is that a fully type-safe proposal would not be much
simpler than GJ, or it would be far less useful. Feel free
to prove me wrong by writing up this specification and
actually demonstrating that it's simpler than GJ, just
as safe, and still anywhere near as powerful.
Submitted On 18-JUL-2000
dkf
(I had a long comment to make, but damned bugs in Sun's
software kept on slinging it all in a bit-bucket.)
It is possible to add generics to Java with only a rewrite
of the compiler (obviously!) and a change to the
ClassLoader. No other changes are needed, and those that
are should not affect backward compatability.
Genericity over object types is good, particularly since it
is based on a well-understood subtype relation, and can be
implemented without rewriting JVM instructions, but rather
just class names. Generics over primitive types,
"functions" and constants don't have this good property, and
in the latter two cases, are better served by other existing
mechanisms.
The kind of preprocessing proposed by javabandit doesn't
work nicely, since you need the instantiated class to be in
the same package as the generic class, even if creating
classes in that package is a priviledged operation. There
are some covariance problems though, so instantiated generic
classes must not be subclasses of the generic class. There
is a need for a different type-relationship here (gen/spec
IIRC.)
Parameterisation adding .class is not good, since the class
substitution has to apply to arguments and return values; it
just jarrs badly with the rest of the language IMHO.
Parameterisation using the keywords "extends" and
"implements" is not necessary, and unreasonably cluttered.
Using angle brackets makes it clearer in a constructor
invokation what is a class parameter, and what is a value
parameter.
Submitted On 18-JUL-2000
gbishop
I don't understand why you people want this, and I fear it.
Why not just make the compiler a bit smarter, and have it
handle removing the cast at compile time?
I had a case where I had things that descended from a
parent class that were placed in a collection, along with
other similiar things, and I had to pull out one of the
parent class things, and inspect it before I could cast it
to the final type. But you see this sort of problem all
the time in Java, and any other OO language. Wouldn't a
better solution be to allow evaluation of objects using
switch statements or a similiar mechanism?
EX:
void actOnTheThingsInHere(Vector v){
for(int x=0;x<v.sizeOf();x++){
Object obj = v.elementAt(x)
switch(obj)){
case ClassName1: //Do something...
case ClassName2: //Do something...
case ClassName3: //Do something...
}
}
}
Submitted On 19-JUL-2000
pnkfelix
gbishop-
>> I don't understand why you people want this, and I fear
it.
I'll admit, I want this for somewhat selfish reasons. I'm a
compiler researcher, and a lot of the code I write uses
mathematical Sets and Sequences and Maps as basic types.
What's more, I often see things like Maps from (Variable
and Instruction Pair) to (Sets of Instructions). Right now,
I have to write my code like this:
Map duChains; // (Var, Instr) -> Set of Instr
and put all the casts in and hope I'm consistent with what I
do.
Inevitably, I mess up in a few spots (often when fiddling
with exactly what is mapping to what) and have to fix what
I'm trying to pull out of my Collections; but I'm always
worried that there may be some code path that I forgot to
include in my test cases where I pull the wrong thing out
and do a bad cast, getting a runtime error. Or worse, I
hand off this Map to somebody else who proceeds to put all
sorts of crazy incorrectly typed mappings into it before
giving it back to me.
Yes, all of this can be resolved with careful specification
and code review. And yes, I could also write my own DuChains
class. But that's a lot of useless wrapping code: there
already is a well defined syntax for specifying generic
types in this manner, and a well understood method of
automatically having the compiler review the code for you!
This is right up there with static typing as a HUGE win for
the programmer! I can just specify
Map< Pair<Temp, Instr> , Set<Instr> > duChains;
and the compiler will check that the rest of my code is
correctly typed for me, allowing me to focus on the REAL
bugs.
Now, a lot of people who AREN'T doing this sort of work look
at generic types and say, "what's the point" because all the
projects they've worked on haven't attempted nesting the
generic collection classes to this level. But this is a
classic example of something where you truly don't pay for
what you don't use. If you prefer the old way of specifying
genericity, its COMPLETELY compatible with GJ, and you don't
have to change a single line of your code.
I suffered through generic types when they were forced down
my throat and I didn't see the use of them then. But since
moving on to projects with such a mathematical mindset, I've
come around to really appreciate GJ's approach. (ps. anyone
know what's up with GJ support being included with the javac
in jdk1.3?)
-Felix
ps. for your example of doing a case-statement: the "Visitor
pattern" is a well known approach for handling that case,
though it requires that you've established your object
hierarchy ahead of time to be incorporated in the Visitor's
equivalent of a case-statement. You should check it out.
In any case, its not really what we're talking about here.
Submitted On 19-JUL-2000
schapel
"gbishop",
The RFE is about compile-time type safety. The mechanism you
propose is not type safe. For example, if you pass me a
reference to your Vector v, I can write
String s = (String) v.get(0);
If you put an Integer into the Vector, I get a
ClassCastException at run time. The bottom line is that you
don't force me to use your mechanism, so you have no way
of enforcing the type safety at compile time.
If you read the proposal of GJ at
http://www.cs.bell-labs.com/who/wadler/pizza/gj/index.html
you'll see a truly type safe mechanism that cannot be
subverted. If you have an alternate proposal, post it here
after first ensuring that it is actually type safe. If it
isn't, it doesn't address this RFE.
Submitted On 19-JUL-2000
pnkfelix
One last thing I will note; with Generic Types, the type
declarations can get kind of heinous. Like in my example,
Map<Pair<Temp,Instr> , Set<Instr>> duChains;
is a real mouthful. Do people here think that if this
feature is added,
we're going to need something like a "typedef" statement
soon afterwards?
Hopefully we can avoid adding a new keyword, maybe something
just
like:
interface DuChains = Map<Pair<Temp, Instr>, Set<Instr>>;
can do the trick? (Where now the word "DuChains" would be
equivaIent to declaring that full type statement?)
I haven't played with the java grammar enough to know if
this would wreak havoc with the parser, but it doesn't seem
like that big a leap to me. Its more of a leap in mindset,
and I admit I'm not sure if I would be pleased or displeased
to see this added to the language...
Submitted On 20-JUL-2000
mharbon
You guys are screwed, and this RFE is screwed. It doesn't
provide runtime type safety. anything less sux.
schapel... GJ is a friggin hack. It is nothing but a piece
of garbage 'pre-compiler' that doesn't support casting of
parameterized types and no runtime type checking. How the
hell are we supposed to use EJB and serialization with any
confidence? How the hell are we supposed to provide any
kind of runtime typesafe distributed solution if we have to
pass Object all over the place. Its stupid.
So what you guys are saying is that we should include
Generic Java in the language, just to rip it out again when
Sun decides to implement a REAL solution to parameterized
types and parametric polymorphism. and we all know its
going to require a complete rewrite to the JVM and the
compiler. Anyone who thinks different is an idiot. All
these quick solutions. What a bunch of losers.
You guys are all screwed. Nothing but bunch of kludge
masters looking for the quick fix. GJ is just another
kludge that doesn't know diddly about its parametric types
at runtime.
Hell, why not just forget it all, and buy Rational Rose and
have all of our code auto-generated for type safety.
Forget Generic Java. Its nothing but a stupid code
parser. BIG DEAL.
This RFE sux, and all you supposed C++ gurus who support GJ
are losers. Leave Java alone and go buy your damned CASE
tools and use THEM instead.
... unless you want to implement a REAL solution to
parameterized types.
Submitted On 21-JUL-2000
pnkfelix
mharbon-
You say that we're asking for Design by Contract. This RFE
is *not* about Design by Contract. There already are enough
flame-fests going on about that in the "Add assertions to
the Java language" RFE.
This is about adding a more expressive type system to the
Java language. You continue to bring Distributed Systems
and EJB and CORBA into the discussion, but those issues are
independent of this one.
We're just talking about giving the compiler more
information about our program so that it can check things
*STATICALLY*. And for the purposes of my work, that's all I
need. I understand that your programs have much wider
requirements, mainly with regards to Runtime checks, and so
you want a larger revision to the language; but the simple
truth is that demanding such an overhaul isn't going to
make Sun listen.
If you're touting C++ as a dream language, then you may have
some problems getting support in here; I see C++ as a
nightmare. Maybe if you had used Eiffel as an example or
something to that effect... perhaps you should look at the
NextGen proposal yourself, it performs transformations that
are reminescient of C++ templates to acheive the Runtime
checking that you have been clamoring for.
Many of the features you push do not really go well with
Java. As an example: what does "const" mean with respect to
objects? If I say an object's method is "const", does that
mean that it will not mutate the object's internal
structures at all, or merely that it will not alter the
abstract state of the object as defined by its
specification? If you answer the former, then no one will
use const, since it is too restrictive and does not allow
unobservable side effects (such as updating an internal
cache). If you answer the latter, then the compiler can't
statically ensure that a method is const without
understanding the abstract specification of the object *and*
the mapping of the implementation state to the abstract
state; without that static ensurance, all const has added
is javadoc. I have considered the problem of incorporating
const into java myself, but I don't think there's a clean
way of getting the desired effect without seriously
complicating the language (such as by adding modifiers to
the private instance variables of an object to define
whether they may be safely modified by a const method of
that object).
Anyway, the point is that you have every right to put your
bug votes somewhere else, but:
1. You should really think deeply about the reality of what
you are asking for; Sun has shown no signs of being willing
to change the JVM or classfile specs, despite (for example)
outcries from the security community on how Inner Classes
were implemented (although the NextGen paper includes as a
footnote a simple way that one could implement them securely
with the current system)
2. You shouldn't flame the people here for supporting this
RFE; their priorities are different from yours.
-Felix
Submitted On 21-JUL-2000
pnkfelix
mharbon-
You've got to be kidding me. We're having a hard enough
time here convincing people in this forum of the
worthwhileness of having compile-time parameterized types;
you think they're going to be happy about a full blown
revision of the jvm, class-file format, *AND* java compiler
"just" for this feature? Not to mention the overhead of
carrying around that information with the generic objects at
runtime (I actually don't know how much overhead it would
be, but I'm sure people will complain nonetheless)
No way. I understand that there are benefits to having the
runtime support you describe, but its too big a change to
make at once; people can't cope with that. We're much
better off doing this incrementally, finding a syntax that
we can expand as our needs grow, and can compile into
compatible code NOW.
By having Sun standardize it as part of the language itself,
everyone can reap the benefits of library code that uses
parameterized types. The features you describe are vastly
different from what I would like to see right now: an
enhancement of the Java language alone that makes the static
code I write safer.
Besides, why would it be bad to incorporate the GJ syntax
now, and enhance it when/if Sun provides Runtime Support for
parameterized types? Or do you think that there is
something fundamental about the syntax for GJ that will
preclude adding such support? I doubt it. After all, the
GJ syntax was extended by the NextGen experiment to add
further support for parameterized types at Runtime (using a
hack not unlike the one described by javabandit).
Personally I don't see why NextGen's features add much more
to GJ; for example, I agree with Phil Wadler's statement
that the Factory pattern is a better way to acheive dynamic
creation of instances of a polymorphic type. But the point
still stands that this IS a valid RFE for the Java language.
-Felix
Submitted On 21-JUL-2000
mharbon
pnkfelix.. i hear you... but that doesn't make this RFE any
better. It sux in its current form. And I don't care what
if some loser thinks that this RFE is going to make a
difference.. because it won't.
You guys want 'design by contract' functionality, but it
means SO MUCH MORE than just some lame code parser that
ensures you aren't doing any illegal adds/casts at compile-
time. BIG DEAL. WHOOPDEDOO.
Where is 'strict'? Where is 'const'? Where are
assertions? Where is runtime type checking? Where is
polymorphism of parameterized types? How stupid is it that
I can't cast a parameterized type backwards? So you guys
say... ok... well... its been two years... lets implement
GJ and wait for the rest. LOSERS.
pnkfelix.. you have been sucked in by these idiots. They
don't have an open-source language, so nothing gets done.
They have you conned into thinking its okay to get only
like 10% of a complete 'design by contract'
implementation. Its lame. And if you buy it, you are
lame, too.
I still contend that this RFE sux. If this RFE is
labeled, 'FULL DESIGN BY CONTRACT IMPLEMENTATION', then
I'll vote for it. But only if it includes all the things
I've mentioned above.
Gawd... i can already write good enough code to avoid
errors in static types. Duh. Big deal. I want the
ability to keep some loser from mutating my objects at
runtime if I want. I want to know at compile-time if some
loser used an invalid value for a primitive with an
assertion (and not some BS 'if (DEBUG)' statement).
The little-baby static type-checking garbage you guys are
asking for is so lame and so lacking that it will do no
real good. You may as well just not include it at all.
Hell... GJ doesn't even provide a complete implementation
of parametric types and templates. How can any of you
other C++ guys out there vote for this? It SUX and you
know it!!!!!
Puhleez.. type checking is important for large projects,
but with the inception of EJB, it makes the need for
runtime checks even greater. MOST large implementations
will be a distributed solution using EJB, probably, or
maybe CORBA. If you don't get the runtime checking, you
are SCREWED anyways. Even WITH this lame code parser
called GJ.
i'm out of here... this sux so bad I can't even stand it.
Why don't we have like a separate RFE for EACH design-by-
contract feature and maybe it will get done in about
FIFTEEN years.
Uhhhhhhh... I think I'll go tell a big client that I'm
gonna give them a distributed solution in C++ that is say a
million lines of code, but not include any runtime type
checking or 90% of the 'design by contract'
implementation. That should make them REAL happy. Losers.
Submitted On 26-JUL-2000
ARae
So this has been here three years and the progress URL at the top is broken.
Is anything actually happening with it?
Submitted On 27-JUL-2000
alexrios
Please do this the Eiffel way.
See GJ implementation too.
Support constrained and unconstraiuned genericity.
Submitted On 18-AUG-2000
frankbranch
This and Alan Houlb's changes to the thread model should be
the highest priority change to the core JLS.
Submitted On 01-SEP-2000
kientzle
To an extent, the amount of casting required in Java could
be reduced
by refining Java's inheritance rules. The inheritance
rules used by
Eiffel are slightly more general than those in Java. For
example,
they permit a method in a subclass to override a method in
a parent class if the return type is a subclass of the
parent
method's return type. This is completely type-safe, and
permits, for example, the "clone()" method to correctly
return an object of the correct type. (Java's current
restrictive definition of method specialization forces all
clone() methods to return type "Object", which is
simply wrong.
Submitted On 02-SEP-2000
abies
Kientzle, it is not so obvious.
To determine that this method actually overloads inherited one, you need to load entire class tree for return
class (in other case you won't know if it is legal override). This is not a case with current scheme - classes
get loaded only when actually first used, not when references somewhere in classfile (superclass and
interfaces are exceptions here).
Now if you will start to check return types at very start of class loading, things get's nasty when few classes
have a loop in return values (you know, A class with method returning B and B class with method returning
A). It is possible to overcome this, but it is not so trivial as it seems. For Eiffel it is no-brainer, because you
get entire tree of classes at compile time.
You also could not compare methods by signatures any longer. You will first have to extract argument part
and strip return value and then compare for equality. Again possible, but extra work.
It is JVM change, not only language one, so be careful with it.
Submitted On 23-SEP-2000
dleuck
abies,
The overloading mechanism suggested by kientzle (known as
covariant return types) is not as big a deal to implement
as you suggest. In fact, the JVM already supports it for
exceptions.
Covariance is a no brainer. The lack of covariance in Java
at this point is an absolute embarrassment, and is clearly
indicative of Sun's laziness due to a lack of any real
competition. Its is completely type safe and 75%+ already
implemented in the VM!!! A lack of covariance leads to any
number of hacks and poor object-oriented design. Anyone
who disagrees with this is making excuses, or clearly
doesn't understand the problem space.
Also, despite needing to work on his bedside manner,
mharbon is absolutely correct in stating that any real
solution to the problem will require JLS _and_ JVMS
revisions. It is unavoidable. It should happen RIGHT
NOW. The longer sun waits the bigger the problem becomes.
I hope Microsoft allocates substantial resources to its C#
initiative - not because I want to see C# be successful,
but because I want to see them light a fire under Sun's ass
and get them to fix Java's incredibly lame typing system.
Sun, make an investment in Javas' success 10 years from now
by correcting its typing before some new fancy language
with a real typing system comes along and does to Java what
Java did to C++.
Submitted On 25-SEP-2000
ldwg
Well, as some people obviously do not understand the problem
space,
here is a short course for type system policies as defined
in Meyer's
excellent book Object Oriented Software Construction (2nd
Edition):
class A { A f(A x) }
Java and C++ do not allow to redefine f(A) with a different
signature.
Meyer calls this "novariance".
Eiffel allows to replace the output parameter types by
subtypes:
class B extends A { B f(A x) { /* redefine A.f(A) */ } }
This is called "contravariance" (!), and is completely type
safe.
Eiffel or Sather also allow to do the narrowing
automatically
using the SAME pseudo type "SAME f(A x)" which would also be
useful for Java interfaces.
Eiffel also allows to replace an input parameter by a
subtype:
class B extends A { A f(B x) { /* redefine A.f(A) */ } }
This(!) is called "covariance", and can be convenient in
some cases, but
is also very problematic: Covariance is not type-safe unless
you
define a static and very conservative global system check
that tends
to be too restrictive. Therefore, covariance could be
regarded as
a hack and will lead to a convenient, but critical design.
Submitted On 26-SEP-2000
dleuck
ldwg, my comments refer to covariant return types (which is common nomenclature). We are talking
about the allowance of overloaded methods returning subtypes. If you wish to call them something else,
fine. Exceptions in Java already support this type of mechanism. Covariant return types (or whatever
you wish to call them - lets not debate this) are type safe in Java. Please give an example, in Java, where
they are not.
Submitted On 02-OCT-2000
jtr
Yikes. Alan Houlb's threading model, while it seems to be a step in
the right direction, needs quite a bit of rethinking because of the
complication it adds.
Let's add generics to the VM, but wait until a new threading model is
fully baked before changing how threads work.
Submitted On 07-OCT-2000
derbyshire16
The generic types proposal URL at the top of this page is broken.
Submitted On 10-OCT-2000
bnlandor2000
Ok, I agree that the one thing missing in the langspec are PTs.
But as long as there are Swing memory leaks that crash our applications...
Well, as soon as these are fixed, PTs get all my votes.
Submitted On 12-OCT-2000
mindbridge
A couple of points about covariance and contravariance,
since they were discussed in some previous posts:
To use ldwg's example (but change its meaning), covariance
of return values is sth like this:
class B extends A { B f(A x) { /* redefine A.f(A) */ } }
(*co*-variance, since the direction of the type
specialization is the same for the class and the return
value). It seems to me that there is a universal agreement
that this is a highly desirable and easy to implement
feature. It is interesting to note that it is already
implemented for exceptions:
class B extends A { A f(A x) throws IOException { /*
redefine A.f(A) throws Exception*/ } }
is already valid in Java. It mystifies me why the same rule
wasn't applied to return values.
The other side of the coin is the contravariance of method
arguments:
class B extends A { B f(B x) }
class C extends B { B f(A x) { /* redefine B.f(B) */ }
(*contra*-variance, since the direction of the type
specialization is the opposite for the class and the method
argument - the overriding method arguments are less
specialized than the overridden ones)
Contravariance of method arguments is just as type-safe and
just as logical as covariance of return values and
exceptions. Theoretically, both of those should be on equal
footing and added together.
There is a practical problem with contravariant method
arguments, however -- there is a conflict with the method
overloading mechanism. Given the current JLS, there is no
way for the compiler to know whether a method with
contravariant arguments is meant to override or overload
the corresponding method in the superclass.
Personally, I think that method overloading should not have
been added to java as a feature (or at least it should have
been restricted to method signatures with different number
of arguments) and all that mess would have been avoided,
but then that's just me. After all, why spoil practice with
theory.
Submitted On 12-OCT-2000
mindbridge
Just to finish my last message to avoid ambiguity: What I
should have mentioned, and didn't, was the more or less
obvious fact that you can emulate contravariant method
arguments using overloading:
class B extends A { B f(B x) }
class C extends B { B f(A x) { /* redefine B.f(B) */ }
B f(B x) { return f((A)x); } }
As a result, I guess that this issue falls into
the "Workaround Exists" category, and will not be addressed.
Submitted On 02-NOV-2000
schapel
The URL for JSR-000014 (add generics to Java) is now
http://java.sun.com/aboutJava/communityprocess/jsr/jsr_014_g
ener.html
You can download the GJ compiler from
http://www.cs.bell-labs.com/who/wadler/pizza/gj/
It supports generic types and *covariance* of return types
today.
Submitted On 08-NOV-2000
hwc
To return to the subject of primitive types: it seems that
Java is soon to be able to build Object arrays on the fly,
creating wrapper objects for the primitive types.
I very much hope that the final proposal for generic types
will offer a similar mechanism. Vector< Integer > could
create the corresponding Object when passed an int, for
example. It wouldn't work the other way round - the user
would have to get the value explicitly.
Submitted On 12-NOV-2000
knuutila
I just hope that all the people bashing the PolyJ approach
(which IS my favorite) would read the FAQ at
http://lirone.lcs.mit.edu/polyj/comparison.html (and p'haps
even test the latest implementation) before making any
claims. For example, current version of PolyJ supports
primitive types as type parameters.
And if someone thinks Java is 'clean and simple' in it's
current state and parameterized types would just make
it 'complex' ... well, kudos to you.
Submitted On 04-DEC-2000
argyn
I agree with those who say that a collection framework
without parametrized container is worthless. It's terrible
to have a collection without compile time type checking.
If I'd asked a single feature Java needs, I'd say
PARAMETRIZED TYPES!!!!!!!!!!!!!!
Submitted On 04-DEC-2000
Sidewinder
I don't think there should be parameterized types in
Java. Java's type system is inherently dynamic and
there's no need for parameterized types because of
common ancestor java.lang.Object. Polymorphism
and casting works just as well. Please don't
complicate the language more than it already is -- this
is why we moved AWAY from C++.
Submitted On 09-JAN-2001
dkf
Sidewinder, experience with mixing up keys and values in
hash map code (ahem!) suggests that you are wrong; what you
suggest only means that it is possible to write correct
code, not that the facilities provided for doing so are
truly sufficient. You can still get failures according to
an application's semantics, just none according to the
language's semantics. Clients tend to be interested in
apps... :^)
Submitted On 14-JAN-2001
oferb1
I want to add a request featuer regarding class casting :
Let add the javac the ability of 'autocasting' classes if
needed means automatically cast if a ClassCastException is
thrown during compilation.
Suppose the next line :
MyListModel myModel = jlist.getModel();
The compiler will throw a ClassCastException on this line
since the getModel() method on JList is signature to return
a javax.swing.ListModel and MyListModel is an extension of
ListModel.
There for to fix this state an explict cast is needed :
MyListModel myModel = (MyListModel)jlist.getModel();
My requested feature is that the javac command line will
contain a flag of 'Xautocasting' which will force the
compiler to make an auto casting in such cases.
I don't think that 'autocasting' should be by default since
developer should know what happens in there code.
email : oferb@fundtech.co.il
Submitted On 24-JAN-2001
dkf
Suboptimal move, oferb1, since you've still got the cast in
there (getting rid of it is a recipe for disaster.) Better
to annotate the jlist with the fact that its model is of
class MyListModel instead of just ListModel (and which would
mean that getting rid of the cast altogether would be
safe.) Which is what this RFE is all about.
Submitted On 01-FEB-2001
Sidewinder
mixing up hash keys & values is a programmer error best
caught with a unit test. Compiler-time type checking is a
crutch that we can do without for the productivity benefits
associated with dynamic typing and unit tests.
There is no universal panacea to handling programmer
errors -- I just think that most programmer errors are not
type errors, so we shouldn't add complexity to solve a
problem that isn't.
With the industry moving in the general direction of
runtime type checking (with XML/SOAP, C#, and scripting
languages), I think that generic types are just not going
to fly. The real effort should be spent on making runtime
type checking more efficient.
Submitted On 02-FEB-2001
laxman_u
Parameterized types could be really helpful for
development. These can be used beyond Collection classes.
Microsoft's Active Template Library is a striking example
of template usage.
Submitted On 08-FEB-2001
hware
I see that parameterized types are useful for Collections,
but that seems a very limited area. Are there significant
other uses for this that aren't more cleanly solved by the
simpler co-variant return types? And co-variant return
types goes halfway towards nice containers too...
Submitted On 26-FEB-2001
bawback
I don't think we should touch the VM specification in order
to support templates. Templates classes are nothing more
than a set of formalized preprocessing instructions for
source code. What we need is just a bit of syntactical sugar
the javac compiler understands. A template class, just like
its C++ counterpart, should have no representation beyond
source code.
Sun would ship a template library along with its JDK (not
JRE), packed with template source code. Better still, they
wouldn't: they would just ship a javac compiler that
understood a backward-compatible, standardized template
language.
Submitted On 06-APR-2001
hwc
bawback, I don't think anyone's suggesting modifying the Java VM,
although the class file format may need extending - the creators of
GJ describe a tool that patches the collections library, but the
resultant code should still run on any standard VM.
Templates may be more flexible and, when combined with inline
function definitions and operator overloading as in C++, may result
in more efficient code, but I'm not sure they eliminate the need
for generic/parameterised types.
Submitted On 11-APR-2001
rickplant
For my money, if Java parametric types end up looking as elegant as Milner's in ML, I'll vote for. But if they
even vaguely resemble Stroustrup's, uh-uh. Parametric types without Hindley-Milner unification are just pale
ashes by comparison. If God made the natural numbers for Cantor, he made parametric type inference for
me. Few things in this game are beautiful enough to make me cry, but this is one of them.
The theory of this stuff goes a bit over my head, but hasn't Luca Cardelli published some sceptical papers
on the feasibility of type-checking languages with both parametric and subtype polymorphism? Because
subtypes got there first, and overloading is in too, the pass may already have been sold. Sigh. On the other
hand, there being nothing new under the Sun, wasn't there at least a proposal to graft H-M unification into
Smalltalk a few years back? Dunno, dunno, dunno... I hope someone around here's got a better memory
than mine, otherwise I'm going to have to re-invent the damned thing myself, in a brand new, revolutionary
programming language called... Yeah, right.
much love, Rick
Submitted On 08-MAY-2001
jtr
Things are looking better. JSR-14 has a public draft available.
Also see http://java.sun.com/people/gbracha/generics-update.html
Submitted On 09-MAY-2001
davecrocker
I would like to see parameterised types introduced, but NOT
using the angle-brackets syntax of C++, due to the lexical
ambiguity of ">>" (i.e. is it a shift operator or a pair of
closing angle brackets). [BTW in C++ it also causes
problems with macro expansion (i.e. you can't pass "A<B,C>"
as a macro parameter because the comma will confuse the
preprocessor)]. Better would be a syntax like "A of B",
or "A of (B, C)" where there are multiple parameters. This
does require a new keyword (i.e. "of"), but it would not be
necessary to use a "template" or "generic" keyword because
the presence of "of" is enough to identify a parameterised
class.
Submitted On 10-MAY-2001
npalombo
Hurry up already!
Submitted On 11-MAY-2001
schapel
If you're in a hurry to use parameterized types in Java,
simply download the GJ compiler:
http://www.cs.bell-labs.com/who/wadler/pizza/gj/
It implements a version of genericity that is nearly
identical to JSR-14.
Also, according to
http://java.sun.com/people/gbracha/generics-update.html
there will soon be an implemention of an open-source
compiler that fully supports JSR-14.
Finally, I have to mention that this change is so elegant
that it's completely described in only 18 pages, handles
the ambiguity of >> and >>>, and allows generic and non-
generic code to interact virtually seamlessly! I can't
imagine a simpler way of handling generics that would be
nearly as powerful.
Submitted On 25-MAY-2001
jarrodhroberson
I have written a Together 4.2 template that does just this.
Takes a custom class and makes a type safe
collection/set/map with a type safe iterator for it as a
wrapper around a backing collection/set/map.
It reduces simple errors and keeps client programmers from
corrupting collections with inappropriate object types and
amkes the code much more readable because there are no
casting of types.
A pre-processor hook into javac would be nice but add
maintance issues in having to track code thru all the
levels of indirection.
Submitted On 04-JUN-2001
sarum
So after 4 years of wanting the feature it
is still not here in 1.4beta. Does anyone
know when it will ship?
Submitted On 04-JUN-2001
pnkfelix
In response to sarum:
Did you not see
<a
href="http://developer.java.sun.com/developer/earlyAccess/adding_generics/">
this</a>?
Or are you asking when this will be officially released?
Seeing as how this and JDK 1.4 are both in beta release, I'd
say they might be on similar footing.
Or maybe not; a lot of people really want 1.4 out the door,
while it seems that only acadamics are excited about
generics...
C:P
Submitted On 08-JUN-2001
schapel
Generics are planned for JDK 1.5, aka Tiger. It will require
some very minor modifications to the JVM (to support
enhanced reflection) and there are a few bugs in the current
implementation.
Many developers have expressed concern that the current
proposal does not remove the casts from the bytecode, and
thus do not improve the performance of generic code.
However, I should mention that successful casts appear to be
an order of magnitude less expensive than method calls in
JDK 1.4! Anyway, the point of generics is enhanced type
safety, not enhanced performance.
Submitted On 21-JUL-2001
eliasen
The sample JSR-014 release implements this functionality and
generates useful, correct code. I ported some existing
libraries of mine to use the new generics scheme and not
only removed dozens of classes doing essentially the same
thing (but each having to perform their own typechecking and
casting,) but also reduced the size of the resulting single
class! In addition, I can be sure that the new code
eliminates a whole category of problems (putting the wrong
type into a data structure.) This makes me very, very happy.
The JSR-014 beta release does have some problems (e.g.
returning wrong line numbers for compilation errors, and
possible problems with inner classes. (although that may be
my misunderstanding.))
I think you'll get a big thrill when you eliminate hundreds
of unnecessary and timeconsuming typechecks and casts from
your code. This is exactly the kind of errors that
compilers can help identify and eliminate for you.
This system allows Java to have both compile-time typesafety
and code reuse, especially in container classes. In the
past, you could have one, but not the other. And did I
mention that code gets smaller? And more trustable?
On top of it all, you don't *need* to use this template
system. The compiler can simply provide warnings if you're
doing type-unsafe things. But it will also show you the
things you can fix at compile-time that will make your code
more robust at runtime.
If this isn't going into the language until 1.5, I strongly
encourage Sun to continue releasing JSR-014 updates before
that time.
Submitted On 10-AUG-2001
dnoyeB
What is the problem with automatic generation of class
files from some java file information as suggested in other
comments?
I mean if I want a custom collection class, I just make a
new class that accepts the type of objects I want to use.
I dont extend Vector or any other collection because
casting can allow a person to get a Vector type reference
which would then allow them to suck Objects out as opposed
to my type.
So you make a collection class that aggregrates Vector or
another colleciton class. That is uncastable to anything
and will always be type safe. Now convince the compiler
through syntax to do this automatically and youve got
something here.
You can convince the compiler by adding a new term 'types'
where normally is 'extends' or 'implements'.
type myColl aggregrates ArrayList(String)
{
//extra methods here
}
This only seems to save some typing though. it could be
easily dont by some other tool. doesent need to be part of
java as far as I can tell.
I must be missing some fundamental point here!?
Submitted On 07-SEP-2001
hwc
I like the new compiler but not the new syntax. For example:
interface Foo
{
void foo();
}
interface Bah
{
void bah();
}
class Test2< T extends Foo & Bah >
{
//...
}
Shouldn't 'extends' be 'implements' here?
The '&' seems out of place, too. It may helps the parser identify
additional bounds but there are better ways. In stead of
class Test3< T implements Foo & Bah, U >
you could use a keyword, e.g. class, as in C++:
class Test3< class T implements Foo, Bah, class U >
or use a different separator between the reference types:
class Test3< T implements Foo, Bah; U >
Both of which seem to me to fit in better with Java's existing syntax.
Submitted On 14-SEP-2001
schapel
Actually, extends is more appropriate. Interfaces extend
other interfaces, so "T extends Foo & Bah" is saying that
type T must be an interface that extends Foo and Bah, or a
class that implements Foo and Bah.
I agree with the awkwardness of the &. I didn't even realize
that was part of the generic syntax until now, even though
I've read the research papers on GJ and the Dr. Dobb's
article on the subject. I've experimented with the generics
compiler, and I've noticed that in the papers the authors
don't give examples that don't fit well with generics. They
seem to have left out any examples of the & syntax, for
example, as well as examples of code that the generics
compiler can't make typesafe.
Submitted On 18-SEP-2001
dkf
Urk. That '&' syntax is pretty grim, and it isn't necessary
either, since you could always declare an extra interface or
class instead and still have something that is equivalently
powerful. KISS...
Submitted On 22-DEC-2001
Ixchel
Hrm. Why are people still putting all of their bug votes on
this issue, when it's an active Java Specification Request,
it's already had a public specification review, and it's
been stated that it's going to happen quite soon (e.g. JDK
1.5)? Your bug votes would be doing more good if they were
moved to some other bug proposal that is less certain to
get fixed, so that other proposals get brought to the
attention of Sun. Personally, I'd like to see enums
(actually, strongly-typed integers) and 'const' added to
the language. You may have some other requested change or
bug fix that is nearer and dearer to your heart. I suggest
moving your bug votes to that, instead of to here.
Submitted On 09-FEB-2002
bigizzy
Parametrized Collections are definately a big neccesity and
knowing that they will be added in some time to the
standard jdk is a big help.
Thought is also needed to the collections api itself. The
fact that you cannot store primitives in collections is a
big drawback. Hence what is either required is that either
the collections should be able to take in primitives
themselves or new collections need to be introduced which
can store primitives.
May be when we have prametirized collections they would be
able to store primitives too.
One more option could be since Array's are Fullscale
Objects in any case we could make them Grow automatically
that we can only store Objects/primitives of only one type
as well as it would be growable.
Submitted On 13-FEB-2002
knollc
I would like to ask if anyone is willing, to maybe shift one
or two votes to 4466510 because although the idea of
generics and covariant return types is great, it isn't
exactly something that effects every type of application
written (although i'm sure you could use that in any type of
application). 4466510 is in reference to memory footprint,
and being that all applications use the JVM and consume
memory, perhaps some of you could find it in your heart to
transfer a few votes to this (arguably) more pressing problem.
Thank you.
-Chris
PS. You guys already got the ball rolling on this for a
proposal, so how about making them focus their attention on
memory consumption?
Submitted On 16-FEB-2002
adamc
I think some of you might want to investigate 4487555
(which requests that generics also support primitives).
Without primitive support, I just don't see enough gain to
care. (i.e., if the problem really demands generics, C++
will remain a superior alternative.)
Submitted On 08-APR-2002
schapel
>Urk. That '&' syntax is pretty grim, and it isn't necessary
>either, since you could always declare an extra interface or
>class instead and still have something that is equivalently
>powerful. KISS...
Actually, the & syntax is necessary. You can have a generic
type that must implement or extend more than one other
generic type:
class <A, B, C extends A & B>
In this case, you cannot declare an extra interface or class
instead.
Submitted On 13-MAY-2002
acoliver
They left off this related bug:
http://developer.java.sun.com/developer/bugParade/bugs/4487555.html
The current JSR for generics is insufficient and really a
bad idea. I support generics and light weight objects in
Java. But the implementation they seek is poor. This is a
kludge in the making. Do it all the way or not at all.
Submitted On 13-JUN-2002
jessh
I'd like to echo knollc's comments above.
This feature is effectively commited for Java 2 v1.5 at
this point. Please consider moving your votes from here to
4466510, which concerns reducing the memory footprint
required for Java apps.
After all, if you given up on Java client apps, in the long
run you give up on Java server apps.
Submitted On 27-JUN-2002
dnoyeB
I sure hope this ends up a simple pre compile tool like the IDL
tool. It will be a much better location for such a thing that
essentially should not affect the JVM or javac anyway!
Submitted On 06-JUL-2002
schapel
Comments about generics should probably go in the "Adding
Generics" forum at http://forum.java.sun.com/forum.jsp?forum=316
Generics are as good as done. Interested users should use
the generic compiler and report bugs.
Submitted On 16-JUL-2002
kenrodd
I too, would like to echo jessh and knollc's comments to
transfer votes to bug 4466510.
The demand for generics has been great (and Sun has
listened), but I'm afraid the urgency for memory footprint
may now be greater (and Sun doesn't seem to be
responding).
A quick look at the comments for bug 4466510 from several
seasoned Java developers resigning themselves to C# is
distressing.
Submitted On 17-JUL-2002
acoliver
http://developer.java.sun.com/developer/bugParade/bugs/4487555.html
- If you think that a better implementation is required
maybe you might want to vote for this instead.
Submitted On 21-JUL-2002
clp3
Support for generics is a total waste of time and effort,
for both Sun and Sun's customers.
Submitted On 26-JUL-2002
rfwan
seems like a precompiler is a good compromise - perhaps sun
should officially endorse a precompiler and include it in the
next jsdk. ANT would pretty quickly move that into their core
tasks.
Submitted On 29-JUL-2002
chennan
I don't understand why Sun is concerned about the impact of
the change. I feel that it is a purely compile-time change,
like using a pre-processor. It shouldn't introduce any
compatibility or stability issue.
Submitted On 23-SEP-2002
schapel
> It shouldn't introduce any compatibility or stability issue.
Of course it does!!!
Compatibility: Programs written with generics will not work
on older compilers.
Stability: The Java language has changed, so it is not stable.
Any time you make a change to a programming language, there
are these issues to consider. That's why changing a
language, especially one as widely used as Java, is so hard.
Submitted On 03-OCT-2002
jstar
I recently came to the realization that this will improve
performance as well, if it's implemented rightly. In
analyzing a recent bubblesort micro-benchmark
(see
http://developer.java.sun.com/developer/bugParade/bugs/4755738.html)
I found that the constant downcasting from Object required
in the Comparator to implement sorting generically was
responsible for a *huge* amount of the total time spent
sorting. Interestingly, once I hand-parameterized the types
and worked around the hotspot inlining issue in the bug
above, Sun Java 1.4.1 beat C++ under both the Microsoft
compiler and the G++ compiler.
Submitted On 19-OCT-2002
abies
Great jstar, but proposed implementation will not reduce
amount of casting. It will reduce amount of _manual_
casting. Amount of instructions behind the scene stays the same.
Submitted On 23-OCT-2002
bestsss
Although having template lib. and something like precompiler
fits, I believe this (entire topic) is waste of
time/resources and so on.
Template lib+precomiler will result in huge amount of newly
classes that just increase load time. Most probably it will
not compensate casting saved time.
What I do is: creating containers myself only if they are
very, very extensvly used.
Works fine for me: just replace all _Item w/ appropriate
Class...
Submitted On 09-DEC-2002
jimoore
The process allows me to vote "for" a bug, but not against
it. If allowed I would use one of my votes to vote against
this bug. I believe that the cost in terms of language
complexity is not worth the benefit in this case. I have
extensive experience with similar features in other
languages (e.g., templates in C++ and generics in Ada), and
I feel strongly that this is a feature that is not needed
for Java.
Submitted On 10-DEC-2002
knollc
Yooo hoo! Hello? Anyone listening? They've committed this
to 1.5, so you don't need to vote for it anymore! Go vote
for the memory usage problems! Yoo Hoo!!!
-Chris
Submitted On 23-FEB-2003
eliasen
I received some very bad news from Sun on Feb. 20, 2003
about their adoption of generics. They have decided that
they're not going to allow code compiled with the generics
compiler to run in a pre-1.5 VM. This obviously severely
limits its utility, and doesn't sound like what most
developers have been working toward. There is more
information here:
http://forum.java.sun.com/thread.jsp?forum=316&thread=362755
Submitted On 20-MAR-2003
chennan
>> It shouldn't introduce any compatibility or stability
>>issue.
>
>Compatibility: Programs written with generics will not
>work on older compilers.
Normally, you only compile your code once. The real issue
here is whether compiled class files can run on old JVMs. If
it is a pure pre-compiler, there should be no bytecode level
change and compiled class files should run on old JVMs.
As mentioned in eliasen's post, it seems Sun is NOT going to
support this compatibility. I hope there is good reasons
behind this decision.
Submitted On 05-MAY-2003
Ixchel
Hmm. The thread mentioned by eliasen above seems to no
longer exist on Sun's site. Disturbing.
Submitted On 12-MAY-2003
HenriGerrits
According to the JSR-014 public draft, the changes to the VM
are related to adding reflection support for generics. Since
Sun already has to change the VM for Tiger, it wouldn't make
much difference to also include reflection support.
Submitted On 03-JUL-2003
rfwan
It appears that changes to the VM are coming, not just the
compiler so a pre-1.5 VM will not be able to run bytecode
produced by the generics compiler. This is quite a shame.
Apart from reflection on generics (which I think we can do
without) - what else is driving a VM change? Will it be
possible to write code that "does not use" the new VM
features so that it will run on a pre1.5 VM?
Submitted On 18-JUL-2003
orderil
ssdfgsdg g sadgash sas hsahash asfh ash
Submitted On 10-AUG-2003
7Kami
Two bugs have been reported against Java 1.5.0 b14; 4902195
and 4902189. RFE 4064105 (this one here, Compile-time type
safety with generics (JSR-014)) could be closed anytime now
(provided generics made it into b14). 1352 votes are about
to be freed!
Submitted On 20-MAY-2004
ChitraR
test
PLEASE NOTE: JDK6 is formerly known as Project Mustang
|