Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4144488
Votes 0
Synopsis Allow covariant return types
Category java:specification
Reported Against 1.1 , 1.2 , 1.2beta3 , 1.2beta4 , tiger-beta2
Release Fixed 1.5(tiger-rc)
State 10-Fix Delivered, request for enhancement
Priority: 4-Low
Related Bugs 4106143
Submit Date 01-JUN-1998
Description
Request to allow refining the return type of a method in a subtype.

We may be able to accomodate this as a beneficial side effect of genericity

See
http://developer.java.sun.com/developer/jcp/jsr_014_gener.html

Done in the upcoming release.




I suggest that the JLS be modified to allow a method to be overridden with a different return type, provided the return type of 
the overriding method is assignable to the return type of the method it is overriding.  Specifically, section 8.4.6.3 would be 
changed from

If a method declaration overrides or hides the declaration of another method, then a compile-time error occurs if they have 
different return types or if one has a return type and the other is void.


to 

If a method declaration overrides or hides the declaration of another method, then a compile-time error occurs if the return 
type of the
overriding method is not assignable to the return type of the overriden method, or if one has a return type and the other is void.

That is, for instance, the method Object clone() from the class java.lang.Object could be overridden with, for instance

public ThisClass clone(){
    return (ThisClass)super.clone();
}

because ThisClass is assignable to Object.
(Review ID: 32255)
======================================================================
Work Around




Lots of casting.  Ewwww!
======================================================================
Evaluation
Maybe as part of a generic types proposal we could deal with this. See comments.


 xxxxx@xxxxx  1998-06-01

Done.

 xxxxx@xxxxx  2004-08-30
Comments
  
  Include a link with my name & email   

Submitted On 03-JUN-1998
buffo
There is a true lack of covariant return types.
This possibility should be added without delay in
Java. Typecasting is boring...


Submitted On 04-JUN-1998
stuartG
Please do not add C++ style code bloat generics to
deal with this.  'Beta' style inheritance generics
would be great.  Covariant return types would fit
well with Beta style generics.


Submitted On 19-JUL-1998
pizzonia
This feature MUST be added as soon as possible.  Both practical and
theoretical arguments can be adduced (see A Theory of Objects -
Abaldi, Cardelli - Springer).  For example, it could be useful to
create sub-interface of Enumeration associated to non-polymorphic
containers in large data structure libraries. This could be useful to
avoid at least one cast for each Enumeration cycle.  The adapter
solution is both inelegant and impractical, because
 1- an Enumeration can be argument to a polymorphic function 
 2- all the code written with generic old-style enumerations must be
rewritten.
The JDSL (Java Data Structure Library) Developers Group.
http://www.cs.brown.edu/cgc/



Submitted On 14-OCT-1998
arick
This request is a duplicate of 4150774.  These
two requests should be combined along with their
votes.


Submitted On 14-OCT-1998
arick
There is another workaround, as described in
#4150774.  Unfortunately, it is even uglier then
casts.  Rather then use a return value, throw an
exception.
Very, very ugly!!!  Which is one of the best
arguments why this should be supported by the
language.



Submitted On 26-OCT-1998
MartDesruisseaux
RFE 4106143 is similar to this one and has 11 votes. Maybe it should be closed
as duplicated of this one.


Submitted On 05-NOV-1998
rolyp
Furthermore, covariant return types are explicitly supported by the JVM for
reasons of binary compatibility.  (Changing the return type of an overriding
method to a subtype and recompiling does not break the binaries of its
supertypes.)


Submitted On 14-JAN-1999
dleuck
What is the argument against covariant return types?  It increases flexibility
without introducing new syntax or requiring VM spec modifications.  It seems
like a no-brainer.


Submitted On 20-APR-1999
pmurray
Yummy. This will require a rewrite of every JVM 
and classloader on the planet. It's an ideal 
opportunity to use that "required JVM version" 
thing that's new to the compiler.


Submitted On 27-MAY-1999
pmurray
As well as an overriding function being able to 
narrow it's return type, it also ought to be able
to widen its parameters.


Submitted On 01-JUN-1999
tjpalmer
Genericity should solve the problem, but even without it, this needs addressed.
There should also be covariant throw clauses.
The problem is worse than just casting.  Sometimes it breaks would-be good
code.
For example:
public interface View
{
    View getParent();
}
public class ComponentView
    extends Component
    implements View
{
    public ComponentView getParent()
    {
        return (ComponentView)super.getParent();
    }
}
This would be fine as long as the parent was a ComponentView.
At present in Java, implement the interface above is strictly illegal.


Submitted On 11-JUL-1999
pmurray
To amplify my previous comment,
This ought to be OK in the language
class X {
Integer a(Integer b) throws Ex1, Ex2;
}
class Y extends X {
PositiveInteger a(Number b) throws Ex1;
}
Any possible call to X.a() can be handled by 
the overriding function Y.a()
If you do this
X foo = new Y();
then foo.a() will always be ok. However, if you
then go
Y bar = (Y) foo;
You get access to the more restrictive return and
the less restrictive argument that comes of 
knowing that foo is actually an instance of Y, 
without having to cast bar.a() every time you
call it. Note also that the broadening of the
argument type is not possible with java as it now
stands, unless you use a "delegation" function to
handle it.


Submitted On 31-AUG-1999
Aardappel
covariance is not without its problems (in Eiffel
it makes the language type un-safe).


Submitted On 15-OCT-1999
MartDesruisseaux
According Sun Engineer, polymorphism is "perfectly type safe". If a
method return a Number, an overrided method may only change the return type for
a Integer, a Float or stuff like that (which are Number). Please see bug
#4106143 for details.


Submitted On 06-DEC-1999
dkf
I suppose covariance of argument types would conflict
somewhat with method overloading...


Submitted On 08-FEB-2000
Hoggy
A POSSIBLE WORK AROUND?

I don't know if this works consistantly
across all compilers and JVMs.  The second
argument of the self method stops my compiler
from complaining - effectively tricking the
compiler/JVM to perform covariance (or
something like it) and serves no other purpose.

Please tell me if this works elsewhere too.

class AA
{
    public AA self(int i, AA a)
    {
        return this;
    }
    
    public static void main(String args[])
    {
        //  AA.self(int, AA) returns AA and
        //  AA does not have a test() method
        AA a = new AA().self(0, null);
        //  We know this simulated covariance
        //  worked because test() is no a method
        //  of AA, yet it can be called from
        //  the return value of self()
        BB b = new BB().self(0, null).test();
    }
}

class BB extends AA
{
    public BB self(int i, BB b)
    {
        return this;
    }
    
    public BB test()
    {
        System.out.println("Hello World!");
        
        return this;
    }
}


Submitted On 13-FEB-2000
MartDesruisseaux
Unfortunatly, the Hoggy's code (from the previous comment) is not a work
around.
It doesn't override the "self" method; it just overload it. sefl(int,
AA) and self(int,BB)
are two independants methods. The code "AA bb=new BB(); bb.self(int,
null)" will
never call "BB.self(int,BB)". In Java, the method's signatures need
to be absolutly
identical in order to override a method.


Submitted On 28-APR-2000
schapel
I disagree that a JVM change would be necessary to support
covariant return types.
A method with a covariant return type could be compiled as
if it had the same return type as the method it's
overloading. Then, when that method is called, the compiler
inserts a cast if the method is called through a reference
to the class that contains the covariant return type
method.
To give an example, let's say I have a class MyClass that
overrides the clone() method to return a MyClass reference.
This clone() method would return an Object reference, as far
as the JVM is concerned, because it overrides Object's
clone() method, which returns an Object. Thus, there is no
incompatability with old JVMs.
If I have the code
    Object o = new MyClass();
    Object s = o.clone()
