This is not the only purpose of java.lang.reflect but it's good to know how to use the main classes of this namespace.
Suppose we have two classes in our project: com.test.Main and com.test.private.TestPrivate.
In Main class there's only the entry-point method static void main(String[] args).
TestPrivate class is without attributes so it's visible only for its namespace.
If I try to create a TestPrivate object on main method, the compiler shows me an error!
package com.test;
public class Main {
public static void main(String []args)
{
TestPrivate obj= new TestPrivate(); //cannot do this
}
}
This is the TestPrivate class:
package com.test.pvt;
class TestPrivate {
private TestPrivate()
{
System.out.println("constructor was called");
}
private void printSomething()
{
System.out.println("printSomething was called");
}
}
So How can I call the method printSomething?
public class Main {
public static void main(String []args)
{
//TestPrivate testPrivate= new TestPrivate() //doesn't work
Object testPrivate; //TestPrivate is certanily an object so I declare an object
//TestPrivate is private so I access the class in this way
Class<?> _cl= Class.forName("com.test.pvt.TestPrivate"); //get a class type
//Class is private, contrusctor is private, I need one to instantiate my object
Constructor<?> constructor= _cl.getDeclaredConstructor(); //get the simplest constructor
constructor.setAccessible(true); //I must set it as accessible otherwise I get an IllegalAccessException
testPrivate= constructor.newInstance(); //finally I can create my instance!
Method method= _cl.getDeclaredMethod("printSomething"); //now I can choose my method to invoke
method.setAccessible(true); //set it as accessible because it's private
method.invoke(testPrivate); //and finally invoke the instance method on my object testPrivate
}
}
This is my output
constructor was called printSomething was called
Let's quickly see another example..
I added to TestPrivateClass a member , another constructor and a non-void method.
package com.test.pvt;
class TestPrivate {
Integer number;
private TestPrivate()
{
System.out.println("constructor was called");
}
TestPrivate(Integer cacheNumber)
{
this.number=cacheNumber;
}
private void printSomething()
{
System.out.println("printSomething was called");
}
private Integer getNextNumber(Integer previousNumber)
{
if(number!=null)
return previousNumber+number+1;
return previousNumber+1;
}
}
I appended to main method of Main class these lines...
Object anotherObject;
Constructor<?> anotherConstructor= _cl.getDeclaredConstructor(Integer.class);
anotherConstructor.setAccessible(true);
anotherObject= anotherConstructor.newInstance(1);
Method anotherMethod= _cl.getDeclaredMethod("getNextNumber", Integer.class);
anotherMethod.setAccessible(true);
Object result1=anotherMethod.invoke(testPrivate, 1);
System.out.println("result from testPrivate object = " + result1.toString());
Object result2=anotherMethod.invoke(anotherObject, 1);
System.out.println("result from anotherObject object = " + result2.toString());
Guess the output =)
result from testPrivate object = 2 result from anotherObject object = 3
Imagine the power that you get with reflections.
Enjoy it but be careful... Exceptions are behind the corner :)
These examples just throws the following exceptions: SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException.
No comments:
Post a Comment