2
  • edit - Here I gave a specific obj. as an example but I'm asking for any obj. I am given *

I'm looking for a way to get all public attributes in the class and all subclasses of an object (name of the attribute and its value). Let say we have a People object:

i
mport java.util.ArrayList;
 public class People {
 public ArrayList<Person> ppl= new ArrayList<Person>();
 int count=2;
 public People() {
 ppl.add(new Person(55, "Daddy", "Long Legs"));
 ppl.add(new Person(20, "Jhon", "Snow"));
 }
 public class Person{
 public int age;
 public Name name;
 public Person(int age, String first, String last){
 this.name = new Name(first, last);
 this.age = age;
 }
 public class Name{
 String first;
 String last;
 public Name(String first, String last) {
 this.first = first;
 this.last = last;
 }
 }
 }
 }

I saw a reference here (I can't comment on there bc I don't have enough points): Java reflection get sub class variable values / get object instance from member field

and tried to implement it also but then my output is

ppl [People$Person@4aa298b7, People$Person@7d4991ad]

whereas I need it needs to go into each Person and extract its variables(and their values). I searched for a information that could help me but I couldn't find anything..any advice?

asked Feb 13, 2018 at 10:52
3
  • there is no inheritance relation here. there are two inner classes . Commented Feb 13, 2018 at 11:00
  • looking at the answers, there seems to be confusion as to why reflection is needed. Commented Feb 13, 2018 at 11:06
  • So reflection is only for one inner class? (that means that it suits only for object which maximum contain another one object with just primitive attributes?) Commented Feb 13, 2018 at 21:47

5 Answers 5

1
public People() {
 ppl.add(new Person(55, "Daddy", "Long Legs"));
 ppl.add(new Person(20, "Jhon", "Snow"));
 for (Person person : ppl) {
 System.out.println(person.name.last);
 System.out.println(person.name.first);
 System.out.println(person.age);
 }
 System.out.println("Size of list: " + ppl.size());
 }

Example without toString() method.

answered Feb 13, 2018 at 11:02
1
  • thanks but People was just an example..I need to list all the variable names and values for any kind of objects :| Commented Feb 13, 2018 at 21:48
1

I Agree with @Jordi Castilla , you need to override toString method properly to get correct output.

For Example :

