type safety in java 1.5 (bug or hole?)  
Author Message
York Werres





PostPosted: 2004-5-24 18:29:00 Top

java-programmer, type safety in java 1.5 (bug or hole?) "John C. Bollinger" <email***@***.com> schrieb im Newsbeitrag
news:c8g89n$esu$email***@***.com...

> It would all the same be a nice complement to generics if the 1.5
> compiler would indeed issue warnings about user-inserted casts that are
> not provably correct. (I.e. those that the compiler cannot simply
> ignore). That would give Bracha's comment (that started this confusion)
> broad enough scope to no longer be confusing.

I agree very much.

BTW, there's another comment from Bracha in the very same paper that's
confusing (me): He says "The Java virtual machine does not directly support
overriding of methods with different return types. This feature is supported
by the compiler.". What does this mean? Does this mean that the different
return types are gone at run time? Here's an example:

static class A {
static A create() { return new A(); }
public A m(A a) { System.out.println("A->A"); return a; }
}

static class B extends A {
static B create() { return new B(); }
public B m(A a) { System.out.println("A->B"); return (B) a; }
public B m(B b) { System.out.println("B->B"); return b; }
}

public void testOverriding() {
A a_a = A.create(); // static type A, dynamic type A
A a_b = B.create(); // static type A, dynamic type B
B b_b = B.create(); // static type B, dynamic type B

A a2 = a_a.m(a_b); // prints: A->A
A a3 = a_a.m(b_b); // prints: A->A

A a5 = a_b.m(a_b); // prints: A->B <== overriding works
A a6 = a_b.m(b_b); // prints: A->B <== overriding works

B b2 = b_b.m(a_b); // prints: A->B
B b3 = b_b.m(b_b); // prints: B->B
}

public void testReflection() {
try {
System.out.println(
B.class.getMethod("m", new Class[] {A.class}).getReturnType()
== B.class
); // prints: true <== reflection works, too
}
catch (Throwable t) {
throw new RuntimeException("Laufzeitfehler", t);
}
}

So there's obviously some runtime support for overriding methods with a
different return type, because in this example both the overriding and the
reflection worked. Then what did Bracha mean?

2004-05-24, York.
--
werres at uni minus bremen.de
http://www.uni-bremen.de/~werres


 
York Werres





PostPosted: 2004-5-24 18:29:00 Top

java-programmer >> type safety in java 1.5 (bug or hole?) "John C. Bollinger" <email***@***.com> schrieb im Newsbeitrag
news:c8g89n$esu$email***@***.com...

> It would all the same be a nice complement to generics if the 1.5
> compiler would indeed issue warnings about user-inserted casts that are
> not provably correct. (I.e. those that the compiler cannot simply
> ignore). That would give Bracha's comment (that started this confusion)
> broad enough scope to no longer be confusing.

I agree very much.

BTW, there's another comment from Bracha in the very same paper that's
confusing (me): He says "The Java virtual machine does not directly support
overriding of methods with different return types. This feature is supported
by the compiler.". What does this mean? Does this mean that the different
return types are gone at run time? Here's an example:

static class A {
static A create() { return new A(); }
public A m(A a) { System.out.println("A->A"); return a; }
}

static class B extends A {
static B create() { return new B(); }
public B m(A a) { System.out.println("A->B"); return (B) a; }
public B m(B b) { System.out.println("B->B"); return b; }
}

public void testOverriding() {
A a_a = A.create(); // static type A, dynamic type A
A a_b = B.create(); // static type A, dynamic type B
B b_b = B.create(); // static type B, dynamic type B

A a2 = a_a.m(a_b); // prints: A->A
A a3 = a_a.m(b_b); // prints: A->A

A a5 = a_b.m(a_b); // prints: A->B <== overriding works
A a6 = a_b.m(b_b); // prints: A->B <== overriding works

B b2 = b_b.m(a_b); // prints: A->B
B b3 = b_b.m(b_b); // prints: B->B
}

public void testReflection() {
try {
System.out.println(
B.class.getMethod("m", new Class[] {A.class}).getReturnType()
== B.class
); // prints: true <== reflection works, too
}
catch (Throwable t) {
throw new RuntimeException("Laufzeitfehler", t);
}
}

