Java возвращает параметры вложенного типа - PullRequest
0 голосов
/ 04 сентября 2018

У меня проблема с универсальной системой Java. В моей программе есть обертка для списков, которая должна иметь метод для возврата своего внутреннего списка:

public class Wrapper<T, S extends List<T>> {

    private S list;

    public Wrapper(S list) {
        this.list = list;
    }

    public S get() {
        return list;
    }
}

Затем есть Контекст, который содержит Карту с различными Обертками и метод, который возвращает список оберток, связанных с идентификатором:

public class Context {

    private Map<String, Wrapper> map;

    public Wrappers() {
        map.put("a", new Wrapper(ArrayList<String>());
        map.put("b", new Wrapper(LinkedList<Integer>());
    }

    public <T, S extends List<T>> S getList(String id) {
        return map.get(id).get();
    }
}

Теперь, когда я вызываю getList (), я хочу получить предупреждение компилятора или, по крайней мере, способ реализовать ошибку до того, как будет выдано исключение ClassCastException.

public class Receiver {

    public doSomething() {
        Context c  = new Context();
        c.createWrappers();

        // Ok
        ArrayList<String> list1 = c.getList("a");
        LinkedList<Integer> list2 = c.getList("b");

        // Compiler error or some way do check in getList().
        ArrayList<Integer> list3 = c.getList("a");
        LinkedList<String> list4 = c.getList("b");
    }
}

На самом деле я пробовал много вещей, таких как изменение определения Wrapper:

public class Wrapper<T, S extends List>

Но когда я хочу реализовать функцию get (), я сталкиваюсь с проблемой, я могу либо определить функцию следующим образом:

public List<T> get() {
    return list;
}

или как это

public S get() {
    return list;
}

В первом примере это все еще возможно сделать.

public doSomething() {
    //...
    LinkedList<String> list = c.getList("a");
}

и во втором примере это можно будет сделать.

public doSomething() {
    //...
    ArrayList<Integer> list = c.getList("a");
}

Есть ли способ определить метод get таким образом?

public S<T> get() {
    return list;
}

Мне кажется, что нет способа проверить одновременно и тип списка, и тип элементов.

1 Ответ

0 голосов
/ 04 сентября 2018

Компилятор не может узнать, какой тип возврата связан с конкретной переданной вами строкой (строки нельзя сделать безопасными для типа).

Однако вы можете заменить строки на типобезопасные маркерные объекты:

class ListId<T> {
    public ListId(string name) { ... }

    public static final ListId<ArrayList<String>> A = new ListId<>("a");
    public static final ListId<LinkedList<Integer>> B = new ListId<>("b");
}

public T getList<T>(ListId<T> id)
...