It is possible to obtain all fields with the method getDeclaredFields() of Class. Then you have to check the modifier of each fields to find the private ones:
List<Field> privateFields = new ArrayList<>();
Field[] allFields = SomeClass.class.getDeclaredFields();
for (Field field : allFields) {
if (Modifier.isPrivate(field.getModifiers())) {
privateFields.add(field);
}
}
Note that getDeclaredFields() will not return inherited fields.
Eventually, you get the type of the fields with the method Field.getType().
Answer from Cyrille Ka on Stack OverflowIt is possible to obtain all fields with the method getDeclaredFields() of Class. Then you have to check the modifier of each fields to find the private ones:
List<Field> privateFields = new ArrayList<>();
Field[] allFields = SomeClass.class.getDeclaredFields();
for (Field field : allFields) {
if (Modifier.isPrivate(field.getModifiers())) {
privateFields.add(field);
}
}
Note that getDeclaredFields() will not return inherited fields.
Eventually, you get the type of the fields with the method Field.getType().
You can use Modifier to determine if a field is private. Be sure to use the getDeclaredFields method to ensure that you retrieve private fields from the class, calling getFields will only return the public fields.
public class SomeClass {
private String aaa;
private Date date;
private double ccc;
public int notPrivate;
public static void main(String[] args) {
List<Field> fields = getPrivateFields(SomeClass.class);
for(Field field: fields){
System.out.println(field.getName());
}
}
public static List<Field> getPrivateFields(Class<?> theClass){
List<Field> privateFields = new ArrayList<Field>();
Field[] fields = theClass.getDeclaredFields();
for(Field field:fields){
if(Modifier.isPrivate(field.getModifiers())){
privateFields.add(field);
}
}
return privateFields;
}
}
obj = obj.getClass().getSuperclass().cast(obj);
This line does not do what you expect it to do. Casting an Object does not actually change it, it just tells the compiler to treat it as something else.
E.g. you can cast a List to a Collection, but it will still remain a List.
However, looping up through the super classes to access fields works fine without casting:
Class<?> current = yourClass;
while(current.getSuperclass()!=null){ // we don't want to process Object.class
// do something with current's fields
current = current.getSuperclass();
}
BTW, if you have access to the Spring Framework, there is a handy method for looping through the fields of a class and all super classes:
ReflectionUtils.doWithFields(baseClass, FieldCallback)
(also see this previous answer of mine: Access to private inherited fields via reflection in Java)
getDeclaredFields() gives you all fields on that Class, including private ones.
getFields() gives you all public fields on that Class AND it's superclasses.
If you want private / protected methods of Super Classes, you will have to repeatedly call getSuperclass() and then call getDeclaredFields() on the Super Class object.
Nothing here isn't clearly explained in the javadocs
In order to access private fields, you need to get them from the class's declared fields and then make them accessible:
Field f = obj.getClass().getDeclaredField("stuffIWant"); //NoSuchFieldException
f.setAccessible(true);
Hashtable iWantThis = (Hashtable) f.get(obj); //IllegalAccessException
EDIT: as has been commented by aperkins, both accessing the field, setting it as accessible and retrieving the value can throw Exceptions, although the only checked exceptions you need to be mindful of are commented above.
The NoSuchFieldException would be thrown if you asked for a field by a name which did not correspond to a declared field.
obj.getClass().getDeclaredField("misspelled"); //will throw NoSuchFieldException
The IllegalAccessException would be thrown if the field was not accessible (for example, if it is private and has not been made accessible via missing out the f.setAccessible(true) line.
The RuntimeExceptions which may be thrown are either SecurityExceptions (if the JVM's SecurityManager will not allow you to change a field's accessibility), or IllegalArgumentExceptions, if you try and access the field on an object not of the field's class's type:
f.get("BOB"); //will throw IllegalArgumentException, as String is of the wrong type
Try FieldUtils from Apache commons-lang3:
FieldUtils.readField(object, fieldName, true);
P.S. In my opinion, reflection is evil.
You can use the getDeclaredFields method of Class class to get all the fields that are declared in the class irrespective of its modifier. Using the getDeclaredFields method will provide you with an array of Field, which you can then iterate through, and call the getType method to get the types of the fields. The following code demonstrates the same:
class TestClass
{
private String x;
private int y;
private boolean z;
}
public class Test
{
public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchFieldException
{
Class clazz = TestClass.class;
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields)
{
System.out.println("fieldName: "+field.getName()+", fieldType: "+field.getType());
}
}
}
The above code outputs:
fieldName: x, fieldType: class java.lang.String
fieldName: y, fieldType: int
fieldName: z, fieldType: boolean
use below to list all private fields
List<Field> privateFields = new ArrayList<>();
Field[] allFields = SomeClass.class.getDeclaredFields();
for (Field field : allFields) {
if (Modifier.isPrivate(field.getModifiers())) {
privateFields.add(field);
System.out.format("type is", field.getType());
}
}
This is quite old question post but i'll provide an answer here for the sake of new searches.
Using the approach provided by @highlycaffeinated here: https://stackoverflow.com/a/6796254/776860
You can easily come up with a desired solution with a couple of changes.
Retrieving a list of private field names only
public List<String> getMap(Object o) throws IllegalArgumentException, IllegalAccessException {
List<String> result = new ArrayList<String>();
Field[] declaredFields = o.getClass().getDeclaredFields();
for (Field field : declaredFields) {
if(!field.isAccessible()) {
result.add(field.getName());
}
}
return result;
}
Retrieving a Map of all field names and their values
public Map<String, Object> getMap(Object o) throws IllegalArgumentException, IllegalAccessException {
Map<String, Object> result = new HashMap<String, Object>();
Field[] declaredFields = o.getClass().getDeclaredFields();
for (Field field : declaredFields) {
field.setAccessible(true);
result.put(field.getName(), field.get(o));
}
}
return result;
}
Exactly like @highlycaffeinated provided just with the additional line field.setAccessible(true); which enables you to introspect private fields too.
What you said, or maybe yourBean.getClass().getMethods()
and then method.getName().startsWith("get") on each method returned.
May I ask why you need to do this for?
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
Class.getDeclaredFields() returns the fields in the order of declaration. To get only the private ones:
for (Field field : YourClass.cass.getDeclaredFields())
if (Modifier.isPrivate(field.getModifiers()))
System.out.println(field.getName());
Note that inherited fields are not included, quoting from the javadoc:
Returns an array of Field objects reflecting all the fields declared by the class or interface represented by this Class object. This includes public, protected, default (package) access, and private fields, but excludes inherited fields.
For that, you have to do the same for the super class and implemented interfaces (recursively).
Warning:
Quoting from the javadoc:
The elements in the returned array are not sorted and are not in any particular order.
The API does not require the returned Field array to be sorted in any way, but in practice (Oracle implementation), they are in the same order as you declared them.
There's no way to be sure Class.getDeclaredFields() stays the way it behaves today. Oracle can change this at any time in any upcomming JDK!
If order is important to you I sugest to implement a field anotation which allows you to number the fields.
If you want to relay on the order in the code and don't want to relay on the current implementation of Class.getDeclaredFields() you have to parse the java source files yourself. Javaparser might save you a lot of time here.