The returned Object reference would *not* be cast to a
MyClass, because the o reference could point to any kind
of Object. The fact that o points to a MyClass object is
ignored.
But in the following code:
    MyClass m = new MyClass();
    MyClass c = m.clone();
The compiler would compile the second line as:
    MyClass c = (MyClass) m.clone();
The cast is inserted because I'm calling the clone() method
with a MyClass reference, and MyClass declares clone() as
returning a MyClass reference.
Java already has covariance of throws clauses and
accessibility. Adding covariance of return type seems easy
and makes the language *more* type-safe because it
reduces the number of casts needed, and these casts can
always throw ClassCastException.


Submitted On 28-APR-2000
pmb
The claims that the JVM already supports covariant return
types and that it requires no JVMS changes do not hold. An
invokevirtual instruction explicitly states the name and
descriptor (indicating parameter types _and_ return type) of
the method to be invoked. According to the JVMS, a method
with matching name and descriptor is searched for during
dynamic method lookup for invokevirtual. In other words, a
method with differing return type would not be considered a
candidate for execution by a given invokevirtual
instruction.

Note: I'm not saying that allowing covariant return types
for overriding methods would be unsound or cannot be
supported; it just doesn't fit with the current JVMS (2nd
ed.).


Submitted On 03-MAY-2000
derbyshire16
In reply to Schaepel's April 28 message: That isn't 
covariance, that's just hiding the ugly cast by making the 
compiler do it for you. The case is still there and still 
exacts a run-time overhead.


Submitted On 03-MAY-2000
derbyshire16
What are "'Beta' style inheritance generics"?


Submitted On 03-MAY-2000
derbyshire16
Nooo...the *cast* is still there! Stupid thing changed my 
message!


Submitted On 03-MAY-2000
derbyshire16
What is Eiffel?


Submitted On 05-MAY-2000
schapel
What does it matter if the cast is "still there"? This way
of implementing covariant return types is just like the way
generics are being added to Java: containers still contain
Object references, but the compiler hides the ugly casts
from you when you retrieve them.
The JVM will not support generics, but Java will
support generics at the source code level. Likewise, with
the method I proposed, the JVM will not support covariant
return types, but Java will support it at the source code
level. Isn't that what really matters, anyway?
It may be true that there's another way to implement
covariant return types that's faster, but as far as I can
tell, speed is the only disadvantage to the casting method.
If the casting method doesn't "really" support covariance,
then do you also think that Java will not "really" support
generics, since that method uses casting as well?


Submitted On 05-MAY-2000
JRI
Request to allow addition of a return type to a method in a subtype.

I suggest that if the overridden has return type void,
the overriding method is allowed to define a different return type.

Reason: 
The method can still be called without a return value.


Submitted On 08-JUN-2000
dkf
While covariance (as requested in this RFE) is not supported
by the JVM/ClassLoader, there is no sensible reason not to
do this as it is clearly a completely safe operation. 
(Covariance is more troublesome when it comes to assignable
things like array indices or C++ references - in fact,
anything that can go on the LHS of an assignment - but we're
not after that here.)  Because it is safe operation, it
should not require a cast; casts should be regarded as
indications that you're doing something ugly and which is
forced upon you by the horrors of working with real-world
problems, and not as something you should be using for
everyday programming.  Casts are where you are fighting
against the language, and not working with it.  (Which is
why I support both this RFE and the generics one; because
they remove casts.)
That cast removal also improves the performance of Java
programs is doubly a good thing...


Submitted On 16-JUN-2000
schapel
I just discovered that the GJ compiler implements covariance
in a way that does not require a change in the JVM, and also
does not require a runtime cast. It depends on the fact that
the JVM allows two methods with identical names and
argument to have different return types (although the Java
language does not allow this type of overloading). You can
read about it by going to
http://www.cs.bell-labs.com/who/wadler/pizza/gj/Documents/
and reading the tutorial.


Submitted On 05-JUL-2000
eblake
Could this also apply to widening type signatures when
implementing abstract methods?  For example:

class SuperA { ... }
class SubA extends SuperA { ... }

abstract class SuperB {
  abstract void foo(SubA arg);
}
class SubB extends SuperB {
  void foo(SuperA arg) { ... }
}

As written, SubB will not compile, because it does not
implement the abstract method with the same type signature
as is in SuperB.  However, if SubB were not extending
SuperB, then passing a SubA to the method foo would be
legal, as the compiler notices it can widen SubA to the
specified SuperA.  It is annoying to make this case work
with an extra overloaded method:

class SubB extends SuperB {
  void foo(SuperA arg) { /* handle the generic case */ }
  void foo(SubA arg) { foo((SuperA)arg); } // satisfy the
compiler
}

In general, each method should accept as parameters the
widest type of objects it can handle, and return the
narrowest type it can, so that there is less typecasting.


Submitted On 27-JUL-2000
alexrios
Eiffel supports this feature and it sure is helpful.
OOSC 2 (Bertrand Meyer) explains how this should work
in explicit detail.


Submitted On 29-JUL-2000
pmurray
in reply to schapel (Fri May 05 06:56:04 PDT 2000), 
inserting a cast in someting to avoid, because it generates 
a runtime check and a performance hit. 
It's very very simple. Returning a narrower type is safe. I 
want the compiler and classloader to be relaxed about this, 
so that I don't have to cast the result of the clone() 
method etc.


Submitted On 21-AUG-2000
schapel
As far as I know, there are three options available for
implementing covariant return types in Java: add methods
that are overloaded on return type (as GJ does), cast the
returned reference (as I suggest), or make a change to the
JVM.

I've never seen a proposal for a change to the JVM that 
would allow this feature. So, we're left with either an
additional cast or a method call, each of which has a
run-time penalty.

If you'd like to propose a way of implementing this feature
without any run-time overhead, you're more than welcome to
do so. But the disadvantage of a change to the JVM is that
covariant return types would not be available on older JVMs.


Submitted On 01-SEP-2000
kientzle
One of the most widely-criticized aspects of
the C language was always the reliance on void*
pointers and the casting that this leads to.

"Object" serves the same purpose in Java that
void* serves in C, and over-reliance leads to
excessive casting, which reduces overall code
quality.

Permitting covariant return types would dramatically
reduce the amount of casting, even without a template
or generic types system.  It's a minor language change
which would dramatically improve the language.


Submitted On 05-SEP-2000
ThomasYip
> We may be able to accomodate this as a beneficial side 
effect of genericity

No. Don't give me complicated solution for that. The simple 
solution (allow covariant return type) will solve a big 
piece of problem. Just relax the compiler to do the safe 
works. Even better, it doesn't break backward compatiblity. 
please relieve us from many of castings. 
Also, no reason for convariant return type doesn't co-exist 
with generic type. And, I don't need, (even don't want) 
generic type. It is very very painful and unsafe to adapt 
any "object factory" and "factory method" pattern without 
covariant return type.

In short, please do it now. Don't wait please. I waited 
long enough. please........


Submitted On 26-SEP-2000
dleuck
Sun, just do it.  You know you need to do it.  Its a backwards compatible change, and it improves code 
quality dramatically.  What possible reason can you give for not supporting this in your next release?


Submitted On 04-OCT-2000
TrevorCampbell
I agree with "dleuck".  Sooner the better.  It is probably 
the most important single feature currently lacking from 
the language (after Swing performance :-) ) 


Submitted On 07-OCT-2000
derbyshire16
The generic types proposal URL at the top of this page is broken.


Submitted On 10-OCT-2000
benjyw
An excellent idea that would solve design problems I run into almost daily. I 
hope this is added to Java ASAP.


