Say we have a class called Test,
Class cls = Test.class; gives the class object for Test.
This is equivalent of
Class cls = Class.forName("Test");
Lets write a class, which does reflection to find out what are all the fields and methods for that class.
========================================
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test {
public Class cls = Test.class;
public static void main(String[] args) {
Field[] fields = Test.class.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
System.out.println(fields[i]);
}
Method[] methods = Test.class.getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
System.out.println(methods[i]);
}
}
}
========================================
interestingly, if you run this program, it prints
----------------------------------------
public java.lang.Class Test.cls
static java.lang.Class Test.class$Test
public static void Test.main(java.lang.String[])
static java.lang.Class Test.class$(java.lang.String)
----------------------------------------
*Note, this class is compiled using Sun's JDK 1.4.2 compiler. If you are using eclipse, you might get a different result.
So as you see, there is no "class" field as such, but we got a field called class$Test, and a method called Class class$(String).
Lets disassemble the class to find what is happening inside!'
For simplicity, im disassembling this class
========================================
public class Test {
public Class cls = Test.class;
}
========================================
.source Test.java
.class public super Test
.super java/lang/Object
.field public cls Ljava/lang/Class;
.field static class$Test Ljava/lang/Class;
.method public
.limit stack 3
.limit locals 1
.line 1
l0: aload_0
l1: invokespecial java/lang/Object/
.line 2
l4: aload_0
l5: getstatic Test/class$Test Ljava/lang/Class;
l8: ifnonnull l23
l11: ldc "Test"
l13: invokestatic Test/class$ (Ljava/lang/String;)Ljava/lang/Class;
l16: dup
l17: putstatic Test/class$Test Ljava/lang/Class;
l20: goto l26
l23: getstatic Test/class$Test Ljava/lang/Class;
l26: putfield Test/cls Ljava/lang/Class;
l29: return
.end method
.method static class$ (Ljava/lang/String;)Ljava/lang/Class;
.limit stack 3
.limit locals 2
.catch java/lang/ClassNotFoundException from l0 to l4 using l5
.line 2
l0: aload_0
l1: invokestatic java/lang/Class/forName (Ljava/lang/String;)Ljava/lang/Class;
l4: areturn
l5: astore_1
l6: new java/lang/NoClassDefFoundError
l9: dup
l10: aload_1
l11: invokevirtual java/lang/ClassNotFoundException/getMessage ()Ljava/lang/String;
l14: invokespecial java/lang/NoClassDefFoundError/
l17: athrow
.end method
========================================
Look at the constructor. What it does is
if (class$Test == null) {
class$Test = class$("Test")
}
cls = class$Test;
So it is pretty much evident that, the class object is once stored in class$Test.
And what happens in class$ method?
Well, this is what it does
return Class.forName(String) !! (Not counting the ClassNotFoundException)
So from this we can understand that the .class Field is just a syntactic sugar which the compiler provides, and not a real Field.
No comments:
Post a Comment