Justin Smith
Justin Smith

Reputation: 81

Generic class method calls

I apologize in advanced for my lack of knowledge in generics... I am trying to understand how generics work and I am not sure what it is but I am missing a key part that is eluding me so hopefully someone can clarify a little more and get me over this hump.

BaseDtoUtil.mapToDto(map, OcrImageDocDto.class); //OcrImageDocDto extends DtoUtils

//This method is in class BaseDtoUtil
public static <T> List<T> mapToDto(Map<String, Object> map, Class<? extends DtoUtils> klass) throws SparkSQLException{
      T obj = (T)klass.newInstance();
      //return a list of these
}

So I guess there are two questions I have:

  1. First is why does it complain when I pass in OcrImageDocDto.class when the variable defined for the method call is any class? (I originally had it as (Class<?>) Doesn't that mean any class value? Obviously I am wrong but not sure what it means then.
  2. Second question is if I send in a class value am I actually able to get that instance and return a type value back? <T> List<T>? If I am not mistaken I believe that the generic variables <T> List<T> is used for instantiations of the object. But what do they do if it is a static method?

I am a bit lost and maybe the way I understand generics is wrong... So if someone can clear these two up I think it will help a lot!

Upvotes: 0

Views: 206

Answers (1)

Andy Turner
Andy Turner

Reputation: 140309

Question 1:

public static <T> List<T> mapToDto(
    Map<String, Object> map,
    Class<? extends DtoUtils> klass) throws SparkSQLException{
  T obj = (T)klass.newInstance();
  ...

You don't know that klass.newInstance() can be cast to a T - all you know is that it is an instance of DtoUtils (or a subclass).

As such, you can either change to use:

DtoUtils obj = klass.newInstance();

or constrain T to extend DtoUtils:

public static <T extends DtoUtils> List<T> mapToDto(
    Map<String, Object> map,
    Class<? extends T> klass) throws SparkSQLException{
  T obj = klass.newInstance();
  ...

Question 2:

Yes, because you have an actual instance of the class. You would not be able to create an instance without that (or some other object which can provide instances of T), because of type erasure.

This would not work:

public static <T extends DtoUtils> List<T> mapToDto(
    Map<String, Object> map) throws SparkSQLException{
  T obj = new T();  // Compiler error.

Something like the following works just fine:

T obj = klass.newInstance();
List<T> list = new ArrayList<>();
list.add(obj);
return list;

Upvotes: 2

Related Questions