Fun with method overriding
Given the following three classes:
package p1;
public class c1 { public static void main(String[] args) { c1 o = new c2(); o.m1(); o.m2();
o = new c3(); o.m1(); o.m2(); }
public void m1() { System.out.println("c1.m1"); }
void m2() { System.out.println("c1.m2"); } }
public class c3 extends c2 { public void m1() { System.out.println("c3.m1"); }
void m2() { System.out.println("c3.m2"); } }
package p2;
public class c2 extends c1 { void m1() { System.out.println("c2.m1"); }
private void m2() { System.out.println("c2.m2"); } }
What will be the output when running p1.c1? (note that javac will not compile this code as is, but it is possible to create the resulting class files with javac by temporarily changing the sources and then recompiling the individual classes, but for convenience I've provided the equivalent code in Jasmin source).
The output is (using Sun's JDK 1.4.0 with the -Xfuture switch to enforce accessibility checking): c2.m1 c1.m2 c2.m1 c3.m2
What does this mean?
- It's possible to override a public method with a package private method (c1.m1 is overridden by c2.m1)
- A private method never overrides another method (making c1.m2 public doesn't make any difference)
- Private methods don't get in the way when finding methods to override (c3.m2 overrides c1.m2, even though c2.m2 is "in the way")
Some other things I found:
- When invokespecial p1/c1/m2()V is added to c3.m2, it calls the private method c2.m2
- It isn't possible to override c3.m1 in another package, even though the original method (c1.m1) is public
I implemented support for these behaviours (except the ability to call private methods from outside of the class). It's also interesting to note that none of this is described in the JVM spec.
Fixed various bugs introduced by the classloader support.
Updated the binaries and source snaphots.
11:05:55 AM Comments
|