Java generic method: create entity of necessary type

Viewed 210

There are two entities classes:

public class Base {
    private String provider;
}

public class SuperClass extends Base {
    private String trunk;
}

and main class:

public class Test {
    public static <T extends Base> List<T> getDetailedReport(Class<T> clazz, String providerName) {
        List<T> list = new ArrayList<>();
        T entity = new Base(); // this is wrong, of course.
        return list;
    }

    public static void main(String[] args) {
        Base base = new Base();
        ​SuperClass superClass = new SuperClass();
        List<Base> baseList = getDetailedReport(Base.class, "Telia");
        List<SuperClass> superClassList = getDetailedReport(SuperClass.class, "Globalcom");
    ​}
​}

I'm trying to create generic method getDetailedReport which returns list of entities. Type of entity is passed through clazz variable. My question is: How to create entity of necessary type?

1 Answers

Reflection API is your friend here. To use the following implementation, you need to make sure the following conditions:

  1. The Base and all the derived objects have no-args constructor (i.e. new Base() or new SuperClass()).
  2. You need deal with 4 thrown exceptions: NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException.

Minimal sample (using Lombok):

@Data
@NoArgsConstructor
public static class Base {
    private String provider;
}
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@NoArgsConstructor
public static class SuperClass extends Base {
    private String trunk;
}
@SneakyThrows
static <T extends Base> List<T> getDetailedReport(Class<T> clazz, String provider) {
    List<T> list = new ArrayList<>();
    T entity = clazz.getDeclaredConstructor().newInstance();
    entity.setProvider(provider);
    list.add(entity);
    return list;
}
List<Base> baseList = getDetailedReport(Base.class, "Telia");
List<SuperClass> superClassList = getDetailedReport(SuperClass.class, "Globalcom");

System.out.println(baseList);
// [Main.Base(provider=Telia)]

System.out.println(superClassList); 
// [Main.SuperClass(super=Main.Base(provider=Globalcom), trunk=null)]
  • I made the data classes static in order to use in the class with the main method comfortably
  • I used @SneakyThrows for safe of answer clarity - you, however, need to handle these exceptions
  • Note that @NoArgsConstructor satisfies clazz.getDeclaredConstructor().newInstance().
  • You might need to modify the implementation as you need (I let the method pass String provider into a newly created instance through the Reflection API and returned it in the List as a demonstration).
Related