You should pass the object to get method of the field, so
import java.lang.reflect.Field;
Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
Object value = field.get(object);
Answer from Dmitry Spikhalsky on Stack OverflowYou should pass the object to get method of the field, so
import java.lang.reflect.Field;
Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
Object value = field.get(object);
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);
}
}
You can use:
String value = (String) this.getClass().getDeclaredField("str").get(this);
Or in a more generalized and safer form:
Field field = anObject.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
String value = (String) field.get(anObject);
And for your example, this should be enough:
String value = this.str;
But you probably know of that one.
Note: anObject.getClass().getDeclaredField() is potentially unsafe as anObject.getClass() will return the actual class of anObject. See this example:
Object anObject = "Some string";
Class<?> clazz = anObject.getClass();
System.out.println(clazz);
Will print:
class java.lang.String
And not:
class java.lang.Object
So for your code's safety (and to avoid nasty errors when your code grows), you should use the actual class of the object you're trying to extract the field from:
Field field = YourObject.class.getDeclaredField(fieldName);
Imagine you have object in variable foo.
Then you need to get Field
Field field = foo.getClass().getDeclaredField("str");
then allow access to private field by:
field.setAccessible(true);
and you can have value by:
Object value = field.get(foo);
Since I don't know what exactly is stopping you from writing your code here are some tools which should be helpful:
to get array of fields declared in class use
Field[] fields = User.class.getDeclaredFields()to check what is the type assigned to field use
field.getType().to check if type is same as other type like List simply use
type.equals(List.class);to check if one type belongs to family of some ancestor (like List is subtype of Collection) use
isAssignableFromlikeCollection.class.isAssignableFrom(List.class)to check modifiers of field like
transientuseModifier.isTransient(field.getModifiers())to access value held by field in specific instance, use
Object value = field.get(instanceWithThatField)but in case of
privatefields you will need to make it accessible first viafield.setAccessible(true). Then if you are sure about what type of objectvalueholds you can cast it to that type likeList<Account> list = (List<Account>) value;or do both operations in one line, like in your case
List<Account> list = (List<Account>) field.get(userObject);which you can later iterate the way you want like
for(Account acc : list){ /*handle each acc*/ }
Elaborating on @Pshemo's answer, Here are the steps: (Please note its easier to get specific Type parameters from a Class than an Object, due to Type erasures.)
- Loop through the fields in User.
- For fields with predefined types check transcience.
- For Collections, get the type of of its parameter and if its a custom Type, run a recursion on that class.
e.g
private static void checkTranscience(Class<?> clazz) {
for (Field field : clazz.getDeclaredFields()) {
field.setAccessible(true);
System.out.println("Transience " + Modifier.isTransient(field.getModifiers()) + " for " + field.getName());
Class<?> fieldClass;
if (Collection.class.isAssignableFrom(field.getType())) {
//In case of Parameterized List or Set Field, extract genericClassType
fieldClass = (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
} else {
fieldClass = field.getType();
}
//Assuming Account belongs to "com.examplepackage.accountpackage" package to narrow down recursives to custom Types only
if (fieldClass.getName().contains("com.examplepackage.accountpackage")) {
checkTranscience(fieldClass);
}
}
class User {
private String x;
private List<String> stringList;
private List<Account> accounts;
private int y;
}
public static void main(){
checkTranscience(User.class);
}
You might have to tune the code a bit to get the specific result, but I'll leave that to the user.
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.
You can create instance from class object and that can be used in field get value.
Class modelClass = Class.forName("com.gati.stackoverflow.EX");
final Field field = modelClass.getDeclaredField("value");
field.setAccessible(true);
Object modelInstance=modelClass.newInstance();
field.get(modelInstance);
Assuming a simple case, where your field is public:
List list; // from your method
for(Object x : list) {
Class<?> clazz = x.getClass();
Field field = clazz.getField("fieldName"); //Note, this can throw an exception if the field doesn't exist.
Object fieldValue = field.get(x);
}
But this is pretty ugly, and I left out all of the try-catches, and makes a number of assumptions (public field, reflection available, nice security manager).
If you can change your method to return a List<Foo>, this becomes very easy because the iterator then can give you type information:
List<Foo> list; //From your method
for(Foo foo:list) {
Object fieldValue = foo.fieldName;
}
Or if you're consuming a Java 1.4 interface where generics aren't available, but you know the type of the objects that should be in the list...
List list;
for(Object x: list) {
if( x instanceof Foo) {
Object fieldValue = ((Foo)x).fieldName;
}
}
No reflection needed :)
I strongly recommend using Java generics to specify what type of object is in that List, ie. List<Car>. If you have Cars and Trucks you can use a common superclass/interface like this List<Vehicle>.
However, you can use Spring's ReflectionUtils to make fields accessible, even if they are private like the below runnable example:
List<Object> list = new ArrayList<Object>();
list.add("some value");
list.add(3);
for(Object obj : list)
{
Class<?> clazz = obj.getClass();
Field field = org.springframework.util.ReflectionUtils.findField(clazz, "value");
org.springframework.util.ReflectionUtils.makeAccessible(field);
System.out.println("value=" + field.get(obj));
}
Running this has an output of:
value=[C@1b67f74
value=3