The Special “Class” Object in Java: RTTI and Reflection

Overview

The special “Class” object in Java is discussed and it is the base for Java to perform RTTI and Reflection. Sample code for RTTI and Reflection is given too.

“Class”: The Special Class in Java

There is special class in Java named as “Class” based on which Java performs RTTI and possibly Reflection, one can treat it as the class for all the .class files, in the textbook the statement is still a bit confusing. Just treat “Class” as the general form for all the .class files which contain the attribute/methods/name/type (these are all metadata) of a class in Java. So each .class is an instance of this special class called “Class”. There several important facts which I think worthy to highlight:

1) There is one “Class” object for each class that is part of your program, and each time you write and compile a new class, a single “Class” object  (i.e., the instance of this special “Class” class)  is also created and stored persistently in an identically named .class file. So treat it as a class of .class files would be easier to imagine what exact it is and do not be confused about it with a normal class in Java, the “Class” class is a class of all the defined classes in Java.

2) All classes are loaded into the JVM dynamically, upon the first use of a class. For example, if you have an Apple class in your program, then you will have a Apple.class file which is an instance of the special “Class” class (not an instance of the Apple class), and to make an instance of Apple class, JVM uses a subsystems called class loader. To make it clearer, we can call Apple.class as “Class” instance by “Apple.class = new Class()”, and  call anything created from “new Apple()” as “Apple” instance. So here is how it works:  first JVM needs to load the Apple.class (“Class” instance) into memory. So it knows how to create “new Apple()”, so Apple.class is used to create Apple class instance. Read carefully, I hope I explained things clearly here though the concepts are quite  confusing.

3) The XXX.class is loaded into memory when the program makes the first reference to a static member of that class and constructor is also a static method of a class.

4) Java adopts Dynamical Loading , that is, a Java program is not completely loaded before it begins, but instead pieces of it are loaded when necessary. This is different from C++ which is a statically loaded language.

5) More concretely, the default class loader first checks to see if the “Class” object for that type (Apple.class) is loaded, if not, it finds the .class file and the bytes for the class are loaded and verified as well. Once the “Class” object (Apple.class) is in memory, it is used to create all objects of that type (new Apple()) .

6) “Class” class has a static method called forName(“ClassName”), so statement like Class.forName(“Apple”) will try to load the Apple.class if it is not in the memory.

7) In the program, there is only on stance for the “Class” instance of each class, that is, there is only one instance of Apple.class, and if you use “Class c = Class.getName(“Apple”)” which is actually equivalent to “Class c = new Apple(). getClass()”, in getName(“xxx”)  xxx has to be the full package path as net.tech-wonderland.Apple, otherwise, it will report ClassNotFound exception.

Java RTTI

After knowing what is “Class” in Java, we can talk about Java RTTI now

1) In order to get Runtime Type inforation RTTI, first get a reference Class c = Class.getName(“pk.Apple”), and we can use the methods in c like c.isInterface(), c.getSuperClass() to get any runtime type information interesting.

2) There are  three different forms of RTTI:

  • classic cast: (Circle)shape[i]
  • the “Class” object representing the type of your object which could be queried for useful runtime information like the type name, like the superClass and so on
  • instanceof to determine whether an object is an instance of a specific class type.

Java Reflection

1) Reflection is nothing magic actually, and it is still about  run time class information. One interpretation of this Java reflection concept is: The name reflection is used to describe code which is able to inspect other code in the same system (or itself).

2) And the following are quoted from “Think in Java”.

The class Class supports the concept of reflection, and there’s an additional library, java.lang.reflect,with classes FieldMethod, and Constructor (each of which implement the Member interface). Objects of these types are created by the JVM at run time to represent the corresponding member in the unknown class. You can then use the Constructors to create new objects, theget( ) and set( ) methods to read and modify the fields associated with Field objects, and the invoke( ) method to call a method associated with a Method object. In addition, you can call the convenience methods getFields( )getMethods( )getConstructors( ), etc., to return arrays of the objects representing the fields, methods, and constructors. (You can find out more by looking up the class Class in the JDK documentation.) Thus, the class information for anonymous objects can be completely determined at run time, and nothing need be known at compile time.

It’s important to realize that there’s nothing magic about reflection. When you’re using reflection to interact with an object of an unknown type, the JVM will simply look at the object and see that it belongs to a particular class (just like ordinary RTTI), but then, before it can do anything else, the Class object must be loaded. Thus, the .class file for that particular type must still be available to the JVM, either on the local machine or across the network. So the true difference between RTTI and reflection is that with RTTI, the compiler opens and examines the class file at compile time. Put another way, you can call all the methods of an object in the “normal” way. With reflection, the .class file is unavailable at compile time; it is opened and examined by the run-time environment.

3) The following is an example of how to use Java reflection to get runtime method information and run a method without know the class type at compile time.

Say you have an object of an unknown type in Java, and you would like to call a ‘unknownMethod’ method on it if one exists. Java’s static typing system isn’t really designed to support this unless the object conforms to a known interface, so it means, we won’t be able to call this method in the normal way like

UnknowClass inst = new UnknowClass();
inst.unknownMethod();

But using reflection, as long as we have the reference to the object, we can find out if it has a method called ‘unknownMethod’ and then call it if we want. We can do similar coding as follows:

Method method = unknowObj.getClass().getMethod("unknownMethod", null);
method.invoke(unknowObj, null);

4) Some applications of the Java reflection could be using it with annotations. For example, Junit will use reflection to look through our classes for methods tagged with the @Test annotation, and will then call them when running the unit test.

More on Java Reflection

1) To use Java Reflection, one has to know the signature, i.e., the name of the method and the parameter list. The the question is why do we bother to use Java Reflection, i.e., invoke() to call the method, why don’t we use obj.method(parameter list) to call it directly? The key of the answer to this question is: We don’t know the method at compile time! We only know this at run time! So obj.method(parameter list) won’t work at all.

2) Java Reflection could be convenient if we want to access private method or private members of the object. Of course, before using Java Reflection in such a case, you have to know the risk and security issues well in your mind.

3) You can find all the method names by Java Reflection.

4) I find Java Reflection might be useful to meet version backward compatibility. This happens say we updated our Java Code either adding or removing fields to some Class say Class A, and in the systems, there could be objects of Old A, we might want to detect whether the objects are of old format or of new format for compatibility concerns. This could be useful when Java objects need to be serialized and deserialized as byte stream.

Summary

The special “Class” object in Java is discussed and it is the base for Java to perform RTTI and Reflection. Sample code for RTTI and Reflection is given too.

Written on December 7, 2014