#java #enums
#java #перечисления
Вопрос:
Я определил следующее перечисление в своем коде:
public enum Table {
BASE_PRICES("base_prices", Affinity.UPS,
Arrays.asList(
Field.BILLING_WEIGHT_LOWER_BOUND,
Field.BILLING_WEIGHT_UPPER_BOUND,
Field.BASE_PRICE,
Field.SERVICE_TYPE_ID,
Field.ZONE_ID
)),
COUNTRY_CODES("country_codes", Affinity.UPS,
Arrays.asList(Field.COUNTRY_CODE)),
SERVICE_TYPES("service_types", Affinity.UPS,
Arrays.asList(Field.SERVICE_TYPE)),
ZONE_DIVISION("zone_division", Affinity.UPS,
Arrays.asList(
Field.COUNTRY_CODE_ID,
Field.SERVICE_TYPE_ID,
Field.ZONE_ID,
Field.POST_CODE_LOWER_BOUND,
Field.POST_CODE_UPPER_BOUND)),
ZONES("zones", Affinity.UPS,
Arrays.asList(Field.ZONE_CODE));
// used to denote the affinity of a table for
// affinity specific DB cleanup and other stuff.
public enum Affinity {
UPS
}
private String name;
private Affinity affinity;
private List<Field> fields;
private Table(String name, Affinity affinity, List<Field> fields){
this.name = name;
this.affinity = affinity;
this.fields = fields;
System.out.println("ENUM CONSTRUCTOR (" name "):");
System.out.println(fields);
System.out.println();
}
public List<Field> getFields(){
return Collections.unmodifiableList(fields);
}
}
Когда я запускаю один тест JUnit с использованием перечисления, все в порядке. Однако, когда я запускаю весь набор тестов, тот же тест, который работал изолированно до сбоя с исключениями нулевого указателя, из-за неправильной инициализации перечисления, вывод println в конструкторе enum:
ENUM CONSTRUCTOR (base_prices):
[BILLING_WEIGHT_LOWER_BOUND, BILLING_WEIGHT_UPPER_BOUND, BASE_PRICE, null, null]
ENUM CONSTRUCTOR (country_codes):
[COUNTRY_CODE]
ENUM CONSTRUCTOR (service_types):
[null]
ENUM CONSTRUCTOR (zone_division):
[null, null, null, null, null]
ENUM CONSTRUCTOR (zones):
[null]
Большинство полей (поле также является перечислением) имеют значение null по какой-то причине, которую я не понимаю, но только в том случае, если я выполняю весь набор тестов.
Я совершенно невежественен, любые предложения очень ценятся.
Спасибо!
Комментарии:
1. Это звучит как проблема с потоками (хотя и не уверен, почему). Вы пытались сделать поля (имя, аффинити и поля) окончательными, чтобы посмотреть, решит ли это вашу проблему?
2. Трудно сказать наверняка, не видя тестов, но мне кажется, что они разделяют какое-то состояние или ресурс, которые неправильно сбрасываются для следующего теста.
3. Что такое поле? Он содержит
Table
?4. Существует ли цикл загрузки класса между
Table
иField
?5. Не могли бы вы, пожалуйста, предоставить модульный тест и
Field
код?
Ответ №1:
Я думаю, у вас есть цикл загрузки класса между Table
и Field
.
Рассмотрим следующие перечисления:
enum A {
X(B.Z),
A(B b) {
System.out.println("Constructing " name() ": " b);
}
}
enum B {
Z(A.X);
B(A a) {
System.out.println("Constructing " name() ": " a);
}
}
Потому A
что ссылки B
, загрузка A
которых приводит B
к загрузке; но B
ссылки A
, которые вызывают A
загрузку — за исключением того, что они уже загружены, поэтому вы видите неинициализированные значения полей ( null
) при построении Z
.
Вам нужно определить этот цикл (это может быть не цикл длиной 2, подобный этому, и может включать не только классы enum, поэтому это может быть не совсем очевидно; существуют инструменты для определения циклических зависимостей в коде) и разорвать его.
Комментарии:
1. Я добавил отчет об ошибке. Я думаю, компилятор должен хотя бы предупредить. Если компилятор отклонит его с ошибкой, было бы лучше. Это просто скрытая бомба NPE.
Ответ №2:
Попытался выполнить приведенный выше код, и он отлично сработал для меня, предполагая, что поле enum (прилагается здесь). Он выдал желаемый результат со следующим кодом:
public class Runner {
public static void main(String[] args) {
System.out.println(Table.BASE_PRICES);
}
}
public enum Field {
BILLING_WEIGHT_LOWER_BOUND, BILLING_WEIGHT_UPPER_BOUND, BASE_PRICE, SERVICE_TYPE_ID, ZONE_ID,
COUNTRY_CODE, SERVICE_TYPE, COUNTRY_CODE_ID, POST_CODE_LOWER_BOUND, POST_CODE_UPPER_BOUND, ZONE_CODE;
}
КОНСТРУКТОР ENUM (base_prices):
[BILLING_WEIGHT_LOWER_BOUND, BILLING_WEIGHT_UPPER_BOUND, БАЗОВАЯ ЦЕНА, SERVICE_TYPE_ID, ИДЕНТИФИКАТОР ЗОНЫ]
КОНСТРУКТОР ENUM (country_codes): [COUNTRY_CODE]
КОНСТРУКТОР ПЕРЕЧИСЛЕНИЯ (service_types): [SERVICE_TYPE]
КОНСТРУКТОР ENUM (zone_division): [COUNTRY_CODE_ID, SERVICE_TYPE_ID, ZONE_ID, POST_CODE_LOWER_BOUND, POST_CODE_UPPER_BOUND]
КОНСТРУКТОР ПЕРЕЧИСЛЕНИЯ (зоны): [ZONE_CODE]
Дайте мне знать, если вы делаете здесь что-то другое.