Получить универсальный тип класса во время выполнения не работает - PullRequest
0 голосов
/ 24 июня 2018

У меня есть два класса и один интерфейс

public class ExcelReader<T> extends Reader<T> implements RowColumnReader<T> {

    // private final TypeToken<T> typeToken = new TypeToken<T>(getClass()) {};
    // private final Type type = typeToken.getType(); 
    /* public Type getType() {
        return type;
        }*/
    // Useing Guava getting System.out.println(reader.getType()) T as ouput

        @Override
        public List<T> readFile(String file) {
          //my code
        }
    }
public abstract class Reader<T> {
    protected Class<T> clazz;

    /*public Reader() {
        clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }*/
    // Constructor is commented beacuse getting Exception java.lang.ClassCastException: sun.reflect.generics.reflectiveObjects.TypeVariableImpl cannot be cast to java.lang.Class
}

public interface RowColumnReader<T> extends HeaderFields<T>{

    public List<T> readFile(String file);
}

public interface HeaderFields<T> {

    default List<String> getHeader(Class<T> clazz) throws HeaderNotDefiendException {
        //my code
        return headerList;
    }

}

Я перепробовал все возможные способы получения класса универсального типа. Я следовал Получить универсальный тип класса во время выполнения и даже попробовал все решения, приведенные на этой странице. Но все равно не получаю никакой удачи.

Даже с Гаувой

https://stackoverflow.com/a/19775924/2290078 получение результата getType() - это не фактический универсальный класс

Мой тестовый код

Reader<Test> reader = new ExcelReader<>();
//System.out.println(reader.getType());  ---> output is T 
List<Test> list = reader.readFile("Sample.xlsx");
System.out.println(list);

Ответы [ 2 ]

0 голосов
/ 24 июня 2018

Я перепробовал все возможные способы получения класса универсального типа.

Таким образом, вы нашли здесь не работает для получения универсального:

public Reader() {
    clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}

, потому что он статически параметризованныйтип, определенный в непосредственном суперклассе Reader, который в этом случае равен Object.

Перемещение этого кода в конструкторе подкласса также не будет работать:

public ExcelReader() {
    clazz = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}

, поскольку он извлекает статически параметризованный тип, определенный в классе Reader, то естьT.Поскольку T не имеет никаких границ, вы все равно получите класс Object в качестве возвращаемого класса.

Какое решение применить в вашем случае?

Дженерики стираются после компиляции.Таким образом, чтобы знать, что параметризованная информация о типе, используемая во время выполнения, равна Test здесь:

Reader<Test> reader = new ExcelReader<>();

, вам необходимо явно «передать» Class, представляющий универсальный код в вашем фактическом коде.
ToДля этого добавьте в конструктор параметр Class, представляющий универсальный тип, и сохраните его в поле.Теперь у вас есть способ ссылаться на тип во время выполнения.

public class ExcelReader<T> extends Reader<T> implements RowColumnReader<T> {

   private Class<T> genericType;

   public ExcelReader(Class<T> genericType){
       this.genericType = genericType;
   }
   /*...*/
}

Теперь вы можете создать экземпляр ExcelReader следующим образом:

ExcelReader<Test> excelReader = new ExcelReader<>(Test.class);
0 голосов
/ 24 июня 2018

Вопрос не только в том, «какой API мне следует использовать для получения универсального типа во время выполнения?».Это зависит от того, что вы хотите сделать с универсальным типом (T).

Дженерики - это скорее функция проверки во время компиляции и могут накладывать некоторые полезные ограничения при использовании T extends и T super.Вот и все.Это может быть полезно Разница междуа такжев Java

Если вы хотите знать тип T во время выполнения и выполнять реализацию условия, используя что-то вроде switch, тогда класс, который вы объявляете универсальным, на самом деле не является универсальным классом по определению, так какреализация отличается для другого типа и, следовательно, не поддерживается изящно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...