private
isn't.December 06, 2003
On Friday I was getting a crash course in the JBoss/Spring/Velocity combination that we're experimenting with at work. We started with a trivial class, something like this:
public class Person {
private String firstName = "Peter";
private String lastName = "Penguin";
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
The template did something like this:
<p>Name: $Person.getFirstName() $Person.lastName</p>
We used both the getFirstName()
getter method and the lastName
variable to demonstrate that it worked both ways. But I didn't really understand how, since lastName
is private
. I vaguely remembered some way around this security restriction but couldn't remember the details. Not that it mattered, since it was unlikely that the technique was being used in Velocity, or even that it would work in a web environment.
So what's going on? I renamed getLastName()
to getLname()
and the template stopped working. Ah ha! Turns out that the template engine sees the lastName
variable and makes a reasonable stab at the getter method's name. That's a handy technique to keep in mind.
But what about this security restriction workaround that I thought I'd seen? Was I out of my mind? Amazingly, no! In "Subverting Java Access Protection for Unit Testing" Ross Burton writes about something that I've been wondering for some time: how to do decent unit testing in Java without making all my variables and methods public
or subverting my design just to make them available to test code in the same package.
The Java Reflection API allows the program to introspect arbitrary classes at runtime, accessing members at will. Most competent Java programmers should know this much, but what many don't know is that the security layer preventing you from accessing
private
members is only optional, and can be turned off. This allows the system code to be written without explicitly planning the unit tests, and if the unit tests really do need to access aprivate
orprotected
member, they can.
Excellent. This makes proper unit testing so much easier, as you aren't restricted to "black box" testing of just public methods. Wonderful. Maybe reading the fine print in the API documentation is worthwhile, after all.