Java ограничивает Class<> определенными типами

Я очень новичок в дженериках Java и типе Класс<> clazz, у меня есть интерфейс

public interface MyInterface {
void doSomething(String arg1);
}

который реализуется несколькими классами

class MyInterfaceImplFirst implements MyInterface {
  private arg;
  public MyInterfaceImplFirst(String arg) {
    this.arg = arg;
  }

  @Override
  void doSomething(String arg1) {
    //...
  }
}

class MyInterfaceImplSecond implements MyInterface {
  private arg;
  public MyInterfaceImplSecond(String arg) {
    this.arg = arg;
  }

  @Override
  void doSomething(String arg1) {
    //...
  }
}

У меня есть класс, который принимает Class<MyInterface> type

public class Dummy {
  public void load(Class<MyInterface> clazz) {
    //...
  }

  public static void main(String[] args) {
    Dummy dummy = new Dummy();
    //The below does not compile
    dummy.load(MyInterfaceImplFirst.class);
  }
}

Если я изменю метод загрузки на общественная пустая нагрузка (класс clazz), он будет работать нормально, может ли кто-нибудь сказать мне, как ограничить аргументы для метода загрузки только подтипами (импл) Мой интерфейс?

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема заключается в PECS (Producer-Extends, Consumer-Super). Учитывая List<Number>, вы, конечно, можете вызвать .add(someDouble). Следовательно, List<Integer>не можешь передается, когда требуется List<Number>. Эта концепция «записи» просто не применяется к Class<X>, но java не «знает» этого и, следовательно, не позволит вам передать Class<SomeImpl>, когда требуется Class<TheInterface>.

PECS — это неправильное название; он написан с точки зрения универсального типа (так, список, класс и т. д.). Если класс только производит материал и не будет потреблять ничего общего типа, как в данном случае, PECS указывает, что вы должны использовать extends.

Следовательно, public void load<Class<? extends MyInterface> clazz) — это то, что вам нужно.

Несколько заметок:

  • Дженерики служат для связи вещей. Если вы объявляете общую переменную и используете ее в 0 или 1 местах, то вы испортите или, взламывая систему типов java (есть законные случаи, когда это хорошая идея, но довольно редко). Учитывая, что вам нигде не нужна эта буква T, вы все испортите. Просто используйте ? вместо этого.
  • Смешивать дженерики и Class обычно плохо. Есть вещи, которые может представлять Class, например, int (Class<?> c = int.class; является допустимым java), которые не могут быть представлены дженериками (List<int> не является допустимым java), и наоборот, дженерики могут представлять этот класс. У вас не может быть экземпляра java.lang.Class, представляющего List<String> (только List — необработанный тип). Class<List<String>> не вещь; List<String>.class не работает. List<List<String>> работает.
  • Что бы ни заставило вас думать: я знаю! Сделаю интерфейс, использую дженерики и сделаю Class<? extends MyInterface> - скорее всего это была ошибка. Вы не объяснили, почему вы решили, что вам это нужно. Скорее всего, правильный ответ — фабрика. Фабрика — это, по сути, абстракция для конструкторов.

Другие вопросы по теме