|
|
Invocations of non-static overridden methods on either the base class or derived class reference result in the execution of the method defined in the derived class. However in case of static overridden methods, the scenario is different. When the invocations are performed on a derived class reference, it behaves exactly like a non-static method with the overridden static method being executed. However, when the reference is a baseClass reference the method that is executed is the static method defined in the baseClass. The example below demostrates this fact. For more information please refer to the section on static methods in Documents.Java-Phenomenon.
JAR Files: Please refer to the Java-Basics section for more information on using JAR files. (a) Test.jar Source of baseClass.java public class baseClass { public void methodOne() { System.out.println(" baseClass.methodOne() [Non-Static]"); } public static void methodTwo() { System.out.println(" baseClass.methodTwo() [Static]"); } public void methodThree() { System.out.println(" baseClass.methodThree() [Non-Static]"); } } Source of derivedClass.java public class derivedClass extends baseClass{ public void methodOne() { System.out.println(" derivedClass.methodOne() [Non-Static]"); } public static void methodTwo() { System.out.println(" derivedClass.methodTwo() [Static]"); } } Source of Test.java public class Test { public static void main(String[] args) { baseClass b = new baseClass(); derivedClass d = new derivedClass(); System.out.println("\n Calling the three methods"); System.out.println(" with a baseClass reference pointing"); System.out.println(" to an object of class baseClass"); b.methodOne(); b.methodTwo(); b.methodThree(); System.out.println("\n Calling the three methods"); System.out.println(" with a derivedClass reference pointing"); System.out.println(" to an object of class derivedClass"); d.methodOne(); d.methodTwo(); d.methodThree(); baseClass baseRef = new derivedClass(); derivedClass derivedRef = new derivedClass(); System.out.println("\n Calling the three methods"); System.out.println(" with a derivedClass reference pointing"); System.out.println(" to an object of class derivedClass"); baseRef.methodOne(); baseRef.methodTwo(); baseRef.methodThree(); System.out.println("\n Calling the three methods"); System.out.println(" with a derivedClass reference pointing"); System.out.println(" to an object of class derivedClass"); derivedRef.methodOne(); derivedRef.methodTwo(); derivedRef.methodThree(); } } Output of the Test program: C:\>java Test Calling the three methods with a baseClass reference pointing to an object of class baseClass baseClass.methodOne() [Non-Static] baseClass.methodTwo() [Static] baseClass.methodThree() [Non-Static] Calling the three methods with a derivedClass reference pointing to an object of class derivedClass derivedClass.methodOne() [Non-Static] derivedClass.methodTwo() [Static] baseClass.methodThree() [Non-Static] Calling the three methods with a derivedClass reference pointing to an object of class derivedClass derivedClass.methodOne() [Non-Static] baseClass.methodTwo() [Static] baseClass.methodThree() [Non-Static] Calling the three methods with a derivedClass reference pointing to an object of class derivedClass derivedClass.methodOne() [Non-Static] derivedClass.methodTwo() [Static] baseClass.methodThree() [Non-Static] Output of javap for baseClass.class Compiled from baseClass.java public class baseClass extends java.lang.Object /* ACC_SUPER bit set */ { public baseClass(); public void methodOne(); public void methodThree(); public static void methodTwo(); } Method baseClass() 0 aload_0 1 invokespecial #8 <Method java.lang.Object()> 4 return Method void methodOne() 0 getstatic #9 <Field java.io.PrintStream out> 3 ldc #1 <String " baseClass.methodOne() [Non-Static]"> 5 invokevirtual #10 <Method void println(java.lang.String)> 8 return Method void methodThree() 0 getstatic #9 <Field java.io.PrintStream out> 3 ldc #2 <String " baseClass.methodThree() [Non-Static]"> 5 invokevirtual #10 <Method void println(java.lang.String)> 8 return Method void methodTwo() 0 getstatic #9 <Field java.io.PrintStream out> 3 ldc #3 <String " baseClass.methodTwo() [Static]"> 5 invokevirtual #10 <Method void println(java.lang.String)> 8 return Output of javap for derivedClass.class Compiled from derivedClass.java public class derivedClass extends baseClass /* ACC_SUPER bit set */ { public derivedClass(); public void methodOne(); public static void methodTwo(); } Method derivedClass() 0 aload_0 1 invokespecial #7 <Method baseClass()> 4 return Method void methodOne() 0 getstatic #8 <Field java.io.PrintStream out> 3 ldc #1 <String " derivedClass.methodOne() [Non-Static]"> 5 invokevirtual #9 <Method void println(java.lang.String)> 8 return Method void methodTwo() 0 getstatic #8 <Field java.io.PrintStream out> 3 ldc #2 <String " derivedClass.methodTwo() [Static]"> 5 invokevirtual #9 <Method void println(java.lang.String)> 8 return Output of javap for Test.class Compiled from Test.java public class Test extends java.lang.Object /* ACC_SUPER bit set */ { public Test(); public static void main(java.lang.String[]); } Method Test() 0 aload_0 1 invokespecial #14 <Method java.lang.Object()> 4 return Method void main(java.lang.String[]) 0 new #7 <Class baseClass> 3 dup 4 invokespecial #12 <Method baseClass()> 7 astore_1 8 new #8 <Class derivedClass> 11 dup 12 invokespecial #13 <Method derivedClass()> 15 astore_2 16 getstatic #20 <Field java.io.PrintStream out> 19 ldc #1 <String " Calling the three methods"> 21 invokevirtual #21 <Method void println(java.lang.String)> 24 getstatic #20 <Field java.io.PrintStream out> 27 ldc #4 <String " with a baseClass reference pointing"> 29 invokevirtual #21 <Method void println(java.lang.String)> 32 getstatic #20 <Field java.io.PrintStream out> 35 ldc #2 <String " to an object of class baseClass"> 37 invokevirtual #21 <Method void println(java.lang.String)> 40 aload_1 41 invokevirtual #15 <Method void methodOne()> 44 invokestatic #18 <Method void methodTwo()> 47 aload_1 48 invokevirtual #17 <Method void methodThree()> 51 getstatic #20 <Field java.io.PrintStream out> 54 ldc #1 <String " Calling the three methods"> 56 invokevirtual #21 <Method void println(java.lang.String)> 59 getstatic #20 <Field java.io.PrintStream out> 62 ldc #5 <String " with a derivedClass reference pointing"> 64 invokevirtual #21 <Method void println(java.lang.String)> 67 getstatic #20 <Field java.io.PrintStream out> 70 ldc #3 <String " to an object of class derivedClass"> 72 invokevirtual #21 <Method void println(java.lang.String)> 75 aload_2 76 invokevirtual #16 <Method void methodOne()> 79 invokestatic #19 <Method void methodTwo()> 82 aload_2 83 invokevirtual #17 <Method void methodThree()> 86 new #8 <Class derivedClass> 89 dup 90 invokespecial #13 <Method derivedClass()> 93 astore_3 94 new #8 <Class derivedClass> 97 dup 98 invokespecial #13 <Method derivedClass()> 101 astore 4 103 getstatic #20 <Field java.io.PrintStream out> 106 ldc #1 <String " Calling the three methods"> 108 invokevirtual #21 <Method void println(java.lang.String)> 111 getstatic #20 <Field java.io.PrintStream out> 114 ldc #5 <String " with a derivedClass reference pointing"> 116 invokevirtual #21 <Method void println(java.lang.String)> 119 getstatic #20 <Field java.io.PrintStream out> 122 ldc #3 <String " to an object of class derivedClass"> 124 invokevirtual #21 <Method void println(java.lang.String)> 127 aload_3 128 invokevirtual #15 <Method void methodOne()> 131 invokestatic #18 <Method void methodTwo()> 134 aload_3 135 invokevirtual #17 <Method void methodThree()> 138 getstatic #20 <Field java.io.PrintStream out> 141 ldc #1 <String " Calling the three methods"> 143 invokevirtual #21 <Method void println(java.lang.String)> 146 getstatic #20 <Field java.io.PrintStream out> 149 ldc #5 <String " with a derivedClass reference pointing"> 151 invokevirtual #21 <Method void println(java.lang.String)> 154 getstatic #20 <Field java.io.PrintStream out> 157 ldc #3 <String " to an object of class derivedClass"> 159 invokevirtual #21 <Method void println(java.lang.String)> 162 aload 4 164 invokevirtual #16 <Method void methodOne()> 167 invokestatic #19 <Method void methodTwo()> 170 aload 4 172 invokevirtual #17 <Method void methodThree()> 175 return
Partial Output form JAM (Java Analyzing Module) for Test.class Constant Count: 54 Actually: 53 1 [TagClass] name_index: 28 2 [TagClass] name_index: 29 3 [TagClass] name_index: 30 4 [TagClass] name_index: 31 5 [TagClass] name_index: 32 6 [TagString] string_index: 41 7 [TagString] string_index: 43 8 [TagString] string_index: 44 9 [TagString] string_index: 45 10 [TagString] string_index: 46 11 [TagString] string_index: 47 12 [TagMethodref] class_index: 7 name_and_type_index: 22 13 [TagMethodref] class_index: 8 name_and_type_index: 22 14 [TagMethodref] class_index: 10 name_and_type_index: 22 15 [TagMethodref] class_index: 7 name_and_type_index: 23 16 [TagMethodref] class_index: 8 name_and_type_index: 23 17 [TagMethodref] class_index: 7 name_and_type_index: 24 18 [TagMethodref] class_index: 7 name_and_type_index: 25 19 [TagMethodref] class_index: 8 name_and_type_index: 25 20 [TagFieldref] class_index: 11 name_and_type_index: 26 21 [TagMethodref] class_index: 9 name_and_type_index: 27 22 [TagNameAndType] name_index: 36 type_index: 33 23 [TagNameAndType] name_index: 49 type_index: 33 24 [TagNameAndType] name_index: 50 type_index: 33 25 [TagNameAndType] name_index: 51 type_index: 33 26 [TagNameAndType] name_index: 52 type_index: 39 27 [TagNameAndType] name_index: 53 type_index: 34 28 [TagUtf8] length: 28 bytes: Calling the three methods 29 [TagUtf8] length: 33 bytes: to an object of class baseClass 30 [TagUtf8] length: 36 bytes: to an object of class derivedClass 31 [TagUtf8] length: 37 bytes: with a baseClass reference pointing 32 [TagUtf8] length: 40 bytes: with a derivedClass reference pointing 33 [TagUtf8] length: 3 bytes: ()V 34 [TagUtf8] length: 21 bytes: (Ljava/lang/String;)V 35 [TagUtf8] length: 22 bytes: ([Ljava/lang/String;)V 36 [TagUtf8] length: 6 bytes: <init> 37 [TagUtf8] length: 4 bytes: Code 38 [TagUtf8] length: 15 bytes: LineNumberTable 39 [TagUtf8] length: 21 bytes: Ljava/io/PrintStream; 40 [TagUtf8] length: 10 bytes: SourceFile 41 [TagUtf8] length: 4 bytes: Test 42 [TagUtf8] length: 9 bytes: Test.java 43 [TagUtf8] length: 9 bytes: baseClass 44 [TagUtf8] length: 12 bytes: derivedClass 45 [TagUtf8] length: 19 bytes: java/io/PrintStream 46 [TagUtf8] length: 16 bytes: java/lang/Object 47 [TagUtf8] length: 16 bytes: java/lang/System 48 [TagUtf8] length: 4 bytes: main 49 [TagUtf8] length: 9 bytes: methodOne 50 [TagUtf8] length: 11 bytes: methodThree 51 [TagUtf8] length: 9 bytes: methodTwo 52 [TagUtf8] length: 3 bytes: out 53 [TagUtf8] length: 7 bytes: println Looking closer into the class file Test.class with a tool such as JAM, we notice that the MethodRef constant in the 18th position in the constant pool is a method belonging to the class baseClass and that the MethodRef constant in the 19th position in the constant pool is a method beloging to the class derivedClass. From this we conclude that the choice of which static method to call is made during compile time. Also.... |