import java.util.ArrayList;
class People {
 public ArrayList<Person> ppl= new ArrayList<Person>();
 int count=2;
 public People() {
 ppl.add(new Person(55, "Daddy", "Long Legs"));
 ppl.add(new Person(20, "Jhon", "Snow"));
 }
 @Override
 public String toString() {
 return "{ Count: "+this.count + " , People:" + this.ppl+" }";
 }
 public class Person{
 public int age;
 public Name name;
 public Person(int age, String first, String last){
 this.name = new Name(first, last);
 this.age = age;
 }
 @Override
 public String toString() {
 return "{ Name: "+this.name + " , Age:" + this.age+" }";
 }
 public class Name{
 String first;
 String last;
 public Name(String first, String last) {
 this.first = first;
 this.last = last;
 }
 @Override
 public String toString() {
 return "{ FirstName: "+this.first + ", LastName: " + this.last+ " }";
 }
 }
 }
 public static void main(String[] args) {
 People ppl = new People();
 System.out.println("OUTPUT => "+ ppl.toString());
 }
}
//Output
OUTPUT => { 
 Count: 2 , 
 People:[
 { Name: { FirstName: Daddy, LastName: Long Legs } , Age:55 }, 
 { Name: { FirstName: Jhon, LastName: Snow } , Age:20 }
 ] 
}
answered Feb 13, 2018 at 12:40
3
  • notice that your code just prints the values of the variable and not their names...(for example, the original name of the variable is "age" but it isn't printed in your output) Commented Feb 14, 2018 at 12:55
  • I think printing "age" instead of "Age" is just matter of changing toString method implementation for Person object. If you have any other purpose for it then please explain it. Commented Feb 14, 2018 at 13:06
  • of course. my intention was that your method doesn't actually get the variable name as it was defined...oh wait- you just printed the values here..I am attaching my solution so far. Maybe you'll have an idea how to print the internal list variable names Commented Feb 14, 2018 at 13:28
1

I believe the closest you can get is related to this question java: get all variable names in a class .

Using Field[] fields = YourClassName.class.getFields(); returns all class fields as java.lang.reflect.Field.

You can check if field is public using Field.getModifiers() and Modifier.isPublic(Modifier).

You can get the field value using Object Field.get().

Hope that helps.

answered Feb 13, 2018 at 11:11
0
1

code a toString() method

What you are getting People$Person@4aa298b7 is the Object.toString representation....

getClass().getName() + '@' + Integer.toHexString(hashCode())

IMHO You need to override the toString() method in both classes: Person and Name.

For example:

public class Name{
 String first;
 String last;
 public Name(String first, String last) {
 this.first = first;
 this.last = last;
 }
 @Override
 public String toString() {
 return this.first + " " + this.last;
 }
} 

get fields and values based on known Person class

If this does not fit, you can get fields names and values using reflection like this:

public static void main(String[] args) throws IllegalAccessException
{
 People pe = new People();
 Field[] allFields = People.Person.class.getDeclaredFields();
 for (Field field : allFields)
 {
 for (People.Person p : pe.ppl)
 System.out.println("Name: " + field.getName() + ". Value: " + field.get(p));
 }
}

OUTPUT:

Name: age. Value: 55
Name: age. Value: 20
Name: name. Value: Daddy Long Legs
Name: name. Value: Jhon Snow
Name: this0ドル. Value: People@677327b6
Name: this0ドル. Value: People@677327b6

NOTE: if you don't want this 2 final values representing the People with ugly results you can:

  • Split Person and Name and make them 2 independent classes
  • Make a toString() method in People class

dynamically get fields from inner classes

If you want to dynamically get fields from inner classes:

public static void main(String[] args) throws IllegalAccessException
{
 Class[] allClasses = People.class.getClasses();
 for (Class clazz : allClasses) {
 Field[] allFields = clazz.getFields();
 for (Field field : allFields) {
 String className = clazz.getName();
 String fieldName = field.getName();
 System.out.println("Class name: " + className + " - Field name: " + fieldName + ".");
 }
 }
}

OUTPUT:

Class name: People$Name - Field name: first.
Class name: People$Name - Field name: last.
Class name: People$Person - Field name: age.
Class name: People$Person - Field name: name.

But not sure how you can get values from inside the ArrayList<Person>....

answered Feb 13, 2018 at 10:58
6
  • this is not what OP was asking for Commented Feb 13, 2018 at 11:00
  • @SharonBenAsher OP is searching for reflection, but reflection is explained in linked question... so IMHO I think it is what OP needs.... Maybe my assumption is wrong... lets OP tell us :) Commented Feb 13, 2018 at 11:03
  • @SharonBenAsher maybe what you think OP needs is the update in my answer? Commented Feb 13, 2018 at 13:21
  • 1
    what I think OP meant was to dynamically get field values from all inner classes of any given class, not to have hard coded People.Person. For example, in the question, there is People.Person.Name inner class that you did not introspect Commented Feb 13, 2018 at 13:45
  • you'rw right about the toString method but here is only an example..I can't know if there's a toString method in the given object (or can I?). I gave here an example with People and Person object but I don't really know the object type. It should be general for any object I get...In you dynamically solution you also didn't manage to get the variables value. Do you have any thought why get method doesn't return it? (and thanks a lot!) Commented Feb 13, 2018 at 21:40
1

here is a recursive method I did (after I added a toString method to Name class). Here it is. However, it is still doesn't prints the variable names inside the ppl list:

private static String getAllFields(Object obj){
 Class<?> objClass = obj.getClass();
 StringBuilder res = new StringBuilder();
 Field[] fields = objClass.getFields();
 res.append(objClass+"\n");
 for(Field field : fields) {
 Class<?> type = field.getType();
 String name = field.getName();
 res.append(" name: "+name+ " ");
 try {
 Object value = field.get(obj);
 res.append("value: "+value+ "\n");
 if (!type.isPrimitive() && !name.contains("java.lang"))
 {
 res.append(getAllFields(value));
 }
 } catch (IllegalArgumentException | IllegalAccessException e) {
 e.printStackTrace();
 }
 }
 return res.toString();
}

here is the output: class People name: ppl value: [Daddy Long Legs 55 , Jhon Snow 20 ] class java.util.ArrayList name: count value: 2

notice that there isn't the Person class name there in the output or the names of the variable names of the variables there. I don't really understand why

answered Feb 14, 2018 at 13:30

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.