aspose file tools*
The moose likes Beginning Java and the fly likes reflection of private field in super class Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Beginning Java
Bookmark "reflection of private field in super class" Watch "reflection of private field in super class" New topic
Author

reflection of private field in super class

Maurice Le Chat
Greenhorn

Joined: Jan 20, 2009
Posts: 18
Situation:
The private field id (primary key of DB) ist set by the JEE container and JPA. For this reason no public setter for id shall exist.
To set the id for JUnit tests, reflection is used. To make it a little bit more complicated a class employee inherits from the super class Person. The id field exist in the Person class only.
The following code snippet from JUnit test class works:

Employee empl = new Employee();
try {
// access private field id and set a unique id otherwise set by DB through container
Person pers = new Person(); //ugly workaround, but it works, create dummy super class!
// inherited declared fields are not accessible but:
Field id = pers.getClass().getDeclaredField("id"); // get id ref from super class Person
id.setAccessible(true);
id.setLong(empl, Long.valueOf(i + 1)); // use id ref on employee!
id.setAccessible(false);
} catch (Exception e) {
//handle it
}

Questions:
1.) Though it works, it looks so weird to me, I suspect rather a bug than a feature!
2.) How to do it the clean way?
3.) Who can tell me more about this.

Any background information is welcome.

Cheers Maurice


SCJP 5
Henry Wong
author
Sheriff

Joined: Sep 28, 2004
Posts: 18855
    
  40

Maurice Le Chat wrote:
1.) Though it works, it looks so weird to me, I suspect rather a bug than a feature!


Not sure what you mean by "bug". Tools sometimes need to access private data components of instances, and reflection provides a way to do it.


Unless, you mean "bug" as in a security bug, in that you can access the private component that you should not be allowed to. Basically, the set accessible method goes through the security manager, if you are using a security manager that disallows it (such as loading from an applet), it will throw an exception.

Henry


Books: Java Threads, 3rd Edition, Jini in a Nutshell, and Java Gems (contributor)
Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4392
    
    8

You don't need an instance of a class to get the Class object - you can use a class literal. You can delete the line creating a Person, and replace pers.getClass() with Person.class.
Jesper de Jong
Java Cowboy
Saloon Keeper

Joined: Aug 16, 2005
Posts: 14164
    
  19

Maurice Le Chat wrote:
Questions:
1.) Though it works, it looks so weird to me, I suspect rather a bug than a feature!
2.) How to do it the clean way?
3.) Who can tell me more about this.

You can access private members through reflection. Access specifiers such as protected and private are not meant as security measures, to make data invisible under all circumstances.

There is really no clean way to access private members from outside the class. The whole purpose of private members is to make them not accessible from outside the class. If you want to be able to change the value of a member variable cleanly, provide a setter method (which can be public) to set the value.

Accessing private member variables through reflection is a trick that some frameworks such as Hibernate use. You shouldn't normally do such things in your code yourself.


Java Beginners FAQ - JavaRanch SCJP FAQ - The Java Tutorial - Java SE 7 API documentation
Scala Notes - My blog about Scala
Maurice Le Chat
Greenhorn

Joined: Jan 20, 2009
Posts: 18
@Matthiew
You are right of course! I didn't yet think about optimizing. I was surprised by the fact to get a handle (field object) to the private id field I want, simply going through the superclass and being able to use this reference to access the id field in a real object, being an extention of this superclass!

@Jesper @Henry
The above is the point! Please read carefully my description of the situation. The application use JPA. A couple of years ago I would have used Hibernate. Anway it's the same. I know reflection and it's use by tools. The point is:
Java SE API says clearly for getDeclaredFields() " ... This includes public, protected, default (package) access, and private fields, but excludes inherited fields." In fact calling getDeclaredField("id") on th derived class Employee throws NoSuchFieldException! So far no surprise. I wonder the fact it's so easy to circumvent this limitation by getting a field object of the superclass and later manipulating with this same object a previously created object of a derived class!
Though I use the reflection in JUnit only, I would be assured to know if this behaviour is by specification, or by accident! If the latter is true, I would like to know, how others do it, or how the tools (Hibernate, etc.) do it.

Thanks

Maurice
Rob Spoor
Sheriff

Joined: Oct 27, 2005
Posts: 19697
    
  20

Maurice Le Chat wrote:I wonder the fact it's so easy to circumvent this limitation by getting a field object of the superclass and later manipulating with this same object a previously created object of a derived class!

Well, have you tried? You may be surprised!


SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6
How To Ask Questions How To Answer Questions
Maurice Le Chat
Greenhorn

Joined: Jan 20, 2009
Posts: 18
Of course I tried! I havent seen any surprise! The main intend of this thread is to avoid future surprises by getting deeper knowledge from the community. Please explain what do you mean by surprise!
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: reflection of private field in super class