Submitted On 23-OCT-2000
jah6
Just a thought: would this allow constructor inheritance to 
work more tidily?


Submitted On 02-NOV-2000
schapel
Hmmm... "constructor inheritance"? I'm not sure what that
is, because constructors are not inherited in Java.

Anyway, I'm all for this RFE, but I think "just do it" is
not the right attitude for adding this change to the Java
language. There are at least two ways of supporting
covariant return types, and there are problems with each
way.

As part of GJ
http://www.cs.bell-labs.com/who/wadler/pizza/gj/
there's a proposal for adding covariant return types that
I believe could be used independently of the "generic types"
features of GJ. However, as the authors of GJ point out,
the reflection API is underspecified and would have to be
modified in order to work with GJ. Even if the reflection
API is updated, think of all the code that uses the
reflection API that assumes overriding methods have the same
return type the overridden method. With this proposal, there
is some Java code that will break.

The other proposal is one I came up with that simply casts
the returned reference. This approach is compatible with
the current reflection API, and thus wouldn't break any
existing code. But if generic types are added to Java
later, there could be incompatibilities at that time.

If you're eager for covariant return types in Java, you can
use the GJ compiler today. It's available for free at the
above URL.

Just do it!


Submitted On 12-NOV-2000
pmurray
I would luurve to be able tpo implement a

