|
|
YOUR FEEDBACK
Did you read today's front page stories & breaking news?
SOA World Conference
Virtualization Conference $200 Savings Expire May 16, 2008... – Register Today!
SYS-CON.TV |
TOP THREE LINKS YOU MUST CLICK ON Java Desktop
Private Conversations in Public
By: Joe Winchester
Digg This!
One of the principles of any OO language such as Java is an object's ability to encapsulate its data and provide clients with a specific and well-defined API. This is done through the visibility keywords public, protected, and private. The use of these is one of the first things any Java programmer learns; the fairly well-understood key points being that a public accessor (be it a method or a field) is visible to any other object, protected only to subclasses and private to no one but the class itself. A not-uncommon scenario, however, is that when you're using a class, you find a gem of a method you want to call that's been marked as private, or you want to access or modify a field that isn't visible to your class. I find this occurs quite a bit with frameworks where you might be extending or calling someone else's code and it works fairly well except for one little twist that you need to complete your task. There is a way (that I describe below) that allows you to access private methods and fields and it's a useful technique that, in these situations, enables you to code your way out of a blind alley. The secret lies in the java.lang.reflect package that lets you execute Java code reflectively. Typically this is used for such tasks as looking up a field, method, or constructor by name and then accessing it for a given object. It's very useful if your program has to consume objects at runtime that it has no prior knowledge of at compile time (like introspection, for example). The three classes - java.lang.reflect.Method, Field, and Constructor - however, all inherit from the java.lang.AccesibleObject. This has the method setAccessible(boolean) whose method comment is: * Set the "accessible" flag for this object to * the indicated boolean value. A value of "true" indicates that * the reflected object should suppress Java language access * checking when it is used. A value of "false" indicates * that the reflected object should enforce Java language access checks. To best way to illustrate this is to take class A, which has a private method isFooBar();
public class A{
private boolean fooBar;
private boolean isFooBar(){
return fooBar;
}
}
Using reflection we can get the method and execute it as follows:
A object = new A();
Method fooBarMethod = A.class.getDeclaredMethod("isFooBar");
fooBarMethod.setAccessible(true);
try{
System.out.println("FooBar=" + fooBarMethod.invoke(object);
} catch (Exception exc){
}
The key is the setAccessible(true) statement. If this weren't present, a java.lang.IllegalAccessException would be thrown. With the accessible set to true the code to execute the method and get the result can be in any class in the JVM. In addition to calling private methods, we can also set field values; the following code sets it to false:
Field fooBarField = A.class.getDeclaredField("fooBar");
fooBarField.setAccessible(true);
try{
fooBarField.set(object,Boolean.FALSE);
} catch (Exception exc){
}
We're using the method setAc-cessible(boolean) as it was designed to allow reflection to ignore any visibility constraints; however, the setAccessible(boolean) method does go through the security manager, which throws a SecurityException if this kind of private invocation is now allowed. The default JRE security manager does not prohibit the accessibility being overridden, and if you wanted to check your JVM to see whether or not this technique was going to work, the code would be:
try{
System.getSecurityManager().checkPermission(new ReflectPermission(""));
} catch (SecurityPermission exc){
// VM not going to let you do funky reflection
}
I don't recommend using reflection and accessibility as a matter of normal programming, but when you're in a tight spot with a deadline breathing down your neck and you can see the API you need but it's just not there, it can be a lifesaver. You'll be linking to private field names and methods though so the next version of the framework or class library you're abusing might very well change and break your code. You won't pick up this breaking change at compile time because it's reflective and will only die at runtime. It's very interesting that this month we have a great article on Java 2D and gaming, and last month we published a fantastic piece on Java3D using Mars rover images as examples. I hope this is a renaissance in both frameworks and we see more interesting uses in which Java apps can find their way onto the desktop. LATEST JAVA STORIES & POSTS
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
|
SYS-CON FEATURED WHITEPAPERS MOST READ THIS WEEK BREAKING JAVA NEWS
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||