class PublicTreeModel {
List<? extends PublicNodeModel> nodes = new ArrayList<>();
}
Вы не должны иметь возможность помещать в этот список что-либо, кроме буквального null
. Этот тип говорит: «это некоторый подкласс PublicNodeModel
, я просто не знаю, какой»: поскольку компилятор не знает, какой подкласс разрешить, он не позволяет добавлять какие-либо элементы. Вы должны использовать только элементы из этого списка, а не предоставлять ему элементы.
В этом конкретном случае c вы фактически просто меняете элементы в списке, поэтому есть простое решение:
TreeModel treeModel = Fixture.createModel();
int index = Fixture.indexOfPrimaryNode(treeModel.getNodes());
Collections.swap(treeModel.getNodes(), 0, index);
То есть: даже если вы не знаете точный ожидаемый подтип элементов в treeModel.getNodes()
, вы знаете, что элемент, который вы пытаетесь вставить обратно, был удален из списка; поэтому он безопасен от типа (или, по крайней мере, не менее безопасен от типа, чем он уже был).
В более общем случае есть два других решения: во-первых, удалите подстановочный знак, так что что список принимает любой подкласс PublicNodeModel
:
class PublicTreeModel {
List<PublicNodeModel> nodes = new ArrayList<>();
}
Это может быть неприемлемо, если вы действительно хотите полагаться на элементы nodes
, которые являются конкретно NodeModel
s.
Второй подход заключается в добавлении параметра типа в класс для типа элементов, которые будут храниться в списке:
class PublicTreeModel<T extends PublicNodeModel> {
List<T> nodes = new ArrayList<>();
}
В контексте кода, который вы show, в котором есть ошибка компиляции, второй подход может выглядеть так:
class TreeModel extends PublicTreeModel<NodeModel> {}
TreeModel treeModel = Fixture.createModel();
int index = Fixture.indexOfPrimaryNode(treeModel.getNodes());
NodeModel primaryNode = treeModel.getNodes().get(index);
treeModel.getNodes().set(index, treeModel.getNodes().get(0));
treeModel.getNodes().set(0, primaryNode);