FooList extends ArrayList {
 put(Object o) {
  if(!(o instanceof Foo)) throw IDontThinkSoException();
  super.put(o);

 Foo get(int i) {
  return (Foo) get(i);
 }

}

At the moment, you just can't. I don't know what generic 
types are and I suspect I don't need them. And I prefer not 
to have hidden casts in the compiled code.

Is java going to fossilise into a mess of bug-compatible 
missing features? Is it going to bloat? Just change the JLS 
and the JVM spec on this one tiny tiny change.


Submitted On 13-NOV-2000
kaknowles
We would like to implement a class hierarchy with EJBs.
However, we are left with lots of 

if (p instanceof MyEJB) {
   MyEJB ejb = (MyEJB) p.create();
   ejb.invoke();
} elseif (p instanceof MyOtherEJB) {
   MyOtherEJB ejb = (MyOtherEJB) p.create();
   ejb.invoke();
}
etc., we plan to have at least several hundred EJB services
and this is untenable.  We want to have a base EJB with
derived EJBs with a shared interface; however, we need this
feature enacted to do this.  Otherwise, the create() method
(required to be defined in the Home interface) cannot
be overridden and we cannot call create() polymorphically.



Submitted On 14-NOV-2000
schapel
Adding covariance of return type to the JVM is absolutely
not a tiny change! If you disagree, please post a proposal
for changes to be made to the JVM to allow this feature.
Keep in mind that JVM byte code allows methods to have
identical names and arguments, but different return types,
and that Java is not the only language that is compiled to
byte codes. Any change should be compatible with all older
JVMs. Specify the exact behavior of the invokevirtual,
invokeinterface, and invokespecial instructions. Discuss
the interaction with binary compatibility (i.e. in what
situations is changing the return type of a method a binary
compatibile change?). Finally, convince JVM implementors
that adding covariant behavior would not impact the speed
of these instructions.

Even if this proposal does turn out to be simple, it would
still be incompatible with all current JVMs! So far, there
have not been any changes to the JVM that haven't also been
tied to changes in the API.

If you need covariance of return types, don't hold your
breath for Sun to include it. Simply download the free GJ
compiler, and you can use the feature today with all JVMs!


Submitted On 23-DEC-2000
smiths
A case can be made for narrowing the return type - but 
widening would defeat the behavior of the compiler to 
detect contract violations.  E.G.,

class SuperA { ... }
class SubA extends SuperA { ... }

abstract class SuperB {
  abstract SubA foo();
}
class SubB extends SuperB {
  SuperA foo() { ... }
}

Why exactly is SubB extending SuperB?  If this is the 
entire declaration, then SubB is *not* a SuperB, it merely 
has a method of the same name.  Now the compiler has no way 
to guarantee that SubB conforms to the contract of SuperB.  
What happens here:

void whatever(SuberB b)
{
    SubA a = b.foo();
}

This code will break sometimes - whenever the passed-in 
object is actually a SubB.  The Java philosophy is that 
subclasses should *never* break the interface of a 
superclass/interface.

Code like:

if (p instanceof MyEJB) {
   MyEJB ejb = (MyEJB) p.create();
   ejb.invoke();
} elseif (p instanceof MyOtherEJB) {
   MyOtherEJB ejb = (MyOtherEJB) p.create();
   ejb.invoke();
}

is just plain ugly and if this is what your design forces 
you to then it is quite frankly no good.  In my experience 
I have yet to be forced to code this way.

Here is a simple workaround which is compatible and follows 
a pattern (or idiom) established by StringTokenizer:

'create a new method which specifies the different return 
type and is available only in the derived class.'

E.G.,
interface Enumeration {
    Object nextElement();
}

class StringTokenizer implements Enumeration {
    Object nextElement() { return nextToken(); }
    String nextToken() { return ...; }
}

The assumption is that you only need the services of the 
derived type if you know you have one, as in:

StringTokenizer st = new StringTokenizer();
String s = st.nextToken();

Where the new method is easily accessible.  In this case:

Ennumeration enu = new StringTokenizer();
String val = ( (StringTokenizer) enu).nextToken();

Is evidence of a worse design than one that requires 
casting of return types.

One final word - type casting is not neccessarily a result 
of language limitations, sometimes (usually) it exposes 
design flaws (especially if it happens alot).


Submitted On 06-JAN-2001
roedy
Allowing an int return type to override a long would be much more difficult to implement than allowing a Spartan to override an Apple.  I suggest this just be done for Objects,
not primitives.


Submitted On 18-JAN-2001
MaximSenin
I completely disagree with that. The great benefit of Java 
over Smalltalk and other languages with weak typing is 
STRONG typing which allows to elliminate a high percentage 
of errors in compile time.
If you are bored from type casting - you don't know Java or 
have no taste - use interfaces instead of types and never 
cast types. In ideal world you should never put class name 
in method declaration - instead you use interfaces 
everywhere, and real classes only when you create instances.

Don't destroy beauty of Java - interfaces are excellent! 
Great advantage over Smalltalk!


Submitted On 24-JAN-2001
dkf
MaximSenin, what are you wibbling about?
If I've got an object of type Foo and I want to clone it,
the new object's return type is Object, and I have to cast
it to get it to be a Foo, despite the fact that everyone
knows cloning returns the same type of object.  There are a
number of other similar problems strewn throughout the
standard libraries.  Using interfaces everywhere does not
help; it is completely orthogonal to the problem.
If it weren't for the fact that I know academics are more
grounded than you, I'd tell you to go back in your ivory
tower and not come hence until you've gained a clue about
real programs...


Submitted On 25-JAN-2001
schapel
And it's acedemics who gave us the GJ language and compiler,
which support covariance of return type.
At http://www.cs.bell-labs.com/who/wadler/gj/ you can find
a compiler that implements this feature (as well as generic
types, of course!) with current JVMs. If you're tired of
casting, you might give it a try.


Submitted On 07-MAR-2001
big_hairy_mama
This feature would be a lifesaver in countless cases, but I
must point out one problem.  I was reading a native library
tutorial the other day and remember seeing a reference to
the way java methods are called from native code - with the
return type included in the signature (which is passed as a
string to a java "interface" function in C).  I suppose this
would not hurt classes that are already written and will not
be changed, but it could introduce complications in case
that the C code uses a subtype of a class to call a method
that, although it returns a subtype of the same method in
its superclass, has a different signature.

Somebody please correct me if I am dead wrong here (as I
have never actually written any sort of native library on my
own).  I wish I hadn't thought of this potential problem,
because this would be a *wonderful* feature to have.


Submitted On 22-MAR-2001
schapel
Relax. There's nothing about the JVM or native method calls
that makes covariance of return type impossible or even hard
to implement. Java bytecodes also include the return type in
method calls, and as I so often point out, the GJ compiler
implements covariance of return type with current and older
JVMs. If you haven't already, go to

http://www.cs.bell-labs.com/who/wadler/gj/

and download the GJ compiler and documentation for further
details. If nothing else, it makes a great additional free
compiler. I always run my production code through javac,
oldjavac, jikes, and gjc to ensure that I haven't taken
advantage of bugs in any compiler or gray areas of the
Java language.


Submitted On 30-MAR-2001
dkf
The easy way round is to generate a dummy method in the
subclass (B) that has the same return type as the superclass
(A) and which just passes everything on to the real method
and just returns the result after widening its type.  (For
sanity, you could ask the compiler to ensure that any
subsubclasses (C, etc.) overriding the method must do so by
being at least as restrictive as the method in the subclass
(B).)


Submitted On 11-APR-2001
javabandit
I'm not completely familiar with the internals of Generic 
Java.  But it seems to me that one of the main reasons that 
a language would support covariant return types and 
generics is to avoid the cast at all -- because of the 
overhead involved.  A cast from what I understand is very 
expensive.

Does Generic Java still do these casts when it compiles the 
code -- effectively eliminating any performance advantage, 
or does it actually create macro/template classes which 
return the truly covariant type?  Does anyone know?

It just seems like everyone is solely concentrating on the 
advantage of 'not having to cast within your code', when it 
seems to me that the other huge advantage for a covariant 
override is to speed up/optimize your code as well.

Thanks for any comments.

-- Rick


Submitted On 12-APR-2001
bassclar
One way to think about this proposed feature is that it allows casts to be moved from the method calls to 
the method body.

public Class Rabbit implements Cloneable {
  public Rabbit Clone() {
    return (Rabbit)super.clone(); // cast in method body--callers need not cast the return type
} }

public class RabbitVector extends java.util.Vector {
  public Rabbit firstElement() {
    return (Rabbit)super.firstElement(); // ditto
} }

This seems like a win because casts are ugly and now there's only one per method instead of one per 
method-call. So all of the many <code>Rabbit r = (Rabbit)v.firstElement();</code> casts in the code can be 
changed to <code>Rabbit r = rv.firstElement();</code>. (Note: This is not a performance win, there's still 
the same number of casts at runtime, they've just been factored-out.)

I find that most of the time I'm using a Vector (or any Collection), I populate it homogeneously. That is, all 
the objects I put in it are of the same type, or at least have a common supertype that is not Object. So if 
this feature were implemented, I would gladly write class RabbitVector (heck, it's only 4 lines) and use that 
instead of a java.util.Vector. It just seems cleaner.

But it's not that simple. If Marshmallow is a subclass of GroceryItem, it's dangerous to think of 
BagOfMarshmallow as a subclass of BagOfGroceryItem because then a new Cabbage() could be add()ed to 
an instance of BagOfMarshmallow, in which case it wouldn't really be a bag of marshmallows anymore. An 
example using RabbitVector would be:

RabbitVector rv = new RabbitVector();
rv.add(System.out); // can add() any Object, not just rabbits
Rabbit r = rv.firstElement(); // will cause a ClassCastException at runtime

While I agree that allowing covariant return types in type-safe in theory, I also think the most common 
place in which they would be used would be with Collection types (such as RabbitVector), and would 
therefore be encouraging quasi-type-unsafe design practices. Comments?

RabbitVector could be "improved" by overriding the add(o), add(n, o), addElement(o), insertElementAt(o, n), 
set(n, o), and setElementAt(o, n) methods to not allow non-Rabbit objects to be inserted. (Take a look at 
what pmurray wrote on Nov/12/2000 to see how to do this.) This is pretty ugly. First, that's a lot of 
methods to have to override, each one with a instanceOf operation, which in some ways is as bad as a 
cast. Second, that leaves the addAll(c), addAll(n, c), and copyInto(a) methods, which could be much 
harder to deal with.


I'm not necessarily against this RFE, but I'm against hurrying it. Better I think to think everything through. 
I'm not sure which of the three proposed implementations I like best:

1. Alter the JVM spec: Older VMs wouldn't be able to run new code, so shouldn't be done lightly.

2. Compiler generates implicit casts: No runtime performance improvement, which is too bad, though I think 
getting rid of the actual casts in the source code is more important.

3. Generate an extra method for each return type, a la GJ: I haven't taken a look at GJ, but the idea rubs 
me the wrong way. (How large is each dup method?)

Maybe a more modest approach would be better. Maybe something like:

4. Augment the JLS to include a new cast-equals operator: A symbol would have to be chosen, but I'll 
borrow Pascal's := for now. <code>x := y;</code> would be syntactic sugar for <code>x = (typeof 
x)y;</code>. (Not C's typeof operator, but the actual compile-time type of x.)

This doesn't attempt to allow covariance or improve performance. All it does is make the source code look 
slightly better by removing explicit casts if they precede an assignment.


Submitted On 12-APR-2001
mana1234
This would be a very good update. I wonder if Sun would be 
able to handle it. Do they still have the people who 
created Java?


Submitted On 20-APR-2001
dkf
You only need a single dup method for each method in the
subclass that has a return type smaller than the method in
the superclass, and all that method does is pass in the args
to the smaller method and expand the type and pass back the
result.

I don't like that ':=' as it encourages sloppy thinking.
When you are narrowing types, you should be aware that you
are doing this. It just shouldn't be necessary to narrow
types quite as often in Java as is currently the case, and
return-type covariance will go a long way towards fixing
this. (That it allows things like your RabbitVector, well,
it is unavoidable; you can get yourself in the same mess now
except for having to have a cast on the caller's side as
well. RTcV opens no holes in the typesystem; it just lets
you express things that the programmer knew and assumed
already, like the fact that clone() copies an object...)


Submitted On 07-MAY-2001
rfwan
pmuarray also suggests widening the argument types, I 
believe this is called contravariance of argument types. 
Method overloading I think interferes with this and makes 
it less necessary.

Correct me if I am wrong, but the JVM has 
method "overloading" on the return types which would cause 
similar interference but the language specs never allow us 
to use the "overloaded" return types. Thus implementing 
covariant return types at worst would require a recompile.

The covariant types would not really help with 
the "RabbitVector" problem but would help with 
a "RabbitIterator". I'm personally tired of writing the 
following Javadoc: "This method returns an Iterator where 
every element is of type Foo."


Submitted On 08-MAY-2001
abies
I think that we got covariant returns as part of generics spec. I would expect this bug to get closed soon.


Submitted On 25-MAY-2001
schapel
There's a prototype open-source Java compiler that supports
covariance of return type available at
http://java.sun.com/developer/earlyAccess/adding_generics/


Submitted On 10-JUN-2001
jstuyts
The run-time system (jdk1.1.8) already supports this. Compile these files:

public class Base {
}

public class Derived extends Base {
}

public class BaseReturner {
public Base getValue() {
return new Derived();
}
}

public class DerivedReturner extends BaseReturner {
public Base getValue() {
return new Derived();
}
}

Make a copy of 'BaseReturner.class'. Now change the return type of 'getValue()' of both 'BaseReturner' and 
'DerivedReturner' to 'Derived'. Compile 'BaseReturner.java' and 'DerivedReturner.java'. Restore the copy of 
'BaseReturner.class'. Then compile the following test program:

public class CovarianceTest {
public static void main(String[] args) {
BaseReturner br;
DerivedReturner dr;
Base b;
Derived d;

dr = new DerivedReturner();
br = dr;

d = dr.getValue();
b = br.getValue();
}
}


Submitted On 11-JUN-2001
schapel
Supporting contravariance of argument type would change many
existing overloaded methods into overriding methods. This
change would cause millions of lines of Java code to break.
I don't see a way of adding contravariance of arguments to
Java in a backwards compatible way. For this reason, I don't
think this feature will ever be added to the Java language.

In contrast, adding covariance of return type does not break
any existing Java code and is scheduled to be added to JDK
1.5, aka Tiger.


Submitted On 11-JUN-2001
jstuyts
I've been thinking about contravariance for arguments, but I don't think there is an unambiguous strategy for 
choosing which method overrides the base class' method. Take a look at these types:

interface Base1 {
}

class Base 2 {
}

class Derived extends Base2 implements Base1 {
}

class DerivedUser {
void doIt(Derived d) {
System.out.println("Doing it on derived");
}
}

class BaseUser extends DerivedUser {
void doIt(Base1 b1) {
System.out.println("Doing it on base 1");
}
void doIt(Base2 b2) {
System.out.println("Doing it on base 2");
}
}

Both 'doIt' methods in 'BaseUser' are contravariant 'doIt' in 'DerivedUser'. Which one should be executed 
when someone invokes 'doIt' on a 'BaseUser' reference to an actual 'DerivedUser'?

One option is to chose 'doIt(Base2 b2)' because this is the class inheritance path and this must be single, so 
ambiguity can not occur.

If you have any thoughts on the subject, please let me know.


Submitted On 19-JUN-2001
auinger
I just had a look at the generic type compiler and this is 
how future code would look like:

"public class IdentityHashMap<K,V>
extends AbstractMap<A,B>
implements Map<K,V>"

I can understand that the proposal guys rely on some 
template like structures to make things type-safe, but I 
always hated templates in C++ and don't want them in Java.

Well.. probably I start playing around with the generic 
compiler and hope that I get used to the new code style 
easily. But from the first glance I would reject this 
covariant types add-on.


Submitted On 10-AUG-2001
rfwan
In response to jstuyts trick-workaround by modifying the 
superclass (June 10, 2001) without recompiling the narrowed 
base class.  It fails being truly covariant when 
considering the following case:

BaseReturner returner = new DerivedReturner();
Derived d = returner.getValue();

would throw a compile time error saying an explicit cast 
was required.  what the proposed run-time example was doing 
in fact was creating a subclass with an overloaded return 
type rather than a covariant one.


Submitted On 10-AUG-2001
rfwan
Possible workaround example:
public class RabbitIterator implements Iterator {
  public Rabbit nextRabbit() {...}
  public Object next() {return nextRabbit();}
}

Code which wishes to use the covariance of a "Rabbit 
iterator" would then use the nextRabbit() method.  Not 
ideal but it seems to work.


Submitted On 29-AUG-2001
pmurray
I have had a bit of a looksee at the generic stuff, and 
there are two problems.

Firstly, it looks like it is a compile solution, that 
probably generates bytecodes with bunches of casting. This 
is a performance hit.

More impotantly - genericity must be built into the base 
class. You can't simply override a method and declare the 
return type as being narrower.

And, it's really quite a heavyweight solution for what we 
are trying to do here - real language bloat. All we want is 
to be abe to declare a MyClassCollection, which overrides 
iterator() to return a MyClassIterator, which overrides next
() to return a MyClass.

I'm sure there's some deep computer-science reason for it, 
but I cant for the life of me work out why this would break 
the type-safety of the language.


Submitted On 30-AUG-2001
dkf
Return-type-narrowing needs a compiler change but can be
done without any JVM changes.  You need a compiler change
because for each method that you narrow the return type for,
you need an adaptor method to widen it so that people
assuming you've got the superclass can still find the
method.  The compiler will also need to be smarter about
detecting existing narrowings (obviously!)  You do not need
a JVM change because methods are currently looked up by
return type as well; this is probably why narrowing is not
currently supported, but it doesn't get in the way.

I *think* that only the class that does the narrowing will
need an adaptor method in it, and subclasses will be able to
use the superclass's adaptor (since they will need to be at
least as narrow, for sanity's sake if nothing else!)

There is, of course, some issue with documentation of this
narrowing process, but that should be resolvable.


Submitted On 07-OCT-2001
JManish
This enhancement will help greatly, moreover it would fully 
support "substitution by subtype" principle. Typecasting is 
not an elegant solution. I think it should implemented as 
soon as possible. 


Submitted On 22-DEC-2001
Ixchel
Hrm. Why are people still putting all of their bug votes on 
this issue, when it (as part of the generic types proposal) 
is 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 12-FEB-2002
ThomasYip
"And, it's really quite a heavyweight solution for what we 
are trying to do here - real language bloat." -- pmurray 
WED AUG 29 10:45 P.M. 2001

I totally agree with you, pmurray. I want a simply 
solution, not a bloat. Generics type is an overkill, and I 
am only interested in covariant return type. 

If there is "vote againts", all my three votes will go 
*against* having generics type in Java. 

All my votes go to this REF currently.

I love to have covariant return type in Java. However, I 
would rather that Java never supports it, then using 
generic type to solve my problem.


Submitted On 12-FEB-2002
shrink_laureate
Good point, Ixchel!
Removed.


Submitted On 13-FEB-2002
shrink_laureate
I really don't get it, ThomasYip. What do you have so badly 
against generics, and what does it have to do with 
covariant return types?

If Java does get them both in the same release, as 
expected, there's no reason to imagine that you'll have to 
use generics in order to have covariant returns.  Even if 
you'd rather tear your eyes out than use generics, it has 
no impact on this RFE.


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


Submitted On 13-MAY-2002
gbishop
Just cast the darn object you rebel scum.  I want to vote 
_against_ this.


Submitted On 21-MAY-2002
spau008
(First time poster, go easy :o)

Type safe is one thing, complicating the design is entirely 
another. What happens to subclasses of that class? What 
should they return? 
e.g.
class Heaven{
 Heaven returnMe(){return new Heaven;}
}
class World extends Heaven{
 World returnMe(){return new World();}
}
class Hell extends World{
 ???? returnMe(){return new ????();}
}
Solution 1: Allow superclass to be returned
i.e. ???  = "Heaven"
But now (of course) someone referencing a world component 
that is actually the subtype Hell, may not get back a World 
object. Cannot allow this, since it is illegal.
i.e. World w = new Hell();
w = w.returnMe(); 

Solution 2: Only allow new restricted type. (the obvious 
choice)
Now the actual implementation of that method is potentially 
hidden in ALL the superclasses of this object. While this 
is not a paradox, it confuses things from a design point of 
view. 
To find out what the current implementation of a method are 
on the object, you have to check each superclass for the 
closest return-type restricition. 
Also, if a subtype class now wants to return the superclass 
component and can't, because of a return-type restriction, 
you are stumped. The alternative now is to go back and 
remove this restriction, editing all referring code to the 
casted type. Just another design choice that has to be made 
before implementation, with the cost in man-hours being the 
penalty.
A subtle problem, to be sure, but the benefits are only to 
save a few casts in your code? Is it worth it?
(Let's not even mention the changes to all the CASE tools 
etc)


Submitted On 22-MAY-2002
spau008
I realise this: assuming you don't find it in the immediate 
superclass, you must check up the heirarchy until you do. 


Submitted On 22-MAY-2002
spau008
...which still means you have to search up the tree to find 
the closest one, meaning you cannot be sure anymore that 
simply because you see that a superclasses member returns a 
particular type, that your inherited member can. 
Again, a subtle and small problem, with a simple solution, 
but an annoying one nonetheless.

As to it being the same as today, it is most definitely 
not. 
E.g. (usual example with easy solution)
Today if I have a Component, I know that any subclass of 
Component returns a Dimension Object from the getSize() 
method. So my Component, no matter what/where it is, can 
return a Dimension for getSize() and be happy.
Now What if some bright spark has written a Component (e.g. 
My3DComponent) that returns a subclass of Dimension that is 
a 3D dimension (with a depth also - called Dimension3D), 
then restricts the return type of getSize() to this new 
subclass. 
In the current Java, I could not care less since I can 
return a normal Dimension from my component as per normal 
for any subclass of this custom 3D Component.
With the proposed change, I cannot, I must make sure I 
return this type, or a subclass of this type. 
The difference is subtle and easily solvable, but annoying.
E.g. (without easy solution):
Complicate the issue further, what if this new Dimension3D 
and Component3D subtype are in another package? And what if 
the Dimension3D has a protected constructor and is a final 
class? 
Therefore: I have access to subclass the Component3D, but 
not to the return my own getSize() because I do not have 
access to create a Dimension3D object. 
In current Java, it still works, because I simply return 
the supertype - Dimension.
In the new version, I am forced to either: 
1) Make my component part of this package or,
2) Try and use the superclass's getSize() method to return 
the size I want - which is probably incorrect, so not 
really a solution.
Solution 1) may not really be possible wince I want to use 
protected members from my own package.
Again, a subtle problem that wont affect most people, but 
it is still there.


