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.

Sean Bright
  • 118,630
  • 17
  • 138
  • 146
DavidVV
  • 225
  • 1
  • 4
  • 12
  • Reflection will give you values: http://stackoverflow.com/questions/13400075/reflection-generic-get-field-value – Adam Jun 21 '16 at 12:46
  • Can't you write the method get for the class Material? so all subclasses can inherit it. – Niles Jun 21 '16 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! – DavidVV Jun 21 '16 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. – Niles Jun 21 '16 at 12:54
  • @Niles but if I put the books specific fields or getters inside the superclass, all subclasses will inherit those fields o getters. I don't think I want that – DavidVV Jun 21 '16 at 12:56
  • @DavidVV if you have a different getter for each classe you can also use **istance of**, it is not so elegant but works... By the way... if you still have your problem explain it better, I will try to help you. – Niles Jun 21 '16 at 13:02
  • 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. – Jaroslaw Pawlak Jun 21 '16 at 13:03
  • @JaroslawPawlak that is actually a lot better and easier! :) – DavidVV Jun 21 '16 at 14:20

1 Answers1

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.

Gerald Mücke
  • 10,724
  • 2
  • 50
  • 67