So there's obviously some runtime support for overriding methods with a
different return type, because in this example both the overriding and the
reflection worked. Then what did Bracha mean?

2004-05-24, York.
--
werres at uni minus bremen.de
http://www.uni-bremen.de/~werres


 
Neal Gafter





PostPosted: 2004-5-24 22:55:00 Top

java-programmer >> type safety in java 1.5 (bug or hole?) York Werres wrote:
> So there's obviously some runtime support for overriding methods with a
> different return type, because in this example both the overriding and the
> reflection worked. Then what did Bracha mean?

What he meant is that it works by virtue of javac generating a bunch of methods
that makes it work, not because covariant return types are supported in the VM.

 
 
Roedy Green





PostPosted: 2004-5-25 3:33:00 Top

java-programmer >> type safety in java 1.5 (bug or hole?) On Mon, 24 May 2004 12:29:18 +0200, "York Werres"
<email***@***.com> wrote or quoted :

>So there's obviously some runtime support for overriding methods with a
>different return type, because in this example both the overriding and the
>reflection worked. Then what did Bracha mean?

Genericity is also done without anything in the JVM. The additional
level of type checking and automatically generated casts is all done
at compile time.

--
Canadian Mind Products, Roedy Green.
Coaching, problem solving, economical contract programming.
See http://mindprod.com/jgloss/jgloss.html for The Java Glossary.
 
 
York Werres





PostPosted: 2004-5-26 0:28:00 Top

java-programmer >> type safety in java 1.5 (bug or hole?) "Roedy Green" <email***@***.com> schrieb im Newsbeitrag
news:email***@***.com...

> > So there's obviously some runtime support for overriding methods with a
> > different return type, because in this example both the overriding and
> > the reflection worked. Then what did Bracha mean?
>
> Genericity is also done without anything in the JVM. The additional
> level of type checking and automatically generated casts is all done
> at compile time.

That's my point. Genericity doesn't work with reflection because there is no
genericity at run time. But there are covariant return types at runtime as
my test example showed. Bracha's statement about the covariant return types
being, too, completely handled by the compiler itself with no support of the
runtime system, sounded to me as if there are no covariant return types with
reflection as there is no genericity with reflection. But there are, so
Bracha must have meant something else.

Concerning genericity, I don't quite understand why there's no runtime
support, anyway. I mean "-source 1.5"-compiled classes don't run in the 1.4
runtime and "-source 1.5 -target 1.4" is not allowed by the compiler and
"-source 1.5 -target jsr14" works fine with some genericity examples on the
1.4 runtime but it failes for example with this one:

public void test7() {
List<Integer> list1 = new LinkedList<Integer>();
list1.add(4);
System.out.printf("%d", list1.get(0));
}

So there's no way to use a 1.5 language feature in the 1.4 runtime. Why then
type erasure as a means to implement genericity if you need a new runtime,
anyway?

25.05.04, York.
--
werres at uni minus bremen.de
http://www.uni-bremen.de/~werres


 
 
Neal Gafter





PostPosted: 2004-5-26 2:06:00 Top

java-programmer >> type safety in java 1.5 (bug or hole?) York Werres wrote:
> That's my point. Genericity doesn't work with reflection because there is no
> genericity at run time. But there are covariant return types at runtime as
> my test example showed.

Your example shows that javac faithfully provides the illusion of runtime
support for covariant returns.

> Bracha's statement about the covariant return types
> being, too, completely handled by the compiler itself with no support of the
> runtime system, sounded to me as if there are no covariant return types with
> reflection as there is no genericity with reflection. But there are, so
> Bracha must have meant something else.

I believe you understood him correctly.

> So there's no way to use a 1.5 language feature in the 1.4 runtime. Why then
> type erasure as a means to implement genericity if you need a new runtime,
> anyway?

For backward compatibility. Specifically, so that existing libraries can
interoperate with generified code, and so that existing sources can be
retrofitted with generics without breaking compatibility with existing code with
which it interoperates.