The disadvantages of reflection are as follows.
There are sophisticated applications that take advantage of reflection, such as analytical tools and dependency injection frameworks, but they are moving away from reflection as they see their shortcomings. If you're wondering if you should use reflection, you probably shouldn't.
Reflection is used in very limited cases.
Many programs that have to use a class that cannot be obtained at compile time have an appropriate type and superclass as the type to put the class at compile time (Item64).
In this case, you create instances reflectively and access those created instances via an interface or superclass.
As an example, in the following program, an instance of the subclass of `Set <String>`
specified by the first argument is created, and other command line arguments are packed in the Set and output as standard.
If HashSet is taken as the first argument, it will be displayed randomly, but if TreeSet is taken as the first argument, it will be displayed in alphabetical order.
package tryAny.effectiveJava;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.Set;
public class Reflection {
// Reflective instantiation with interface access
public static void main(String[] args) {
// Translate the class name into a Class object
Class<? extends Set<String>> cl = null;
try {
cl = (Class<? extends Set<String>>) // Unchecked cast!
Class.forName(args[0]);
} catch (ClassNotFoundException e) {
fatalError("Class not found.");
}
// Get the constructor
Constructor<? extends Set<String>> cons = null;
try {
cons = cl.getDeclaredConstructor();
} catch (NoSuchMethodException e) {
fatalError("No parameterless constructor");
}
// Instantiate the set
Set<String> s = null;
try {
s = cons.newInstance();
} catch (IllegalAccessException e) {
fatalError("Constructor not accessible");
} catch (InstantiationException e) {
fatalError("Class not instantiable.");
} catch (InvocationTargetException e) {
fatalError("Constructor threw " + e.getCause());
} catch (ClassCastException e) {
fatalError("Class doesn't implement Set");
}
// Exercise the set
s.addAll(Arrays.asList(args).subList(1, args.length));
System.out.println(s);
}
private static void fatalError(String msg) {
System.err.println(msg);
System.exit(1);
}
}
The technique used above is powerful enough to be used in a full-fledged service provider framework (? Item1). For the most part, this technique is all that is needed for reflection.
The above has two drawbacks.
In the above code, there is a warning when casting.
This warning is valid because the cast to `Class <? Extends Set <String >>`
is successful even if the name taken as the first argument is not the implementation class of Set.
See Item 27 for warning suppression.
A very rare case of using reflection is the dynamic use of multiple versions of a package. Compile the oldest version and dynamically call the method of the new class. (It doesn't come at all)
Recommended Posts