Java GenericClass <? расширяет интерфейс> как параметр - PullRequest
3 голосов
/ 15 января 2020
public interface A {}
public interface B {}
public class Test implements A{}
public class Test2 {}

Я создал метод, который проверяет, реализует ли класс интерфейс. Я хочу, чтобы мой метод принимал только общие c интерфейсы, а не все объекты классов.

метод

    public static boolean containsInterface(Class clazz, Class intf)
    {
    try
    {
        Validate.isTrue(intf.isInterface());
        if(clazz.isInterface())
            return JavaUtil.isClassExtending(intf, clazz);
        for(Class c : ClassUtils.getAllInterfaces(clazz))
        {
            if(JavaUtil.isClassExtending(intf, c))
                return true;
        }
    }
    catch(Throwable t)
    {
        t.printStackTrace();
    }
    return false;
}

Поскольку Test.class & Test2.class не являются интерфейсами для параметра 2d, я хочу, чтобы он имел ошибку компиляции, поскольку параметр 2d должен быть интерфейсом класса

containsInterface(Test.class, Test.class);
containsInterface(Test.class, Test2.class);

допустимое использование моего метода

containsInterface(Test2.class, A.class);
containsInterface(Test.class, B.class);

то, что я пытался

public static boolean containsInterface(Class clazz, Class<? extends Interface> intf)

В настоящее время я проверяю, является ли класс в параметре интерфейсом, затем выдает исключение. Я бы предпочел заставить людей не иметь возможности вызывать метод для начала, если это не интерфейс

Мне известны аннотации и объекты Enum, доступные для использования в качестве сигнатуры класса, чтобы убедиться, что люди используют параметры правильные, но я не могу найти тот, который подходит для самого интерфейса.

Мне сказали, что дженерики не поддерживают интерфейсы или тип абстрактных классов, это так даже в jre 9-13 +

Ответы [ 2 ]

1 голос
/ 17 апреля 2020

Вы не можете заставить аргумент быть ЛЮБОЙ реализацией интерфейса, используя систему управления типами. То же самое применимо, если вы хотите, например, форсировать только Class<?> с модификатором abstract. Я не уверен, действительно ли это необходимо, так как простой тип isInterface assert равен

  1. Straigthforward
  2. Clean
  3. Прочный
  4. Легко понять
  5. Склонность к ошибкам
  6. Тестируемый

Инженеры JDK также не заботятся об этом. В качестве идеального примера такого механизма может быть использован (но его нет) JDK Dynami c Proxy creation. Вы можете создать только создать прокси интерфейса (или набора), но не класса.

Не думаю, что стоит написать собственные препроцессоры. Более того, он не будет универсальным - как вы предполагаете, тип времени выполнения должен быть известен во время компиляции - как насчет динамически загружаемых классов et c?

0 голосов
/ 17 апреля 2020

Интерфейсы в java не имеют суперкласса, который вы можете использовать в режиме generi c.

Если вы попытаетесь получить суперкласс интерфейса с отражением, то вы получите ноль.

public static void main (String [] args) {
        System.out.println(A.class.getSuperclass());
}

interface A {}

Выход:

null
...