0

I have a class called Material and some subclasses of it: Book, Audio, magazine... I also have an ArrayList<Material> arrayOfMaterials

I am trying to implement a search method: I want to give a string to this method as a parameter and it should call all the getters() in every object inside the array, plus the toString functions and compare the results to the input parameter.

I have read about Reflection in java, but if I got it right, that will give me the names of the fields or methods of a class, but won't give me the values of those fields in objects or the results of calling its getters().

I need to loop through ALL getters, or through all fields (I shouldn't access fields from outside, but it'd work), and not all subclasses of Materialhave the same number of fields.

Is there any way to do this? I have no code to paste because, as far as I know, there is no way to do this.

8
  • Reflection will give you values: stackoverflow.com/questions/13400075/… Commented Jun 21, 2016 at 12:46
  • Can't you write the method get for the class Material? so all subclasses can inherit it. Commented Jun 21, 2016 at 12:46
  • @Niles Does It make sense that a subclass inherits a getter for a field it doesn't have? Anyway, if I get to loop, I don't think the number of cycles will be a big deal. Thank you! Commented Jun 21, 2016 at 12:50
  • @DavidVV if your superclass have a field also all subclasses have that field, at least you have to be careful to don't override it. You can of course insert the get into your loop. Commented Jun 21, 2016 at 12:54
  • 1
    As far as I understand you are doing some kind of search based on the string parameter you pass. You can create an abstract method in Material like abstract boolean contains(String property) and then have each of your subclass implement it. Reflection API is not there to replace OOP principles. Commented Jun 21, 2016 at 13:03

1 Answer 1

2

The following example retrieves the field names of the concrete class (declaredField = fields declared by the class, (public)field = public fields declared by the class and it's super classes), derives a name of a corresponding getter from it (i.e. private String example -> getExample), searches for the method with the same name and invokes it on the instance m of Material

Material m = ...;
Stream.of(Material.class.getDeclaredFields())
      .map(field -> "get" + ucFirst(field.getName()))
      .map(getterName -> Material.class.getMethod(getterName))
      .map(getterMethod -> getterMethod.invoke(m))
      .forEach(fieldValue -> {
            //do something
      });

...
private String ucFirst(String input) {
    if(input.length() <= 1){
        return input.toUpperCase();
    }
    return input.substring(0, 1).toUpperCase() + input.substring(1);
}

(I removed the exception handling for better readability)

This is just one way to do it, there are many others. The same way you could access the toString method:

String toString = (String)Material.class.getMethod("toString").invoke(m);

Or you could get all the getter you want:

Stream.of(Material.class.getMethods())
      .filter(method -> method.getName().startsWith("get"))
      .map(getterMethod -> getterMethod.invoke(m))
      .forEach(fieldValue -> {
            //do something
      });

Note that getMethods will retrieve only public methods, but from all the super classes as well, while getDeclaredMethods will retrieve only method from the current classes. This may be important to know when dealing with the subclasses.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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.