Submitted On 22-MAY-2002
megagurka
"To find out what the current implementation of a method are 
on the object, you have to check each superclass for the 
closest return-type restricition."

No, you only have to check the closest superclass where the
method is declared. This is always the most restrictive
return type. Actually this is exactly the same as today, no
additional restrictions are made.



Submitted On 23-MAY-2002
spau008
ok...in my proposed scenario you are aware of the correct 
inheritance but cannot comply with the creation of the new, 
restricted return type because it has been made a package-
access class.
Incorrect inheritance, along with other bad programming 
techniques, will always be a feature of code - no matter 
what you do. 
e.g.
If you allow restricted the return types, you will have 
people over-using this feature to save themselves a few 
casts. (Leading to design issues later.)

I have also ignored the simple fact that this small 
conceptual change will lead to rather large (or at least 
fundamental) changes to design tools, IDES etc. 


Submitted On 23-MAY-2002
megagurka
Actually I dont think it's a problem at all. If you are
inheriting from a class you should be aware of the methods
you are inheriting otherwise you are in deep water. The
easiest way to check which methods you inherit is to walk up
(not down) the inheritance tree. Exactly like today.

Incorrect inheritance is the root of much evil. Composition
is often a better choice.


Submitted On 28-MAY-2002
deyanb
Actually 
World w = new Hell();
w = w.returnMe(); 

