classpath
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Japitools 1.5 support tough design issue


From: Stuart Ballard
Subject: Re: Japitools 1.5 support tough design issue
Date: Wed, 7 Sep 2005 21:26:48 -0400

I did some testing and I'm more confused than ever.

class Super<T> 
{
  String foo(T t) {return "Super";}
}
class Sub1 extends Super<String> {
  String foo(String str) {return "Sub1(String)";}
}
// Sub2 is a compile error: "name clash: foo(java.lang.Object) in Sub2
and foo(T) in Super<java.lang.String> have the same erasure, yet
neither overrides the other"
//class Sub2 extends Super<String> {
//  String foo(Object str) {return "Sub2(Object)";}
//}
// Sub3 is a compile error: "name clash: foo(java.lang.Object) in Sub3
and foo(T) in Super<java.lang.String> have the same erasure, yet
neither overrides the other"
//class Sub3 extends Super<String> {
//  String foo(String str) {return "Sub3(String)";}
//  String foo(Object str) {return "Sub3(Object)";}
//}
// Sub4 is a compile error: "foo(java.lang.String) in Sub4 cannot
override foo(T) in Super; attempting to use incompatible return type"
//class Sub4 extends Super<String> {
//  void foo(String str) {System.out.println("Sub4(String)");}
//}
class Sub5 extends Super<String> {
  void foo(Object str) {System.out.println("Sub5(Object)");}
}
// Sub6 is a compile error: "foo(java.lang.String) in Sub6 cannot
override foo(T) in Super; attempting to use incompatible return type"
//class Sub6 extends Super<String> {
//  void foo(String str) {System.out.println("Sub6(String)");}
//  void foo(Object str) {System.out.println("Sub6(Object)");}
//}
// Sub7 is a compile error: "foo(java.lang.String) in Sub7 cannot
override foo(T) in Super; attempting to use incompatible return type"
//class Sub7 extends Super<String> {
//  void foo(String str) {System.out.println("Sub7(String)");}
//  String foo(Object str) {return "Sub7(Object)";}
//}
class Sub8 extends Super<String> {
  String foo(String str) {return "Sub8(String)";}
  void foo(Object str) {System.out.println("Sub8(Object)");}
}
public class Tester {
  public static void main(String[] args) {

    Super s1 = new Sub1();
    // Prints Sub1(String)
    try {System.out.println(s1.foo(""));} catch (Exception e)
{System.out.println(e);}
    // ClassCastException
    try {System.out.println(s1.foo(new Object()));} catch (Exception
e) {System.out.println(e);}
    Super<String> ss1 = new Sub1();
    // Prints Sub1(String)
    try {System.out.println(ss1.foo(""));} catch (Exception e)
{System.out.println(e);}
    Super s5 = new Sub5();
    // Prints Super
    try {System.out.println(s5.foo(""));} catch (Exception e)
{System.out.println(e);}
    // Prints Super. Really interesting that this *isn't* a ClassCastException.
    try {System.out.println(s5.foo(new Object()));} catch (Exception
e) {System.out.println(e);}
    Super<String> ss5 = new Sub5();
    // Prints Super
    try {System.out.println(ss5.foo(""));} catch (Exception e)
{System.out.println(e);}
    Super s8 = new Sub8();
    // Prints Sub8(String)
    try {System.out.println(s8.foo(""));} catch (Exception e)
{System.out.println(e);}
    // ClassCastException
    try {System.out.println(s8.foo(new Object()));} catch (Exception
e) {System.out.println(e);}
    Super<String> ss8 = new Sub8();
    // Prints Sub8(String)
    try {System.out.println(ss8.foo(""));} catch (Exception e)
{System.out.println(e);}
  }
}

What do I conclude from these results?

It appears that what actually happens is that the foo(String) method
of Sub1 actually gets compiled as if it were:
String foo(Object o) {foo((String) o);}
String foo(String str) {...}
I assume that the foo(Object) method is one of those "bridge" methods
that we're currently ignoring in japitools.

Furthermore Sub5 is interesting because it ends up with two methods
foo(Object), which differ only in return type. The one with return
type String is only accessible when used as an unqualified Super. In
other words the compiler probably doesn't actually insert a String
foo(Object) method here at all, it's just found at runtime by
superclass lookup.

Sub8 is just the combination of these two, but it's interesting
because in that case both String foo(Object) *and* void foo(Object)
must actually exist, with implementation bodies, in the class itself.
Presumably String foo(Object) is marked as ACC_BRIDGE and so will be
ignored by normal method lookup if the type is known at compiletime to
be Sub8.

What does this mean to Japitools?
Firstly, that many of the particularly evil cases are accounted for
and forbidden by the compiler.
Secondly, that ignoring bridge methods simplifies the Sub8 case.

But when I try to go into more detail it all seems more murky than
ever. Here's a breakdown as I see it...

Sub1 has the following methods:
1A) String foo(Object) (BRIDGE)
1B) String foo(Object but instantiated as String) (inherited from Super)
1C) String foo(String) (declared directly)

Sub5 has the following methods:
5A) String foo(Object but instantiated as String) (inherited from Super)
5B) void foo(Object) (declared directly)
5C) (maybe?) String foo(String) (BRIDGE?) (automatically added by
compiler? I can't think of a straightforward test for whether this
actually exists or not)

Sub8 has the following methods:
8A) String foo(Object) (BRIDGE)
8B) String foo(Object but instantiated as String) (inherited from Super)
8C) String foo(String) (declared directly)
8D) void foo(Object) (declared directly)

The goal is to try to compare these in a way that's meaningful both
from a 1.4 perspective and a 1.5 perspective. However...

>From a 1.4 perspective, 1A is an override of 1B, and 1C is an entirely
different method.
>From a 1.5 perspective 1A doesn't exist and 1C is an override of 1B.

>From a 1.4 perspective 5A and 5B are contradictory and 5C, if it
exists at all, is an entirely separate method.
>From a 1.5 perspective 5A and 5B are entirely separate and 5C doesn't exist.

>From a 1.4 perspective 8A is an override of 8B, 8D contradicts both of
them, and 8C is an entirely separate method.
>From a 1.5 perspective 8A doesn't exist, 8C is an override of 8B, and
8D is an entirely separate method.

How on earth do you reconcile that???

-- 
http://sab39.dev.netreach.com/




reply via email to

[Prev in Thread] Current Thread [Next in Thread]