Getting value of public static final field/property of a class in Java via reflection
First retrieve the field property of the class, then you can retrieve the value. If you know the type you can use one of the get methods with null (for static fields only, in fact with a static field the argument passed to the get method is ignored entirely). Otherwise you can use getType and write an appropriate switch as below:
Field f = R.class.getField("_1st");
Class<?> t = f.getType();
if(t == int.class){
System.out.println(f.getInt(null));
}else if(t == double.class){
System.out.println(f.getDouble(null));
}...
Access static final variable using reflection
Accessing static fields is done exactly the same way as normal fields, only you don't need to pass any argument to Field.get()
method (you can pass a null).
Try this:
Object getFieldValue(String path) throws Exception {
int lastDot = path.lastIndexOf(".");
String className = path.substring(0, lastDot);
String fieldName = path.substring(lastDot + 1);
Class myClass = Class.forName(className);
Field myField = myClass.getDeclaredField(fieldName);
return myField.get(null);
}
How to get static final property from ClassName.class?
You should use:
for (Class<?> item : CLASSES) {
Field f = item.getDeclaredField("PROPERTY");
string.equals(f.get(item));
}
Is there a way to get all the static fields and its values from different class dynamically?
You could user reflection (Class name can be even dynamically passed):
package com.example;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Main {
public static void main(String[] args)
throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException {
printStaticFieldsAndValues("com.example.ClassWithStaticFields");
}
private static void printStaticFieldsAndValues(String className)
throws IllegalArgumentException, IllegalAccessException, ClassNotFoundException {
Class clazz = Class.forName(className);
for (Field f : clazz.getDeclaredFields()) {
if (Modifier.isStatic(f.getModifiers())) {
System.out.println("Name: " + f.getName());
System.out.println("Value " + f.get(null));
}
}
}
}
Class which has static fields:
package com.example;
public class ClassWithStaticFields {
static String stringField = "String Value";
}
Output:
Name: stringField
Value String Value
Change private static final field using Java reflection
Assuming no SecurityManager
is preventing you from doing this, you can use setAccessible
to get around private
and resetting the modifier to get rid of final
, and actually modify a private static final
field.
Here's an example:
import java.lang.reflect.*;
public class EverythingIsTrue {
static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
public static void main(String args[]) throws Exception {
setFinalStatic(Boolean.class.getField("FALSE"), true);
System.out.format("Everything is %s", false); // "Everything is true"
}
}
Assuming no SecurityException
is thrown, the above code prints "Everything is true"
.
What's actually done here is as follows:
- The primitive
boolean
valuestrue
andfalse
inmain
are autoboxed to reference typeBoolean
"constants"Boolean.TRUE
andBoolean.FALSE
- Reflection is used to change the
public static final Boolean.FALSE
to refer to theBoolean
referred to byBoolean.TRUE
- As a result, subsequently whenever a
false
is autoboxed toBoolean.FALSE
, it refers to the sameBoolean
as the one refered to byBoolean.TRUE
- Everything that was
"false"
now is"true"
Related questions
- Using reflection to change
static final File.separatorChar
for unit testing - How to limit setAccessible to only “legitimate” uses?
- Has examples of messing with
Integer
's cache, mutating aString
, etc
- Has examples of messing with
Caveats
Extreme care should be taken whenever you do something like this. It may not work because a SecurityManager
may be present, but even if it doesn't, depending on usage pattern, it may or may not work.
JLS 17.5.3 Subsequent Modification of Final Fields
In some cases, such as deserialization, the system will need to change the
final
fields of an object after construction.final
fields can be changed via reflection and other implementation dependent means. The only pattern in which this has reasonable semantics is one in which an object is constructed and then thefinal
fields of the object are updated. The object should not be made visible to other threads, nor should thefinal
fields be read, until all updates to thefinal
fields of the object are complete. Freezes of afinal
field occur both at the end of the constructor in which thefinal
field is set, and immediately after each modification of afinal
field via reflection or other special mechanism.Even then, there are a number of complications. If a
final
field is initialized to a compile-time constant in the field declaration, changes to thefinal
field may not be observed, since uses of thatfinal
field are replaced at compile time with the compile-time constant.Another problem is that the specification allows aggressive optimization of
final
fields. Within a thread, it is permissible to reorder reads of afinal
field with those modifications of a final field that do not take place in the constructor.
See also
- JLS 15.28 Constant Expression
- It's unlikely that this technique works with a primitive
private static final boolean
, because it's inlineable as a compile-time constant and thus the "new" value may not be observable
- It's unlikely that this technique works with a primitive
Appendix: On the bitwise manipulation
Essentially,
field.getModifiers() & ~Modifier.FINAL
turns off the bit corresponding to Modifier.FINAL
from field.getModifiers()
. &
is the bitwise-and, and ~
is the bitwise-complement.
See also
- Wikipedia/Bitwise operation
Remember Constant Expressions
Still not being able to solve this?, have fallen onto depression like I did for it? Does your code looks like this?
public class A {
private final String myVar = "Some Value";
}
Reading the comments on this answer, specially the one by @Pshemo, it reminded me that Constant Expressions are handled different so it will be impossible to modify it. Hence you will need to change your code to look like this:
public class A {
private final String myVar;
private A() {
myVar = "Some Value";
}
}
if you are not the owner of the class... I feel you!
For more details about why this behavior read this?
Retrieve only static fields declared in Java class
You can do it like this:
Field[] declaredFields = Test.class.getDeclaredFields();
List<Field> staticFields = new ArrayList<Field>();
for (Field field : declaredFields) {
if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) {
staticFields.add(field);
}
}
Get field values using reflection
Something like this...
import java.lang.reflect.Field;
public class Test {
public static void main(String... args) {
try {
Foobar foobar = new Foobar("Peter");
System.out.println("Name: " + foobar.getName());
Class<?> clazz = Class.forName("com.csa.mdm.Foobar");
System.out.println("Class: " + clazz);
Field field = clazz.getDeclaredField("name");
field.setAccessible(true);
String value = (String) field.get(foobar);
System.out.println("Value: " + value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Foobar {
private final String name;
public Foobar(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
Or, you can use the newInstance
method of class to get an instance of your object at runtime. You'll still need to set that instance variable first though, otherwise it won't have any value.
E.g.
Class<?> clazz = Class.forName("com.something.Foobar");
Object object = clazz.newInstance();
Or, where it has two parameters in its constructor, String and int for example...
Class<?> clazz = Class.forName("com.something.Foobar");
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
Object obj = constructor.newInstance("Meaning Of Life", 42);
Or you can interrogate it for its constructors at runtime using clazz.getConstructors()
NB I deliberately omitted the casting of the object created here to the kind expected, as that would defeat the point of the reflection, as you'd already be aware of the class if you do that, which would negate the need for reflection in the first place.
Reflection generic get field value
Like answered before, you should use:
Object value = field.get(objectInstance);
Another way, which is sometimes prefered, is calling the getter dynamically. example code:
public static Object runGetter(Field field, BaseValidationObject o)
{
// MZ: Find the correct method
for (Method method : o.getMethods())
{
if ((method.getName().startsWith("get")) && (method.getName().length() == (field.getName().length() + 3)))
{
if (method.getName().toLowerCase().endsWith(field.getName().toLowerCase()))
{
// MZ: Method found, run it
try
{
return method.invoke(o);
}
catch (IllegalAccessException e)
{
Logger.fatal("Could not determine method: " + method.getName());
}
catch (InvocationTargetException e)
{
Logger.fatal("Could not determine method: " + method.getName());
}
}
}
}
return null;
}
Also be aware that when your class inherits from another class, you need to recursively determine the Field. for instance, to fetch all Fields of a given class;
for (Class<?> c = someClass; c != null; c = c.getSuperclass())
{
Field[] fields = c.getDeclaredFields();
for (Field classField : fields)
{
result.add(classField);
}
}
Related Topics
What Does an Integer That Has Zero in Front of It Mean and How to Print It
Is the in Relation in Cassandra Bad for Queries
How to Rotate Jpeg Images Based on the Orientation Metadata
What Is the Point of Getters and Setters
Ways to Save Enums in Database
Location of Hibernate.Cfg.Xml in Project
Iteratively Compute the Cartesian Product of an Arbitrary Number of Sets
Oracle Jdbc Intermittent Connection Issue
Spring Batch - Using an Itemwriter with List of Lists
Creating New Generic Object with Wildcard
Javafx Exception in Thread "Main" Java.Lang.Noclassdeffounderror: Javafx/Application/Application
How to Create a Process in Java
What Are the Advantages of Using an Executorservice
Find an Array Inside Another Larger Array
Java: Jackson Polymorphic JSON Deserialization of an Object with an Interface Property
How to Prevent Parameter Binding from Interpreting Commas in Spring 3.0.5
Differences Between Just in Time Compilation and on Stack Replacement