#java #generics
#java #дженерики
Вопрос:
У меня есть эта задача создать пользовательскую реализацию универсального списка, которая соответствует следующим требованиям:
- имеет 3 класса: 1 абстрактный класс (скажем,
ExampleAbstractList
), одну реализацию пустого списка (например,ExampleEmptyList
) и один непустой список (например,ExampleNonEmptyList
) - должна быть возможность добавлять / объединять два неабстрактных класса вместе обоими способами (например, добавлять непустой список в пустой список и наоборот)
- «разработчики» должны работать с абстрактным классом (например
ExampleAbstractList<Integer> list2 = new ExampleNonEmptyList<>(11, list1);
ExampleNonEmptyList
класс может получить 2 параметра: первый параметр должен иметь некоторый тип, и это будет «заголовок» списка, и второй параметр, который должен быть самим списком (ExampleNonEmptyList
илиExamplenEmptyList
)- В конечном счете, предоставьте заводскую функцию для изготовления семейств связанных объектов, чтобы скрыть фактическую реализацию
Моя текущая реализация выглядит следующим образом:
public abstract class ExampleAbstractList<T> {
protected transient T head;
protected transient T tail;
...
public abstract void add(T e);
...
}
public final class ExampleNonEmptyList<T, U> extends ExampleAbstractList<T> {
protected ArrayList<T> tail_elements = new ArrayList<>();
public ExampleNonEmptyList(T head, U tail)
{
this.setHead(head);
this.add((T) tail);
}
...
@Override
public void add(T e)
{
if(e instanceof ExampleNonEmptyList)
{
ExampleNonEmptyList enel = (ExampleNonEmptyList) e;
T enHead = (T) enel.getHead();
this.getTailElements().add(enHead);
for(Object tElem : enel.getTailElements())
{
T tailElement = (T) tElem;
this.getTailElements().add(tailElement);
}
} else if (e instanceof ExampleEmptyList) {
ExampleEmptyList list = (ExampleEmptyList) e;
if(list.size() == 0)
return;
for(Object el : list.getList())
{
this.getTailElements().add((T) el);
}
} else {
this.getTailElements().add(e);
}
this.updateSize();
}
...
}
public final class ExampleEmptyList<T> extends ExampleAbstractList<T> {
private final List<T> list = new ArrayList<>();
...
public void add(T e)
{
this.getList().add(e);
this.updateSize();
}
...
}
Теперь у меня проблема в том, что я не могу добавить ExampleNonEmptyList к ExampleEmptyList, потому что я получаю следующую ошибку:
incompatible types: ExampleAbstractList <Integer> cannot be converted to Integer
(когда я пытаюсь добавить списки целых чисел)
Исключение:
Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - Erroneous sym type: ExampleAbstractList.add
at Main.main(Main.java:42)
Java Result: 1
Код в Main.java:
32 ExampleAbstractList<Integer> list0 = new ExampleEmptyList<>();
33 list0.add(3);
34 ExampleAbstractList <Integer> list1 = new ExampleNonEmptyList<>(1, list0);
35 ExampleAbstractList <Integer> list2 = new ExampleNonEmptyList<>(32, list1);
36 list2.add(9);
...
Some prints
...
42 list0.add(list1);
Я понимаю ошибку и уверен, что она связана с параметрами типа, но я не могу понять, как это исправить… Кто-нибудь, пожалуйста, может мне помочь?
Спасибо!
Комментарии:
1. Можете ли вы опубликовать полную ошибку?
2. Почему
ExampleNonEmptyList
имеет два параметра типа вместо одного? В конечном итоге вы все равно приводите толькоU tail
к типуT
, и если они будут элементами в одном базовом списке, они должны быть одного типа.3. @Tenner когда я это делал, я делал это потому, что класс должен получать два аргумента двух разных типов, но теперь я вижу, что могу ссылаться на ExampleAbstractList там вместо ‘U’. Сейчас я это исправил, но это не решает мою проблему.
Ответ №1:
Из вашего кода следует, что вы добавляете один список в другой с помощью list0.add(list1)
. Вместо этого попробуйте list0.addAll(list1)
метод. метод addAll принимает Collection<? extends E> c
в качестве аргумента и должен использоваться в вашем конкретном случае. Больше информации здесь
Комментарии:
1. я сделал это: ‘public void addAll(Collection<? расширяет T> e) { this.getList().addAll(e); this.updateSize(); }’, но я получаю почти ту же ошибку, но теперь она стала ‘несовместимые типы: ExampleAbstractList <Целое число> невозможно преобразовать TCollection<? расширяет Integer>’ вместо просто Integer.
2. Вам просто нужно заменить
list0.add(list1)
наlist0.addAll(list1)
. Это то, что вы сделали?3. да, даже приведено list1 к Collection<?расширяет целое число>
4. ОК. но
list0.add(list1)
это определенно неверно. Придется копать глубже.