Как согласовать типы между `hakyll` и` hakyll-images`

У вас есть скрытая циклическая зависимость, которая запутывает JVM. Давайте посмотрим на ваш код.

class Recreate {

  private static ArrayList FEATURES = new ArrayList();

  public enum Car {
    TESLA(FEATURES);
    Car(ArrayList l) { }
  }

  public static class Garage {
    final Car car;

    Garage(Car car) {
      this.car = car;
    }
  }

  public static Garage ONE_CAR_GARAGE = new Garage(Car.TESLA);
}

Нам также понадобится несколько фрагментов с страницы из JLS .

Тип класса или интерфейса T будет инициализирован непосредственно перед первым вхождением любого из следующих:

  • Используется статическое поле, объявленное T, и поле не является постоянной переменной (§ 4.12.4).
blockquote>

& nbsp;

12.4.2. Подробную процедуру инициализации

...

  1. Затем выполните либо инициализаторы переменных класса, и статические инициализаторы класса, либо инициализаторы полей интерфейса, в текстовом порядке, как если бы они были одним блоком.
blockquote>

Таким образом, наши статические данные инициализируются, когда они впервые упоминаются. Теперь ваш Car.TESLA неявно static final, но он не является константой, согласно определению .

Постоянная переменная является конечной переменной примитивного типа или введите String, которая инициализируется константным выражением

blockquote>

. Итак, для наших целей здесь есть три статических непостоянных переменных: FEATURES, TESLA и ONE_CAR_GARAGE .

Теперь в вашем рабочем случае вы ссылаетесь на Recreate.ONE_CAR_GARAGE. Это ссылка на статическое поле в Recreate, поэтому FEATURES, а затем ONE_CAR_GARAGE инициализируются. Затем во время инициализация ONE_CAR_GARAGE, TESLA инициализируется, так как ссылается на ее класс перечисления. Все хорошо.

Однако, если мы слишком рано ссылаемся на перечисление, мы делаем вещи в неправильном порядке. Recreate.Car.TESLA получает ссылку, поэтому TESLA получает инициализацию. TESLA ссылается на FEATURES, поэтому Recreate должен быть инициализирован. Это заставляет FEATURES и ONE_CAR_GARAGE инициализироваться до того, как TESLA закончит существующие.

Это скрытая зависимость, которая вас трогает. Recreate.Car зависит от Recreate, который зависит от Recreate.Car. Перемещение поля ONE_CAR_GARAGE в класс Garage приведет к тому, что он не будет инициализирован с помощью FEATURES и устранит вашу проблему.

0
задан mherzl 20 January 2019 в 06:48
поделиться

1 ответ

Это поведение является ошибкой, попавшей в выпуск hakyll-images 0.3.1. Это было впоследствии исправлено в hakyll-изображениях 0.4 и выше. Просто обновитесь до последней версии, чтобы избавиться от этой проблемы.

Это был грубый недосмотр, и были добавлены тесты, чтобы это больше не повторилось.

Если вы хотите реализовать экземпляры самостоятельно, вы можете взглянуть на то, как это делается здесь .

0
ответ дан Laurent René de Cotret 20 January 2019 в 06:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: