-
1. Re: Changing method signatures
adrian.brock Feb 22, 2006 9:49 AM (in response to adrian.brock)I've backed out this change.
It doesn't work in the case where MyClass is an interface.
I get verification errors. :-)
e.g. trying to do MyInterface.toString()
So I need a different approach. -
2. Re: Changing method signatures
starksm64 Feb 22, 2006 1:49 PM (in response to adrian.brock)So what is this new jdk5 behavior, the compiler selects an overloaded method based on the return type? The bytecode is showing two methods for the AnotherClass.getSomething() method, but I don't see how one could use the reflection api to select one or the other. I'll have to try this.
[starksm@banshee9100 src]$ cat AnotherClass.java ISomething.java MyClass.java public class AnotherClass extends MyClass implements ISomething { public AnotherClass getSomething() { return this; } public ISomething getISomething() { return this; } } public interface ISomething { ISomething getISomething(); } public class MyClass { MyClass getSomething() { return this; } }
[starksm@banshee9100 src]$ javap -c -verbose AnotherClass Compiled from "AnotherClass.java" public class AnotherClass extends MyClass implements ISomething SourceFile: "AnotherClass.java" minor version: 0 major version: 49 Constant pool: const #1 = Method #4.#17; // MyClass."<init>":()V const #2 = Method #3.#18; // AnotherClass.getSomething:()LAnotherClass; const #3 = class #19; // AnotherClass const #4 = class #20; // MyClass const #5 = class #21; // ISomething const #6 = Asciz <init>; const #7 = Asciz ()V; const #8 = Asciz Code; const #9 = Asciz LineNumberTable; const #10 = Asciz getSomething; const #11 = Asciz ()LAnotherClass;; const #12 = Asciz getISomething; const #13 = Asciz ()LISomething;; const #14 = Asciz ()LMyClass;; const #15 = Asciz SourceFile; const #16 = Asciz AnotherClass.java; const #17 = NameAndType #6:#7;// "<init>":()V const #18 = NameAndType #10:#11;// getSomething:()LAnotherClass; const #19 = Asciz AnotherClass; const #20 = Asciz MyClass; const #21 = Asciz ISomething; { public AnotherClass(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: invokespecial #1; //Method MyClass."<init>":()V 4: return LineNumberTable: line 1: 0 public AnotherClass getSomething(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: areturn LineNumberTable: line 5: 0 public ISomething getISomething(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: areturn LineNumberTable: line 9: 0 public MyClass getSomething(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: invokevirtual #2; //Method getSomething:()LAnotherClass; 4: areturn LineNumberTable: line 1: 0 }
-
3. Re: Changing method signatures
starksm64 Feb 22, 2006 2:13 PM (in response to adrian.brock)So I don't get it. Reflect will return a "public volatile lang.reflect.MyClass lang.reflect.AnotherClass.getSomething()" (don't know what a volatile method is), but it cannot be explicitly selected, and is not selected based on return type by the compiler:
public class TestOverload { static void callBothGetSomething(AnotherClass ac) { MyClass mc = ac.getSomething(); AnotherClass mc2 = ac.getSomething(); } public static void main(String[] args) throws Exception { System.out.println("+++ AnotherClass.class.getMethods():"); Method[] methods = AnotherClass.class.getMethods(); for(Method m : methods) { System.out.println(m); } System.out.println("+++ AnotherClass.class.getMethod(getSomething):"); Class[] sig = {}; Method getSomething = AnotherClass.class.getMethod("getSomething", sig); System.out.println(getSomething); } }
Output:+++ AnotherClass.class.getMethods(): public volatile lang.reflect.MyClass lang.reflect.AnotherClass.getSomething() public lang.reflect.AnotherClass lang.reflect.AnotherClass.getSomething() public lang.reflect.ISomething lang.reflect.AnotherClass.getISomething() public native int java.lang.Object.hashCode() public final native java.lang.Class java.lang.Object.getClass() public final void java.lang.Object.wait() throws java.lang.InterruptedException public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException public boolean java.lang.Object.equals(java.lang.Object) public final native void java.lang.Object.notify() public final native void java.lang.Object.notifyAll() public java.lang.String java.lang.Object.toString() +++ AnotherClass.class.getMethod(getSomething): public lang.reflect.AnotherClass lang.reflect.AnotherClass.getSomething()
javap of the callBothGetSomething method only shows "public lang.reflect.AnotherClass lang.reflect.AnotherClass.getSomething()" being selected:static void callBothGetSomething(lang.reflect.AnotherClass); Code: 0: aload_0 1: invokevirtual #2; //Method lang/reflect/AnotherClass.getSomething:()Ll ang/reflect/AnotherClass; 4: astore_1 5: aload_0 6: invokevirtual #2; //Method lang/reflect/AnotherClass.getSomething:()Ll ang/reflect/AnotherClass; 9: astore_2 10: return
-
4. Re: Changing method signatures
adrian.brock Feb 23, 2006 5:00 AM (in response to adrian.brock)I think we'll have to rewrite the method invocation to be something like:
result = (DerivedClassReturnValue) ((DefiningSuperClass) derivedClassInstance).doSomething();
The volatile flag on the method, probably just tells the JDK5 runtime that the return type
has been changed?