Is perfectly legal in Java and would compile and run just
fine if you declared the returnMe() as:

public Heaven returnMe()
{
  return this.getClass().newInstance();
}

in your Heaven class.

Then you could do:
Hell hell = new Hell();
World w1;
Heaven h1 = w1 = hell.returnMe(); (note that you don't even
have to cast here).

But you've missed the point of this whole thread (and by
posting this so do I)...

Otherwise the covariant return types will be the second best
thing that will happen to Java after the generics become
part of the language.


Submitted On 30-MAY-2002
spau008
I haven't missed the point. (which is actually quite a 
simple one so I would have to be pretty stupid!) 
I was just pointing out this suggestion IS changing the 
language, not simply allowing some "extra feature" that 
does not effect the way the language works at all. (this 
has become one of the premises of the argument, if you 
remember) 
I also realise that making the class a public one would fix 
the problem - although it is my experience that these sorts 
of classes usually tend to be inner classes or protected 
classes, not designed to be used outside of the package. 
However, this point is irrelavent, since it was merely an 
EXAMPLE of how situations could arise that change the way 
the language is used.
Covarientce would also introduce the problem of "over-
restriction", in which programmers start setting arbitary 
return type restrictions to save a few casts, with this 
having repercussions later on. 

I am not saying this is a bad idea oveall, actually I would 
use it if available myself. However, it is not a silver 
bullet with no side effects as some people have been trying 
to say. If a change is made, let it be made on facts, not 
fantasy.
While the proposd change is subtle and wont bring anyone's 
project to a grinding halt, is covarience going to save 
anything more than some casting? Is this worth the 
compounded effort to implement? 
I would disagree with this.


Submitted On 13-JUN-2002
jessh
Covariance is a wonderful feature in a language purist 
sense.

In practical terms the only real benefits in Java would be 
less castes to type and execute.  Given the larger issues 
on this enhancement list (e.g. 4466510) and ongoing quality 
of implementation issues (e.g. HTTP client library issues, 
quality of Java Plug-In delivery, etc, etc) I would put 
such an "ivory tower" request at the bottom of the list!!!


Submitted On 17-JUN-2002
ebkopp
I think what it comes down to is that what an object
actually is and what the compiler thinks it is are very
seperate entities. Casting, despite how verbose it is
and how automatic it could be in some situations, is
provided by the programmer to concretely let the compiler
know what it can and cannot do with an object.
I agree with all of you who've said they would prefer
a bit of casting as opposed to negotiating the logistics
of covariant return types.

I think SUN engineers knew what they were doing when they
drafted the language specifications and made methods to be
functions of their inputs only and not as functions of their
output containers.

Such is the price of late binding.

P.S. For 99% of applications, casting overhead is the least
of your problems (unless, of course, you're casting several
billion objects per second.)


Submitted On 24-JUN-2002
shrink_laureate
I can't believe some of you people.  This really isn't that 
hard.

> Solution 1: Allow superclass to be returned
> i.e. ???  = "Heaven"

No, it's overriding a method that returns World, so it must 
return some form of World. Either it returns World like its 
parent, or it returns Hell which is a World.  In either 
case, client code knows that it will be getting a World.

Unless you're arguing that a Hell isn't a Heaven, in which 
case it's your class hierarchy that's at fault.


> Now the actual implementation of that method is 
potentially 
> hidden in ALL the superclasses of this object. While this 
> is not a paradox, it confuses things from a design point 
of 
> view. 

No, it simplifies things from a design point of view. The 
whole point of object oriented programming is that 
implementations are hidden. You don't know the internals of 
an object, you just know its interface.


> To find out what the current implementation of a method 
are 
> on the object, you have to check each superclass for the 
> closest return-type restricition. 

No, you trust the return type that you are told. The return 
type isn't free, it's covariant.  A World is a World, 
whether it's a Hell or not.  The return type of the type 
you believe it is will always be the most restricted return 
type you can trust.


> In the current Java, I could not care less since I can 
> return a normal Dimension from my component as per normal 
> for any subclass of this custom 3D Component.
> With the proposed change, I cannot, I must make sure I 
> return this type, or a subclass of this type.

Correct.  A 3D component should always have a 3D size.  If 
you return a 2D size, as is currently allowed, then you are 
making a mistake.  With covariance you are forced to only 
do the thing that makes sense, returning a 3D size for your 
3D component.


> And what if the Dimension3D has a protected
> constructor and is a final class? 

Then that is the developer of Dimension3D's way of 
deliberately preventing you from making one.  It's not an 
accidental error, it's a deliberate restriction.


> In practical terms the only real benefits in Java would 
be 
> less castes to type and execute.

My project would be significantly aided by the use of 
covariance.  I have a superclass (with company-sensitive 
stuff hidden, of course):

