|
Breaching Java Rules with Reflection
We'll show you how to use the Java Reflection API to modify the behavior of runtime applications running in a Java Virtual Machine
Kunal Jaggi
Thursday, August 09, 2007
Have you ever wondered how your favorite IDE manages auto-completion of
method and field names? Even better, how does an object relational (OR) mapping
framework like Hibernate support default fields while persisting entity classes?
If all these questions sound geek, you must give the Reflection API a spin. Much
of the sizzle that has been caused by Java is because of power added by the
Reflection API to change the runtime behavior of an application that's running
inside a Java Virtual Machine (JVM). In this article, we'll look at the runtime
magic that Reflection provides to Hibernate O/R mapping framework and then we'll
use the Java Reflection API to break one of the fundamental rules of the Java
programming language--we'll access a method marked with the private access
modifier from the client code.
Hibernate mapping
To begin with, we'll look at Hibernate OR mapping framework. As an
illustration, consider the following mapping file which declares the persistent
properties of an entity class:
|
Direct Hit! |
|
Applies To: Advanced Java SE and Java EE developers
USP: Use Reflection to access a method
marked with private access modifier
Primary Link: http://java.sun.com/docs/
books/tutorial/reflect/index.html
Google Keywords: Java Reflection API
On PCQ Xtreme DVD: \system\Labs\
Reflection |
|
...
How does Hibernate get to know the Java type of the name and address
properties? How does Hibernate instantiate the Patient Plain Old Java Objects (POJO)
entity class? What's the significance of the default-access=field element? All
this and much more are possible through Reflection. Hibernate can access the
fields (including private) directly. Hibernate will try to determine the correct
conversion and mapping type itself without specifying the type attribute in the
mapping. Further, Hibernate recommends that the access of the default 'no
argument' constructor should be at least package level, as Hibernate needs to
instantiate the class through Reflection.
|
Jargon watch
- Hibernate – A framework for
mapping an object-oriented domain model to a traditional relational
database. Its purpose is to relieve the developer from a significant
amount of relational data persistence-related programming tasks.
- Plain Old Java Object (POJO)
– A Java object without any runtime dependencies other than Java Standard
Edition (SE) classes. The name is used to emphasize that the object in
question is an ordinary Java object and not a special object.
- Reflection – An API that
enables you to discover information
about fields, methods and constructors of loaded Java classes and even
modify this information.
|
Accessing private method using Reflection
According to Java Language Specification (JLS), 'A private class member or
constructor is accessible only within the body of the top level class that
encloses the declaration of the member or constructor.' This is a well known
Java rule that once a method or a field is declared with the private modifier,
it can't be accessed by any other class. But with Reflection, breaking this
fundamental rule is simple. Reflection provides a convenient handle to all
fields and methods irrespective of their accessibility.
We'll design a simple Java stack of patients as a part of our MedTracker
application to provide a LIFO implementation. Apart from the conventional push()
and pop() methods we'll provide an overloaded version of pop() method which
accepts an integer argument. The integral value specifies the number of elements
to be popped from the stack. As an illustration, consider the following code
listing which presents the patient stack:
private Patient[] pop(int elementCount) {
System.out.println("Inside private method
pop(int)");
if (elementCount < 0)
throw new IndexOutOfBoundsException();
Patient newPatients[]=new Patient[elementCount];
for(int i=0;i
return newPatients;
}
This code fragment is pretty straight forward. Inside the pop(int
elementCount) method, we've put a simple check for the elementCount argument;
for any negative value passed to this method, we propagate an
IndexOutOfBoundsException (an unchecked exception). For any positive value, we
populate a local array of Patient objects and return the same. Next, we'll call
the private pop(int elementCount) method from a standalone Java client through
Reflection.
 |
| Java Reflection API lets you hook on to
private objects and tweak their behavior at run time. The pop() method
appears to remove the given range of items from the stack |
Page(s) 1 2
|