Как проверить с помощью типа отражения универсального класса

#java #reflection

#java #отражение

Вопрос:

У меня есть интерфейс для реализации структуры данных стека:

 public interface Stack<T> {
    void push(T element);
    //other methods
}
  

И одной или нескольких реализаций, в которых это реализовано.

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

 class StackImpl<T> implement Stack<T>{
//...
}
  

Для теста вызова я хочу написать это:

 Tester.<Integer>test(new StackImpl<Integer>());
  

И в тестере это:

 public static <T> void test(Object any) {
        if (any instanceof Stack) {
            testQueue((Stack<T>) any);
        }
    }

    private static<T> void testStack(Stack<T> stack) {
        new TestStack<>(stack).invoke();
    }
  

И тестовый стек:

 public class TestStack<T> implements Test {

    private Stack<T> stack;

    TestStack(Stack<T> stack) {
        this.stack = stack;
    }

    @Override
    public void invoke() {
        //and here need help!
    }
}
  

И в методе invoke() я хочу получить исходный универсальный тип, в данном случае Integer.

Как получить необходимое значение для теста реализации?

Комментарии:

1. Это невозможно из-за удаления типа, это было бы возможно, если бы у вас был отдельный класс, такой как IntegerStack implements Stack<Integer>

Ответ №1:

Общий тип переменной стирается во время выполнения единственный способ, которым вы могли бы это сделать, — это самостоятельно сохранить тип, т. Е. Добавить метод в свой интерфейс стека для получения типа:

 public interface Stack<T> {
    ...
    Class<T> getType();
    ...
}
  

Затем в вашем impl добавьте тип в качестве аргумента конструктора:

 public class StackImpl<T> implements Stack<T> {
    private final Class<T> type;

    public StackImpl(Class<T> type) {
        this.type = type;
    }

    @Override
    public Class<T> getType() {
        return type;
    }
}
  

Итак, теперь у вас будет доступ к типу:

 public class TestStack<T> implements Test {
    private Stack<T> stack;

    TestStack(Stack<T> stack) {
        this.stack = stack;
    }

    public void invoke() {
        System.out.println(stack.getType());
    }
}
  

И:

 Tester.<Integer>test(new StackImpl<Integer>(Integer.class));
  

Это не идеально, но это единственный подход, который сработает!