TL; DR: Не устанавливайте для свойства ComboBox#items
значение ObservableList
, поддерживаемое List
, которое не допускает null
элементов.
Важной частью вашей трассировки стека являются первые несколько кадров (или последние несколько кадров, в зависимости от того, как вы на это смотрите):
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
at java.base/java.util.Objects.requireNonNull(Objects.java:222)
at java.base/java.util.ImmutableCollections$AbstractImmutableList.indexOf(ImmutableCollections.java:166)
at javafx.base/com.sun.javafx.collections.ObservableListWrapper.indexOf(ObservableListWrapper.java:124)
at javafx.controls/javafx.scene.control.ComboBox.lambda$new$1(ComboBox.java:245)
В частности, этот кадр:
at java.base/java.util.ImmutableCollections$AbstractImmutableList.indexOf(ImmutableCollections.java:166)
Это означает, что вы используете один из неизменяемых списков , добавленных в Java 9/10, и вы действительно подтверждаете это в своем собственном ответе . Характеристики этих неизменяемых списков включают следующее:
Они запрещают null
элементы [выделение добавлено] . Попытки создать их с элементами null
приводят к NullPointerException
.
И документации List#indexOf(E)
, которую вы видите, было вызвано просмотром трассировки стека , состояния:
Броски:
NullPointerException
- если указанный элемент является нулевым и этот список не допускает нулевые элементы ( необязательно )
Затем, согласно ваш ответ снова, вы используете FXCollections#observableList(List)
. Этот метод:
Создает ObservableList
, для которого поддерживается указанным списком [выделение добавлено] . Об операциях мутации в экземпляре ObservableList
будет сообщено наблюдателям, которые зарегистрировались в этом экземпляре.
Это означает, что вы установили для элементов ComboBox
значение ObservableList
, поддерживаемое List
, который не допускает null
элементов. Если вы снова посмотрите на трассировку стека, вы увидите, что здесь происходит вызов #indexOf(E)
:
at javafx.controls/javafx.scene.control.ComboBox.lambda$new$1(ComboBox.java:245)
Вот исходный код (JavaFX 13.0.2) ComboBox
вокруг этой строки:
public ComboBox(ObservableList<T> items) {
getStyleClass().add(DEFAULT_STYLE_CLASS);
setAccessibleRole(AccessibleRole.COMBO_BOX);
setItems(items);
setSelectionModel(new ComboBoxSelectionModel<T>(this));
// listen to the value property input by the user, and if the value is
// set to something that exists in the items list, we should update the
// selection model to indicate that this is the selected item
valueProperty().addListener((ov, t, t1) -> {
if (getItems() == null) return;
SelectionModel<T> sm = getSelectionModel();
int index = getItems().indexOf(t1); // LINE 245 (NPE THROWN HERE)
// REST OMITTED FOR BREVITY
}
Вполне допустимо, чтобы значение ComboBox
было null
. Это может привести к тому, что t1
будет null
, и, таким образом, строка 245 станет:
int index = getItems().indexOf(null);
И ваш NullPointerException
будет брошен.
Решение состоит в том, чтобы убедиться, что ObservableList
из элементов разрешений null
элементов. Ваш ответ означает, что вы нашли хотя бы одно решение. Если вы хотите продолжить возвращать неизменяемый, недопустимый список из вашего DAO, и вы не против скопировать список, возвращенный вашим DAO, в другой список, тогда вы можете использовать FXCollections#observableArrayList(Collection)
, когда установить элементы вашего ComboBox
или даже просто сделать:
comboBox.getItems().setAll(collectionFromDao);