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