Julia
Julia

Reputation: 1237

How do I get contents of collections with generics?

I get object from hibernate query. Then i have list of fields, whose getters i must invoke on this object. So after i invoke these getters (not depending on me, so i have no idea what they return), i put these objects in one array Object[]. Now i am iterating through these objects, some of which are again collections containing other objects. So i check if objects is collection like this

private static boolean isCollection(Object obj){
    Class clazz = obj.getClass();
    return Collection.class.isAssignableFrom(clazz) ||     
     Map.class.isAssignableFrom(clazz);
}

now i need to do somethinhg like:

 if(isCollection(object)){
       get subobjects from this collection();
       getDeclaredMethods of this type of object();
       do something with everyObject();
}

Appreciate all the help on how to make this generic. Oh and yes, this method is checking for a Map, but in general in my case, map can not be returned, only sets and lists.

Thank you

EDIT: I will add exact code here for reference in case it is not clear

Object[] objectRow = parseObject(hibernateObject);
for(Object field: objectRow){
      get subobjects from this collection();
   getDeclaredMethods of this type of object();
   do something with everyObject();

}

public Object[] parseObject(Object mainObject) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException{
    rowToReturn = new Object[fieldObjects.size()];

    Method[] allMethods = mainObject.getClass().getMethods();
    Method[] getters = findGetters(allMethods);
    cutGetters(getters); // builds map so that we match getters with fields



    for(FieldObject field: fieldObjects){
        if(getterNameMethodMap.containsKey(field.getFinalFieldName())){
            Method methodToInvoke = getterNameMethodMap.get(field.getFinalFieldName());

            Object invokedObject = methodToInvoke.invoke(mainObject, (Object) null);
            rowToReturn[field.getOrder()] = invokedObject; // put what ever it is that we got, into the final array
        }
    }

    return rowToReturn;
}


private void cutGetters(Method[] getters){
    getterNameMethodMap = new HashMap<String, Method>();
    for(Method getter:getters){
        String stringToGet = getter.getName().substring(4,getter.getName().length());
        getterNameMethodMap.put(stringToGet, getter);
    }

Upvotes: 2

Views: 303

Answers (2)

Matthew Leidholm
Matthew Leidholm

Reputation: 4469

Because Generics are erased at compile-time, by definition they cannot be used to determine the type of an object if you cannot know that type at compile-time. Unfortunately, without changing whatever code is giving you the array of objects that may or may not be Collections, the only way to determine their type is to manually check the returned Objects' types like you are already doing.

Further info: http://docs.oracle.com/javase/tutorial/java/generics/erasure.html

P.S.: that's not to say there isn't a more efficient way of doing what you're doing. By casting those objects that you have already determined are Collections, you may be able to "do something" without resorting to reflection to get the declared methods. The actual determination, however, cannot be shortcut with Generics.

Upvotes: 0

Bernd Elkemann
Bernd Elkemann

Reputation: 23550

This is exactly the code Generics try to prevent. Generics try to take the burden of scattering if object.type == class throughout your code from you. Have a look here, this is only an introduction:

http://en.wikipedia.org/wiki/Generics_in_Java

Since you have a collection of collections of objects, you would do something like this:

List<List<? extends Shape>>

This is to declare a list of lists and also to be as precise as possible which kind of object those inner lists contain (I chose Shape just as an example, no idea which kind of objects you want to deal with). You can find the explanation for that exact code here:

http://download.oracle.com/javase/tutorial/extra/generics/methods.html

Upvotes: 2

Related Questions