Getting a list of all fields in an object
I’ve got the following code that I use to output a list of all (public) fields in an object in an easy(ish) to read way. The issue with it is that the code is not easy to look at, and I’m not sure what I could do to improve it. I’m not too fond of all of the StringBuilders, the append calls are ugly and chaining them does not help the situation however I can’t see a better way of doing it.
public abstract class Component < private String[] getFields() < Class extends Component>componentClass = getClass(); List lines = new ArrayList<>(); for (Field field: componentClass.getFields()) < StringBuilder lineBuilder = new StringBuilder(); lineBuilder.append(field.getName()); field.setAccessible(true); try < Object value = field.get(this); lineBuilder.append(" = "); lineBuilder.append(value); >catch (IllegalAccessException e) < lineBuilder.append(" >"); lineBuilder.append(e.getClass().getSimpleName()); > lines.add(lineBuilder.toString()); > return lines.toArray(new String[lines.size()]); > @Override public final String toString() < StringBuilder builder = new StringBuilder(getClass().getSimpleName()); boolean firstIteration = true; builder.append('('); for (String field: getFields()) < if (!firstIteration) < builder.append(", "); >else < firstIteration = false; >builder.append(field); > builder.append(')'); return builder.toString(); > >
I’m not entirely sure why I separated getFields into it’s own method, however it might be better to move it back into toString .
2 Answers 2
If you are using Java 8, you can do:
private String[] getFields() < Class extends Component>componentClass = getClass(); Field[] fields = componentClass.getFields(); List lines = new ArrayList<>(fields.length); Arrays.stream(fields).forEach(field -> < field.setAccessible(true); try < lines.add(field.getName() + " = " + field.get(this)); >catch (final IllegalAccessException e) < lines.add(field.getName() + " >" + e.getClass().getSimpleName()); > >); return lines.toArray(new String[lines.size()]); >
private String[] getFields() < Class extends Component>componentClass = getClass(); Field[] fields = componentClass.getFields(); List lines = new ArrayList<>(fields.length); Arrays.stream(fields) .forEach( field -> < field.setAccessible(true); try < lines.add(field.getName() + " = " + field.get(this)); >catch (final IllegalAccessException e) < lines.add(field.getName() + " >" + e.getClass().getSimpleName()); > >); return lines.toArray(new String[lines.size()]); >
Note that this is adding to @EricStein’s excellent answer on normal concatenation instead of StringBuilder s.
(I’m just starting to look into Streams , so if this is bad, please comment on why)
lineBuilder.append(" > "); lineBuilder.append(e.getClass().getSimpleName());
lineBuilder.append(" > ").append(e.getClass().getSimpleName());
Also, I would use a simple array instead of an ArrayList :
private String[] getFields() < ClasscomponentClass = getClass(); Field[] fields = componentClass.getFields(); String[] lines = new String[fields.length]; int index = 0; for (Field field : fields) < StringBuilder lineBuilder = new StringBuilder(); lineBuilder.append(field.getName()); field.setAccessible(true); try < Object value = field.get(this); lineBuilder.append(" = "); lineBuilder.append(value); >catch (IllegalAccessException e) < lineBuilder.append(" >"); lineBuilder.append(e.getClass().getSimpleName()); > lines[index++] = lineBuilder.toString(); > return lines; >
EDIT: The above review, if not using Java 8, should be replaced by @EricStein’s code.
Also, getFields() is a bad name. Try getFieldDescriptions() .
Java Get All Field Names of Class
In this Java tutorial we learn how to implement an utility class to programmatically get all field names of the class and supper classes of an object in Java.
Table of contents
Example Java classes to get field names
For example, we have two class BaseEntity and Customer which Customer class extends the BaseEntity class as below.
public class BaseEntity private Long id; public Long getId() return id; > public void setId(Long id) this.id = id; > >
public class Customer extends BaseEntity private String name; private String email; private String phone; public String getName() return name; > public void setName(String name) this.name = name; > public String getEmail() return email; > public void setEmail(String email) this.email = email; > public String getPhone() return phone; > public void setPhone(String phone) this.phone = phone; > >
If we have an instance of Customer class as below.
Customer customer = new Customer();
And we want to programmatically get list of field names of the customer object then we can do next step.
Implement Utility Class to get All Field Names
In order to get the all fields of an object we need to get all classes related to it including super classes as following Java code.
ListClass> listOfClasses = new ArrayList<>(); listOfClasses.add(classToGetFields); Class superClass = classToGetFields.getSuperclass(); while(superClass != null && superClass != Object.class) listOfClasses.add(superClass); superClass = superClass.getSuperclass(); >
From the above listOfClasses result we can loop it and get the list of field names.
Below is the final ClassUtils utility class.
import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; public class ClassUtils public static ListString> getAllFieldNames(Class classToGetFields) ListString> result = new ArrayList<>(); ListClass> listOfClasses = new ArrayList<>(); listOfClasses.add(classToGetFields); Class superClass = classToGetFields.getSuperclass(); while(superClass != null && superClass != Object.class) listOfClasses.add(superClass); superClass = superClass.getSuperclass(); > for(Class aClass : listOfClasses) for(Field field : aClass.getDeclaredFields()) result.add(field.getName()); > > return result; > >
How to use the ClassUtils class
The following Java program to show you how to use the above ClassUtils class to get field names of an object.
import java.util.List; public class FieldNamesExample1 public static void main(String. args) Customer customer = new Customer(); ListString> allFieldNames = ClassUtils.getAllFieldNames(customer.getClass()); allFieldNames.forEach(System.out::println); > >
More example Java program to retrieve all field names of the BaseEntity class.
import java.util.List; public class FieldNamesExample2 public static void main(String. args) BaseEntity baseEntity = new BaseEntity(); ListString> allFieldNames = ClassUtils.getAllFieldNames(baseEntity.getClass()); allFieldNames.forEach(System.out::println); > >