class Doodad {
  Doodad modifyMe() { ... }
}

And lots of subclasses that look like:

class Doodad3 extends Doodad {
  Doodad3 modifyMe() { ... }
}

And I need the option to call both:

  Doodad3 d3 = doodad3.modifyMe();
  Doodad d = doodad.modifyMe();

At present, I have to use a method with a different name 
like superModifyMe();  See how annoying that is?  And 
there's lots more like it.


Submitted On 30-JUN-2002
spau008
Shrik, you have missed the point entirely - it is a theoretical foray into various scenarios that could arise from this change. I am trying to address three related points that were brought up:
1) The change DOES effect the language in a fundamental and there ARE differences in implementation. These are subtle, but they are still there.
2) This change could create annoying and subtle situations that are not noticed till much later in the design process.
3) "Over-restricting" return types will auite probably become a "new" programming antipattern, to replace the one this solution solves.

In reference to your reply:
>No, it's overriding a method that returns World....
The first solution was set up as a "straw man" to illustrate a non-viable alternative.  Of course I know it is not a valid option! 
> The whole point of object oriented programming is that implementations are hidden.
Not when it is part of the PUBLIC interface and the type that this PUBLIC interface returns, it is NOT the point at all.
>No, you trust the return type that you are told.
Which you find out by......oh look....searching each superclass to find the closest restricted return type. (Which is what I said in the first place)
>Correct.  A 3D component should always have a 3D size.
Not neccessarily, I may want to create my own 3D size class that is not a child of the programmer's 3d size. At any rate, the example is not suppose to be a specific problem to be solved, it is trying to illustrate a scenario where restricted return types cause a gotcha. (I know there are ways around it, that is not even remotely close to the point I was making)
>It's not an accidental error, it's a deliberate restriction.
It may have been a programmer simply trying to save themselves a few casts, which seems to be one of the main reasons many people have given for this change so far - therefore far more likely. 
>Doodad3 d3 = doodad3.modifyMe();
>Doodad d = doodad.modifyMe();
What's wrong with:
Doodad3 d3 = (Doodad3)doodad3.modifyMe();
Need to test it?
if(doodad3 instanceof Doodad3)
   Doodad3 d3 = (Doodad3)doodad3.modifyMe();
Again, it is simply a matter of casting.


Submitted On 02-JUL-2002
megagurka
> What's wrong with:
> Doodad3 d3 = (Doodad3)doodad3.modifyMe();
> Need to test it?
> if(doodad3 instanceof Doodad3)
>    Doodad3 d3 = (Doodad3)doodad3.modifyMe();
> Again, it is simply a matter of casting.

There's nothing wrong with the code, if you are willing to
accept runtime type checks instead of compile time type
checks. But Java is a (mostly) strictly typed language 
(unlike Python, Smalltalk, Ruby etc.) and I think it's a
huge advantage if the compiler can type check as much as
possible. It saves lots of time spent tracking down type
casting bugs.


Submitted On 08-JUL-2002
shrink_laureate
I'm with megagurka. What's wrong with that code is that I 
have to use a cast, when I already know what the return 
type will always be.

There will be situations when programmers restrict what you 
can do with their classes. That's the right of anybody who 
publishes classes - they get to decide on the types and 
interfaces.  If they make a mistake, then that's their 
fault, but nothing will prevent bad programmers.  A good 
programmer can make use of this to provide exactly the 
right scope for future use, and to prevent future mis-use.


Submitted On 03-AUG-2002
cakoose
Aside from being a non-optimal solution, will
compiler-inserted casts even work?  The compiler can figure
things out when it's dealing with all the files involved,
but what about when you're dealing with a pre-compiled
library?  The method signature of the derived-class's method
will still be the same, right?  And since it doesn't have
access to the original source code, the only way for the
compiler to figure out that covariance is being used is by
analyzing the method's bytecode.

A more fundamental change (one at a lower level than the
compiler) seems necessary.


Submitted On 13-AUG-2002
HMarggraff
One more reason to provide it:
C-Shrap doesnt have it.


Submitted On 19-AUG-2002
winget-roger
Someone asked:
"Type safe is one thing, complicating the design is entirely 
another. What happens to subclasses of that class? What 
should they return?"

Of course, any subclass's return type must be at least as
narrow as its parents.


Submitted On 22-AUG-2002
dkf
spau008's argument that people (well, programmers ;^)) could
misuse return type narrowing seems a little odd to me.  I'm
of the opinion that any time you can supply more information
to the computer about the real intention behind the code,
the more likely it is that the machine will be able to find
any stupid errors that are there.  Right now, the contract
on the behaviour of, say, the clone() method only explicitly
states that it returns an object (that the object is of the
same type as the object being cloned is merely an informal
thing that goes on behind the compiler's back) and this
forces every developer that uses it to clone a Foo object to
deal with the fact that the system might decide to return an
int[][] instead just because it felt like a bit of a
chuckle.  Why can't I constrain the contract further? 
Simple.  It's a *compiler* restriction (and one that can be
eased without any bytecode changes.)

"Somebody might misuse it"?  Might as well also remove
sockets, file-system access and GUIs, because they're all
susceptible to (much more serious) misuse...


Submitted On 22-AUG-2002
Abuse
yet another person who thinks this is a far cleaner and 
theoretically better solution than generics....


Submitted On 31-AUG-2002
valjok
Hm, to extent a collection with covariants you need to add 2 
lines:
[code]public class MyCollection extends java.util.ArrayList  {
       public void add(MyObject o) { super.add(o); }
       public MyObject get(int index) { return (MyObject)
super.get(index); }
    }[/code]
Is it so hard? Explain me, please, why should java be 
terminated with hostle generics synthax, memory footprint 
overuse, 10% performance fall, cardinal changes in compiler 
and JVM, loosing embedded device sector. And all of this to 
satisfy ambtions of lasy persons who can't write 2 lines of 
text? How to stop generics?


Submitted On 02-SEP-2002
megagurka
Please understand that this is NOT a replacement for generic
types! valjok, you seem to think you can replace generics
with covariant return types, which is not correct. In your
example you can still add Object's to MyCollection, which
breaks type safety. I think both generics and covariant
return types are valuable additions to the Java language.


Submitted On 29-OCT-2002
schapel
> Explain me, please, why should java be terminated with
> hostle generics synthax, memory footprint overuse,
> 10% performance fall, cardinal changes in compiler 
> and JVM...

I will, as soon as you explain to me why generic syntax is
"hostile," generics will either increase memory footprint or
decrease performance, or a JVM change is needed for
generics. As far as I can tell, none of these are true. If
you actually try the generics prototype compiler, you'll see
for yourself! And you'll also see that covariant return
types is not a replacement for generics, but instead another
useful change that will reduce the number of casts in source
code, thus increasing type safety.


Submitted On 14-NOV-2002
abies
valjok, you get it other way.

Currently proposed generics solution does not require jvm
changes. It also does not provide any overhead on runtime
(except maybe a bit longer signatures). It is your solution
which would be a kill for embedded solutions - because for
every specialization of container, you would like to create
separate class, replicating all tables and structures which
are needed to define it (and collections are certainly not
lightweight).


Submitted On 21-MAR-2003
AtariFan
I support this suggestion strongly.


Submitted On 29-APR-2003
pmurray
Dammit! It's been FIVE YEARS since Jun 1998, when this 
minor change to the JLS was suggested!

I'll bet it's political - who "owns" this area of java? Someone 
badly wants generics, and is opposing this change because 
they know it would drastically ease the demand for them. God 
Damn generics to hell! They're ugly in C++  and they'll be ugly 
in java.

