Reflection in Java enables programs to inspect the structure of unknown classes at runtime, create instances of classes, access their fields, and run methods. The root class Object
defines a method getClass
which return an object of class Class
which allows information about the class of an object to be retrieved, e.g., get all fields of the class. This allows not just for passive inspection of the class structure, but also enables objects of a class to be created dynamically, to call methods of an object of the class, or to change or retrieve the value of an object's fields. Furthermore, every class has a static field class
which allows the Class
object corresponding to this class to be accessed. Have a look at the documention of this classes methods to learn more:
https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Class.html
import java.util.Arrays;
Class strClass = String.class;
return Arrays.toString(strClass.getFields());
package lecture;
public class A {
public int x;
public String y;
public void setBoth(int x, String y) {
this.x = x;
this.y = y;
}
public String toString() {
return "x: " + x + ", y: " + y;
}
}
import lecture.A;
import java.util.Arrays;
A a = new A();
Class aClass = a.getClass();
return Arrays.toString(aClass.getFields());
import lecture.A;
import java.util.Arrays;
A a = new A();
Class aClass = a.getClass();
return Arrays.toString(aClass.getMethods()).replaceAll("\\),", "\\)\n");
import lecture.A;
import java.util.Arrays;
import java.lang.reflect.Method;
A a = new A();
Class aClass = a.getClass();
Method setBoth = aClass.getMethod("setBoth", int.class, String.class); // get setBoth method
setBoth.invoke(a, 1, "helloh"); // call setBoth(1,"helloh") on a
Method toStr = aClass.getMethod("toString"); // get toString methdo
return (String) toStr.invoke(a); // call a's toString method
Annotations allow additional information to be stores with classes, fields, and methods. This information is accessible through reflection. Annotation are declared using <modifiers> @interface <name> {...
where <name>
is the name of the annotation. Methods in annotations are restricted to methods without parameters that do not throw exceptions. These methods determine the elements that can be stored in an annotation. Annotations are attached to classes, fields and methods using the syntax @A
or @A(<key-value pairs>)
where A
is an annotation type. @A(<key value pairs)
assigns values to the elements of the annotation. We show usage of build-in annotations here since beakerx does not support annotation definition. See here for an example.
package lecture;
public class OverridesSomething {
@Override // we use the build-in annotation @Override to indicate that this method is overriding a method declared by a superclass.
public String toString() {
return "I've got nothing";
}
}
import lecture.OverridesSomething;
import java.util.Arrays;
import java.lang.reflect.Method;
import java.lang.annotation.Annotation;
Class c = OverridesSomething.class;
Method m = c.getMethod("toString");
Annotation[] a = m.getAnnotations(); // not all annotations are available at runtime. @Override is not
return Arrays.toString(a);