| By Joe Winchester | Article Rating: |
|
| October 6, 2004 12:00 AM EDT | Reads: |
17,649 |
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.
Published October 6, 2004 Reads 17,649
Copyright © 2004 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By Joe Winchester
Joe Winchester, Editor-in-Chief of Java Developer's Journal, was formerly JDJ's longtime Desktop Technologies Editor and is a software developer working on development tools for IBM in Hursley, UK.
- It's the Java vs. C++ Shootout Revisited!
- Patterns for Building High Performance Applications
- Asynchronous Logging Using Spring
- Java for Programmers (2nd Edition)
- Cross-Platform Mobile Website Development – a Tool Comparison
- Three Buzzwords That Every CIO Hears but One They Should Listen To
- Write Once Run Anywhere or Cross Platform Mobile Development Tools
- Immersing into JavaScript Frameworks
- Workday Reportedly Prepping to Go Public
- Cloud Expo New York: The Java EE 7 Platform - Developing for the Cloud
- Book Review: Sams Teach Yourself Java in 24 Hours
- OpenOffice.com Lives
- Book Excerpt: Introducing HTML5
- Adobe Sends Flex to the Apache Foundation
- Five Years Waiting for JRE 7: Is It Justified? (Part 1)
- Book Excerpt: Java Application Profiling Tips and Tricks
- i-Technology in 2012: Five Industry Predictions
- It's the Java vs. C++ Shootout Revisited!
- Patterns for Building High Performance Applications
- OpenXava 4.3: Rapid Java Web Development
- The Next Web Architecture
- Asynchronous Logging Using Spring
- Java for Programmers (2nd Edition)
- Is Write Once Run Anywhere Ever Going to Be a Reality?
- A Cup of AJAX? Nay, Just Regular Java Please
- Java Developer's Journal Exclusive: 2006 "JDJ Editors' Choice" Awards
- JavaServer Faces (JSF) vs Struts
- The i-Technology Right Stuff
- Rich Internet Applications with Adobe Flex 2 and Java
- Java vs C++ "Shootout" Revisited
- Bean-Managed Persistence Using a Proxy List
- Reporting Made Easy with JasperReports and Hibernate
- Creating a Pet Store Application with JavaServer Faces, Spring, and Hibernate
- Why Do 'Cool Kids' Choose Ruby or PHP to Build Websites Instead of Java?
- What's New in Eclipse?
- i-Technology Predictions for 2007: Where's It All Headed?


