Please Sun! I'm gasping for air here! Just one, really, really, 
tiny change! Just one! A method's return type must be the 
same primitive type as the one it overloads, or an assignment-
compatible object type. The JLS, the compiler, and the class 
loader. Jeeze - this is way simpler than adding assert, which 
everyone was hot to do. It'd take an afternoon - if that.


Submitted On 19-JUN-2003
hwc
To those who think it is a bad idea to allow co-variance as 
described, would you prefer some sort of mark-up to make it 
explicit, as proposed for generics and arrays?


Submitted On 03-JUL-2003
rfwan
Been poking around the web recently and have come to some 
tentative conclusions:

jsdk 1.5 will have the change to the JLS we want as "part of 
generics".  I found this on the section describing the 
enhanced-for loop
http://jcp.org/aboutJava/communityprocess/jsr/tiger/enhance
d-for.html

It looks like the change we want (i.e. JLS change with 
bridge/adapter methods, no JVM change, no behind the 
scenes casting) is coming through along with the Generics 
which some people are dubious over.

From my reading, it appears that those who hate generics will 
still be able to use the covariant return types without 
incurring any behind the scenes casting costs.  

Covariance will provide type-safety on iterators.  For type-
safety on collections we'll need to summon the generic beast 
to insert behind the scenes casts.  There will be the runtime 
performance hit but not the runtime risk of class cast 
exceptions because the behind the scenes casts will be 
provably safe at compile time.


Submitted On 30-JUL-2003
GOVERP
Please, the language is broken without this.  A simple
example.  Say I want a Money class that combines BigDecimal
(to get proper handling of the pennies) and a Country object
(for exchange rates), so I can add Pounds Sterling and US
Dollars.  This is a real requirement in some international
investment funds.

I want to have Money as a subclass of BigDecimal, so I can
override add(), subtract() and so forth.  Now I can define
Money.add(Money) because it has a new method signature.  But
I can't can't handle the exchange rate calculation properly.
 There I have say the USD to GBP converion of today 1.68. 
So I want Money.multiply(BigDecimal), and that currently
MUST return BigDecimal.  The only way I can get Money back
is with a cast.  Which is horrible.

Paul Gover


Submitted On 13-AUG-2003
dkf
Perhaps I'm just being dumb, but why would Money inherit 
from BigInteger?  That seems like the Inappropriate 
Inheritance Anti-Pattern to me...


Submitted On 13-AUG-2003
dkf
Oops!  BigDecimal, not BigInteger.  My bad.


Submitted On 14-AUG-2003
bassclar
Tell me more, rfwan. Is "Note that that they rely on
covariant return types, which will be introduced as a part
of support for generics (JSR-14)" all we have so far? Or are
there more details on this aspect of JSR-14 out there?


Submitted On 30-AUG-2003
pmuurray@bigpond.com
Yes, hallelujah, it is part of the JSR-14 public draft.

"3.2 Overriding 
<snip>
This specification requires that the result type of a method
is a subtype of the result types of all methods it
overrides. This is more general than previous specifications
of the Java programming language, which require the result
types to be identical. See Section 6.2 for an implementation
scheme to support this generalization."

You can see the public draft of JSR-14 via
http://www.jcp.org/aboutJava/communityprocess/review/jsr014/index.html

It's catty of me, but I would still like to have seen this
RFE done in its own right, not simply as a side-effect
because its needed for something else.

Oh, by the way. It would be cool if the language spec would
accept those unicode big angle brackets to delimit generics.


Submitted On 14-SEP-2003
secosic
PS it's still not included in the generics prototype! :-(


Submitted On 14-SEP-2003
secosic
This is REALLY ESSENTIAL to be included with the upcomming 
generics as this little programm shows:

public class Bug
{   public static void main(String[] args)
    {   A<Object> a     = new B<Object>();  // expected 
error: Object is no Comparable
        A<String> aa    = new B<String>();  // expected no 
error
        A<Object> aaa   = new B<String>();  // this should 
work, shouldn't it? But it doesn't.
    }
}

class A<T>
{}

class B<TT extends Comparable>
extends A<TT>
{}


This is a small bug reprodution program. The initial idea was 
to built
binary trees and binary search trees, where a 
BinarySearchTree<String>
was to be assigned to a BinaryTree<Object> or to be a 
parameter for a
method like

public int countElements(BinaryTree<Object> tree) {...}


Submitted On 08-OCT-2003
MichaelFranz12
I just tried the following in Intellij (using EAP generics
support)

class X
{
  public Exception getException() {...}
}

class Y extends X
{
  public RuntimeException getException() {...} // compiler
now accepts this
}

Client code:

X x = new X();
Y y = new Y();

Exception e1 = x.getException();
RuntimeException e2 = y.getException(); // Look, no cast!

It works sweetly!

So assuming this feature is staying (it's difficult to
imagine generics working without it), someone from Sun could
put a few developers out of their collective missery by
stating that the problem has been resolved.


Submitted On 08-JAN-2004
Oleg.Danilov
Nowdays it is indeed a serious tendency to use (and 
most important to REUSE) a generic code. For a 
small company sometime it can reduce investments 
in development/support up to 10 times or more. In big 
part the success of script languages like Python is
based on their ability to deal with generic code. So
everything which can reduce the amount of code to 
write and maintain has a tremendous significance.
This is not about lazyness but about efficiency.
If I had 10000 votes I'd spend 9990 on this one! 
We neded this 5 years ago! 


Submitted On 01-APR-2004
afreije
There is a big issue with covariant throws in combination
with unchecked casts. Please have a look at 
http://forums.java.sun.com/thread.jsp?forum=316&thread=509263
The examples shows taht you can trick the JVM and throw any
unchecked exception, not just RuntimeExceptions


Submitted On 07-MAY-2004
dkf
That forum thread is irrelevant and stems from a belief 
that Foo<Bar> must be a supertype of Foo<Object>. It 
is hard to see how someone could become so 
confused as to believe that to be the case!

As long as the return-type is a *strict* subtype of the 
return-type in the superclass, a narrowing of the return-
type is guaranteed to be safe.

(Now, should RuntimeException have been a subtype 
of Exception? I think not, but that's a mistake made 
years ago now...)


Submitted On 20-MAY-2004
afreije
> That forum thread is irrelevant and stems from a belief
> that Foo<Bar> must be a supertype of Foo<Object>.

In contrary, the example uses unchecked casts just to show
that with a throw statement, a Foo<Exception> illegally can
be treated like a Foo<RuntimeException>.

For methods with generic-typed return values an implicit
cast is used, which prevents illegal assignments. The issue
is that the thrown exception is not type-checked at compile
time not runtime.
Either the thrown exception must be type-checked (a JVM
issue?) or the unchecked cast mechanism must be improved to
solve this issue.


Submitted On 18-JUN-2004
Amir.Pashazadeh
This feature can be helpful in using Stateless Sesion EJBs too, consider that you can have a generic Home interface with a create method,
And then you can have a factory for them, without need of reflection,
This feature must be added asap.


Submitted On 28-JUL-2004
AdinsX
Absolutely Horrid Idea.  There is no way to determine to determine which one to call.  That's why you write A Wrapper Method.


Submitted On 09-AUG-2004
simcoeng
more flexibility


Submitted On 22-AUG-2004
musheno
This is a great Idea, now, support for future releases, another story. I would suggest the class should be allowed to provide a way to declair if this is permissable, with some sort of functionality similar to Template classes in C++.


Submitted On 02-SEP-2004
cowwoc
Limiting the use of covariants makes absolutely no sense, nor does "writing a wrapper for it". I think a lot of people commenting on covariant return types don't actually understand what is implied.

Sun, thanks for providing this enhancment!



PLEASE NOTE: JDK6 is formerly known as Project Mustang