Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem at JUnit test with generics

In my utility method:

public static <T> T getField(Object obj, Class c, String fieldName) {
    try {
        Field field = c.getDeclaredField(fieldName);
        field.setAccessible(true);
        return (T) field.get(obj);
    } catch (Exception e) {
        e.printStackTrace();
        fail();
        return null;
    }
}

The line

return (T) field.get(obj);

gives the warning "Type safety: Unchecked cast from Object to T"; but I cannot perform instanceof check against type parameter T, so what am I suppose to do here?


2 Answers

The annotation @SuppressWarnings will stop the compiler reporting this warning. I don't think there's any way you can get away from the compiler warning when using reflection like this. Something like the following:

Field field = c.getDeclaredField(fieldName);
field.setAccessible(true);

@SuppressWarnings(value="unchecked")
T t = (T) field.get(obj);

return t;
like image 168
Jeff Foster Avatar answered Sep 14 '25 12:09

Jeff Foster


You can easily solve this problem by adding an additional parameter to your method which will specify the type of the filed, the method will then look as follows:

  public static <T> T getField(Class<T> fieldType, Object obj, Class<?> c, 
    String fieldName) 
  {
     try {
         Field field = c.getDeclaredField(fieldName);
         field.setAccessible(true);
         Object value = field.get(obj);
         return fieldType.cast(value);
     } catch (Exception e) {
         e.printStackTrace();
         fail();
         return null;
     }
 }

And here's how you can use it: getField(String.class, new G(), G.class, "s") where G is defined as:

 public class G {
  String s = "abc";      
 }

A 2nd improvement is to eliminate the c parameter of getFiled(). c can be obtained inside the method by invoking obj.getClass(). The only caveat is that this will give you the dynamic type of the object so you mat want to loop over all of C's superclasses until you find the field you're looking for, or until you arrive at Object (You will also need to use c.getFields() and look for the field in the resulting array).

I think that these changes will make your method easier to use and less prone to errors so it's worth the effort.

like image 31
Itay Maman Avatar answered Sep 14 '25 14:09

Itay Maman