Java обобщений и рефлексии: загрузка классов - PullRequest
5 голосов
/ 16 января 2020

Мне дали несколько уроков, которые мне неизвестны. Некоторые из них показаны в качестве примера:

class Paper {}

class Bakery {}

class Cake extends Bakery {}

class ReflexiveBaker {

  /**
   * Create bakery of the provided class.
   * 
   * @param order class of bakery to create
   * @return bakery object
   */
  public Object bake(Class order) {
    // Add implementation here
  }

}

Задача состоит в том, чтобы при необходимости перепроектировать типы сигнатур методов и добавить реализацию. Метод bake должен соответствовать следующему:

  • Создание объектов класса Bakery или любого его подкласса в соответствии с аргументом класса
  • Отметить ошибку времени компиляции, если аргумент порядка не Bakery или любой его подкласс (например, если это Бумага или Объект)

Что бы я ни пытался, я получаю сообщение об ошибке: Main. java :: error: несовместимые типы: Объект не может быть преобразован Cake Cake cake = baker.bake (Cake.class);

Лучшее, что я придумал, это:

publi c Объект Bake (порядок классов) выдает Exception { return order.getDeclaredConstructor (). newInstance ();

Я знаю, что это неправильно, но я полностью застрял здесь. Может кто-нибудь объяснить, что происходит?

1 Ответ

6 голосов
/ 16 января 2020

Ваш метод возвращает тип java.lang.Object, и компилятор не может подтвердить, что возвращаемое значение имеет тип Cake, если вы не убедите компилятор, добавив явное непроверенное приведение типа этого.

Cake cake = (Cake) ReflexiveBaker.bake(Cake.class);

Этот непроверенный актерский состав подвержен ошибкам и неудобен. Скажем, у вас есть другой класс с именем Bread, который является подтипом Bakery, и вы передаете этому экземпляру класса ожидающий Cake в качестве возвращаемого типа. Вышеприведенный оператор все еще компилируется, но выдает ClassCastException во время выполнения.

Гораздо лучший подход заключается в генерировании метода с использованием параметра ограниченного типа таким образом, чтобы он принимал только подтипы Bakery и возвращал тот же тип, что и параметр типа предоставленного объекта класса. Вот одна из таких попыток.

static class ReflexiveBaker {
    public static <T extends Bakery> T bake(Class<T> order) {
        try {
            return order.getDeclaredConstructor().newInstance();
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException
                    | InvocationTargetException e) {
            throw new AssertionError("Class could not be instantiated.", e);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...