Просто начните изучать и знать о отражении Java, буду признателен за любую помощь по этой проблеме.

Я пытаюсь написать метод, и он выглядит так:

    private <T> void myMethod (List<T> testSub) {
        testSub.forEach(s -> assertEquals(s.getSource(), "TEST"));
    }

Но он показывает ошибку, потому что java не знает, имеет ли класс testSub этот метод getSource (), и хочет, чтобы я привел s.getSource () к известному классу.

Я хочу каким-то образом сообщить java, что элементы в классе testSub имеют этот метод getSource (), и его можно вызывать и безопасно вызывать.

Заранее спасибо!

----------------------------Обновить--------------------- - Выберите вариант использования:

    private <T> void myMethod (List<T> testSub, Class<T> clazz) {

        testSub.forEach(s -> assertEquals(clazz.getMethod("getSource").invok(s), "TEST"));
    }

Придется ловить исключения, но работает.

0
DawnZHANG 9 Янв 2018 в 21:25

2 ответа

Лучший ответ

Есть два способа вызвать метод getSource().

Одним из них является обычное выражение вызова метода , например object.getSource(). Это возможно только в том случае, если компилятор знает, что object принадлежит к классу, имеющему метод getSource().

В вашем случае компилятор знает только s как общий тип T, который не ограничен, поэтому может быть любым классом, даже Object, и компилятор не может подтвердить, что есть метод getSource ().

Если у вас нет общего родительского класса или интерфейса для элементов списка, имеющих метод getSource(), вы можете использовать комбинации instanceof / cast. Это некрасиво, но может сработать для вас, если вы действительно знаете возможные классы элементов.

for (T s : testSub) {
    if (s instanceof Class1) {
        assertEquals(((Class1) s).getSource(), "TEST"));
    } else if (s instanceof Class2) {
        assertEquals(((Class2) s).getSource(), "TEST"));
    } else {
        throw new IllegalArgumentException();
    }
}

Другой способ - использовать отражение. Вы можете найти Method m = s.getClass.getMethod("getSource") и, если не ноль, сделать m.invoke(s). Но это даже уродливее, чем решение instanceof / cast, и, конечно же, намного медленнее.

0
Ralf Kleberhoff 9 Янв 2018 в 19:31

Добавьте привязку к определению переменной вашего типа:

private <T extends HasSource> void myMethod (List<T> testSub) {

Где HasSource определяет метод getSource():

public interface HasSource {
    String getSource()
}

Компилятор будет знать, что T на самом деле является подклассом HasSource и, следовательно, у него есть метод getSource().

Конечно, чтобы использовать это решение, вам нужно будет заставить все классы, которые вы хотите использовать в качестве элементов testSub, реализовать этот интерфейс HasSource.

1
Roman Puchkovskiy 9 Янв 2018 в 18:38