To access a private field you need to set Field::setAccessible to true. You can pull the field off the super class. This code works:
CopyClass<?> clazz = Child.class;
Object cc = clazz.newInstance();
Field f1 = cc.getClass().getSuperclass().getDeclaredField("a_field");
f1.setAccessible(true);
f1.set(cc, "reflecting on life");
String str1 = (String) f1.get(cc);
System.out.println("field: " + str1);
Answer from John McClean on Stack OverflowTo access a private field you need to set Field::setAccessible to true. You can pull the field off the super class. This code works:
CopyClass<?> clazz = Child.class;
Object cc = clazz.newInstance();
Field f1 = cc.getClass().getSuperclass().getDeclaredField("a_field");
f1.setAccessible(true);
f1.set(cc, "reflecting on life");
String str1 = (String) f1.get(cc);
System.out.println("field: " + str1);
Using FieldUtils from the Apache Commons Lang 3:
CopyFieldUtils.writeField(childInstance, "a_field", "Hello", true);
The true forces it to set, even if the field is private.
Basically the problem is your utility method, which assumes you have an instance. It's reasonably easy to set a private static field - it's exactly the same procedure as for an instance field, except you specify null as the instance. Unfortunately your utility method uses the instance to get the class, and requires it to be non-null...
I'd echo Tom's caveat: don't do that. If this is a class you have under your control, I'd create a package level method:
void setFooForTesting(Bar newValue)
{
foo = newValue;
}
However, here's a complete sample if you really, really want to set it with reflection:
import java.lang.reflect.*;
class FieldContainer
{
private static String woot;
public static void showWoot()
{
System.out.println(woot);
}
}
public class Test
{
// Declared to throw Exception just for the sake of brevity here
public static void main(String[] args) throws Exception
{
Field field = FieldContainer.class.getDeclaredField("woot");
field.setAccessible(true);
field.set(null, "New value");
FieldContainer.showWoot();
}
}
Just pass null for the object-instance argument. So:
field.set(null, p_fieldValue);
This will let you set the static field.
Private does not mean it can't be mutated. Private means the reference of that object cannot access directly using the parent object. If you have a getter and which return object reference then any object which has that instance can mutate it.
Yes. By using reflection, you can access your private field without giving reference methods.
For example:
Field field = YourClass.class.getDeclaredField("fieldName");
field.setAccessible(true); // Force to access the field
// Set value
field.set(yourClassInstance, "Something");
// Get value
Object value = field.get(yourClassInstance);
Get all the methods and find the matching one, which has type info about the parameters:
String name;
String value;
Method[] methods = Child.class.getMethods();
for (Method method : methods) {
if (!method.getName().equals(name))
continue;
Class<?> paramType = method.getParameterTypes()[0];
//You will have to figure how to convert the String value to the parameter.
method.invoke(child, paramType.cast(value)); // for example
}
You could use Apache Commons FieldUtils.writeDeclaredField
Child childObject = new Child();
FieldUtils.writeDeclaredField(childObject, "name", "John", true);
Yes, it absolutely is - assuming you've got the appropriate security permissions. Use Field.setAccessible(true) first if you're accessing it from a different class.
import java.lang.reflect.*;
class Other
{
private String str;
public void setStr(String value)
{
str = value;
}
}
class Test
{
public static void main(String[] args)
// Just for the ease of a throwaway test. Don't
// do this normally!
throws Exception
{
Other t = new Other();
t.setStr("hi");
Field field = Other.class.getDeclaredField("str");
field.setAccessible(true);
Object value = field.get(t);
System.out.println(value);
}
}
And no, you shouldn't normally do this... it's subverting the intentions of the original author of the class. For example, there may well be validation applied in any situation where the field can normally be set, or other fields may be changed at the same time. You're effectively violating the intended level of encapsulation.
Yes.
Field f = Test.class.getDeclaredField("str");
f.setAccessible(true);//Very important, this allows the setting to work.
String value = (String) f.get(object);
Then you use the field object to get the value on an instance of the class.
Note that get method is often confusing for people. You have the field, but you don't have an instance of the object. You have to pass that to the get method
You are not missing anything. What you do depends entirely on your situation. However, consider this:
It is very common to do parameter validation in a setter. For example, let's say I have a class with field that can hold a value 0 through 10 (the "throws" is unnecessary for the exception type below but I include it for clarity):
public class Example {
private int value;
public Example () {
}
public final int getValue () {
return value;
}
public final void setValue (int value) throws IllegalArgumentException {
if (value < 0 || value > 10)
throw new IllegalArgumentException("Value is out of range.");
}
}
Here, setValue() validates 'value' to make sure it sticks to the rules. We have an invariant that states "an Example will not exist with an out of range value". Now let's say we want to make a constructor that takes a value. You might do this:
public class Example {
...
public Example (int value) {
this.value = value;
}
...
}
As you can see, there is a problem. The statement new Example(11) would succeed, and now an Example exists that breaks our rules. However, if we use the setter in the constructor, we can conveniently add all parameter validation to the constructor as well:
public class Example {
...
public Example (int value) throws IllegalArgumentException {
setValue(value); // throws if out of range
}
...
}
So there are many benefits to this.
Now, there are still cases when you might want to assign values directly. For one, maybe you don't have setters available (although I would argue that creating private or package private setters is still desirable, for the reasons mentioned above, for reflection/bean support if necessary, and for ease of validation in more complex code).
Another reason might be that perhaps you have a constructor that knows, somehow, ahead of time that valid values will be assigned, and therefore doesn't need validation and can assign variables directly. This is usually not a compelling reason to skip using setters though.
However, all-in-all, it's generally a good idea to use the setters everywhere when possible, it will usually lead to cleaner and clearer code that is easier to maintain as complexity increases.
Most of the examples you see where people set variables directly are just people being "lazy" - which is perfectly acceptable if the situation warrants it (perhaps you're writing a quick test program or application and don't want to implement a bunch of setters, for example). There's nothing wrong with that as long as you keep the big picture in mind and only be "lazy" when it's appropriate.
Something I'd like to add based on some of the other answers here: If you override a setter in a subclass, and the data you are setting breaks invariants that the base class assumes, then either the relevant setters should be made final or the base class should not make those assumptions. If overriding setters breaks base class invariants then there is a bigger issue at hand.
You'll notice the getter/setter is final in the above example. This is because our rule is that "any Example must have a value from 0 to 10". This rule therefore extends to subclasses. If we did not have that rule and if an Example could take on any value, then we would not need a final setter and could allow subclasses to override.
Hope that helps.
Sometimes when you would want make the class immutable, it is just one of the things you need to do. And don't have setter methods at all in that case.