Very recently I came across the Reflection API and to my surprise we can access and even alter the private variables.I tried the following code
import java.l
Yes, It does violate OO concepts. However it does not break any java security model. It can be controlled by java security manager if necessary. Java reflection itself is an useful thing. It is used in Annotations and IOCs which are very useful concepts with ability to handle classes during runtime.
Isn't the reflection API changing the very purpose of Data Encapsulation?
Yes and no.
Why do we have to use Reflection API?
There are many uses of reflection that DO NOT break encapsulation; e.g. using reflection to find out what super types a class has, what annotations it has, what members it has, to invoke accessible methods and constructors, read and update accessible fields and so on.
And there are situations where is is acceptable (to varying degrees) to use the encapsulation breaking varieties of reflection:
You might need to look inside an encapsulated type (e.g. access / modify private fields) as the simplest way (or only way) to implement certain unit tests.
Some forms of Dependency Injection (aka IoC), Serialization and Persistence entail accessing and/or updating private fields.
Very occasionally, you need to break encapsulation to work around a bug in some class that you cannot fix.
I read in some sites that it can be used for testing purpose but according to me modules are tested and that can be done easily using JUnit test cases. So can anyone explain why do we have such a hack?
That depends on the design of your class. A class that is designed to be testable will either be testable without the need to access "private" state, or will expose that state (e.g. protected
getters) to allow testing. If the class doesn't do this, then a JUnit test may need to use reflection to look inside the abstraction.
This is not desirable (IMO), but if you are writing unit tests for a class that someone wrote, and you can't "tweak" the APIs to improve testability, then you may have to choose between using reflection or not testing at all.
The bottom line is that data encapsulation is an ideal that we strive to achieve (in Java), but there are situations where the pragmatically correct thing to do is to break it or ignore it.
Note that not all OO languages support strong data encapsulation like Java does. For example, Python and Javascript are both unarguably OO languages, yet both make it easy for one class to access and modify the state of objects of another class ... or even change the other classes behaviour. Strong data abstraction is not central to everyone's view of what Object-Oriented means.
You can't mix Encapsulation
,Polymorphism
with reflection.
Reflection has entirely different purpose.With reflection you can dynamically create types and execute it.You can access members of the class dynamically at runtime.
For example,recently I had used reflection for running Plugins
in my application.i.e I loaded the dll's from a particular directory,and then created object of the class through reflection by casting it to a shared interface..
Isn't the reflection API changing the very purpose of Data Encapsulation?
Don't get too hung up on the rules. There are times when it's useful to break them.
Reflextion is very useful. Take for example my code for logging finding changes so that I can log them to a database:
public static void log(String userID, Object bOld, Object bNew)
throws IntrospectionException, IllegalAccessException, InvocationTargetException {
String res = "";//String to hold the change record
boolean changed = false;
try {
if(bOld != null){ //if this is an update
BeanInfo beanInfo = Introspector.getBeanInfo(bOld.getClass());
res = bOld.getClass().getSimpleName() + " - ";
//loop and compare old values with new values and add them to our string if they are changed
for (PropertyDescriptor prop : beanInfo.getPropertyDescriptors()) {
Method getter = prop.getReadMethod();
Object vOld = getter.invoke(bOld); //old value
Object vNew = getter.invoke(bNew); //new value
if (vOld == vNew || (vOld != null && vOld.equals(vNew))) {
continue;
}
changed = true;
res = res + "(" + prop.getName() + ", " + vOld + ", " + vNew + ")";
}
}
It's a lot easier to do it this way. If I was using getters I would have to write a seperate method for each class and modify every time a new field was added. With reflection I can just write one method to handle all of my classes. I write about my method for logging changes here