Class Generator
Scenario:
We need to create a Java class, on the spur, in order to facilitate a particular
function. In other words, in the middle of running our program there is need
for class that needs to created such that the rest of the program runs as we
want it. We can not afford to stop our program (because perhaps users are
running it), rather we would like to spawn a new class that allows us to delegate certain tasks
to other classes. Not only must we create a class, but also compile and run
it.
Solution:
Note: There is no non-Reflection solution to this problem. Below we elaborate
on how we employ Reflection to fulfill our needs.
The new .java file can be created using a standard input/output stream that
is provided in the java.io package. Using the FileOutputStream
class, we create a file called Concat.java.
The purpose of this file is simply to concatenate the arguments that it receives
as input when its main method is invoked by our current (parent) class, ClassCreator.java.
The Process generator provided by the Java API allows us to create a runtime
process which enables us to compile the created file. It is important to wrap
this entire code within a try-catch block, to ensure that exceptions do not
rise through cause the rest of the program to stop from running.
Despite Java’s reputation of being platform independent, the particular code
responsible for executing the process thread, in ClassCreator.java,
will work on Linux machines, but may not work in other operating systems. In order to run this code on an alternate platform, one must simply
use a substitute code, outlined in the Java Reflection in Action reference book.
In the particular mock example provided the following code in ClassCreator.java:
:
:
m.invoke(null, new Object[] {new String[] {"Today"," is",
" a", " Thursday!"} });
:
:
produces the following result through Concat.java:
Today is a Thursday!
Conclusion:
In order to create a solution for our scenario without Reflection, we could
have generated the Concat.java
file, but we could not have invoked the main method. Though we could have run
the class by simply using the Process class in the API, Reflection allows us
to invoke any arbitrary method, with any given inputs. In addition, this process
gives us complete control over the name, location, and other attributes of the
new class created. Moreover, the dynamic solution facilitated by Reflection
allows the user to control the inputs passed to the new class (concat), via
the current class (classCreator).
Source
Code (ClassCreator.java)
Source Code (ProgressChecker.java)