Reflection

  • https://docs.oracle.com/javase/tutorial/reflect/
  • Uses:
    • Extensibility Features
    • Class Browsers and Visual Development Environments
    • Debuggers and Test Tools
      • debuggers can inspect private members
      • Test can discover set of APIs defined on class
  • Drawbacks:
    • Performance Overhead
      • since it is dynamic, certain JVM optimizations cannot be done
      • In general slower than non-reflection counterpart
    • Security Restrictions
      • requires a runtime permission which may not be present when running under a security manager, for example while running applet
    • Exposure of Internals
      • can result in unexpected side-effects, if private members are accessed
      • breaks abstractions
    • Maintenance issues
      • can complicate maintaining code, as the code’s behavior can change dynamically at runtime.

Class class

  • For every type of object, the JVM instantiates an immutable instance of java.lang.Class which provides methods to examine the runtime properties of the object including its members and type information.
  • It is entry point for all of the Reflection APIs
  • Class also provides the ability to create new classes and objects
  • You can access and work with following:
    • Class
    • Fields
    • Methods
    • Constructors

Retrieve Class objects

  • For reference types: Object.getClass()
  • For both reference + primitive types as well:
    • String.class: Object of Class<String>
    • int.class: Object of Class<Integer>
      • alias: Integer.TYPE
    • Integer.class: Object of Class<Integer> but different from int.class
  • For reference types, using fully qualified name: Class.forName("com.duke.MyLocaleServiceProvider")
  • For primitive wrapper types: Double.TYPE, Void.TYPE

Class info

  • getDeclaredXXX() methods are used to access fields which are directly declared inside the class
Class<?> clazz = Integer.class;
 
// name
clazz.getName();
clazz.getCanonicalName();
clazz.getClass();
clazz.getSuperClass();
 
// types, modifiers, annotations
clazz.getTypeName();
clazz.getTypeParameters();
clazz.getModifiers()
clazz.getAnnotations();
 
// fields
clazz.getFields();
clazz.getField("field-name");
clazz.getDeclaredFields();
clazz.getDeclaredField("field-name");
 
// methods: getDeclaredXXX() are omitted here
clazz.getMethods();
clazz.getMethod("method-name", ...parameterTypes);
 
// constructors: getDeclaredXXX() are omitted here
clazz.getConstructors();
clazz.getConstructor(...parameterTypes)
 
// classes, interfaces and enums: getDeclaredXXX() is omitted here
clazz.getClasses()

Call private constructor

  • Calling a private constructor is possible using reflection
var singleton = Singleton.getInstance();
 
Class<?> clazz = Singleton.class;
var ctor = clazz.getDeclaredConstructor();
ctor.setAccessible(true);
var newSingleton = ctor.newInstance();

Method handles