Введите безопасный шаблон гетерогенного контейнера для хранения списков предметов - PullRequest
7 голосов
/ 01 июля 2011

Я пытаюсь реализовать безопасный для типов гетерогенный контейнер для хранения списков разнородных объектов.

Я видел несколько примеров безопасного для типов гетерогенного контейнера ( link ), но все они хранят один объект типа.

Я попытался реализовать это следующим образом:

public class EntityOrganizer {  

    private Map<Class<?>, List<Object>> entityMap = new HashMap<Class<?>, List<Object>>();

    public <T> List<T> getEntities(Class<T> clazz) {
        return entityMap.containsKey(clazz) ? entityMap.get(clazz) : Collections.EMPTY_LIST;
    }

    private <T> void addEntity(Class<T> clazz, T entity) {
        List<T> entityList = (List<T>) entityMap.get(clazz);
        if(entityList == null) {
            entityList = new ArrayList<T>();
            entityMap.put(clazz, (List<Object>) entityList);
        }
        entityList.add(entity);
    }   
}

Но проблема в том, что этот код полон непроверенных приведений. Может кто-нибудь помочь с лучшим способом реализации этого?

Большое спасибо

Ответы [ 3 ]

7 голосов
/ 01 июля 2011

Вопрос в том, что такое "непроверенный состав"?

Иногда приведение доказуемо безопасно, к сожалению, доказательство выходит за рамки возможностей javac, что делает только ограниченный статический анализ, перечисленный в спецификации. Но программист умнее, чем javac.

В этом случае я утверждаю, что это «проверенные приведения», и очень уместно подавить предупреждение.

См. 2 других связанных примера:

Гетерогенный контейнер для хранения объектов общего типа в Java

Typesafe for loading Имя класса

1 голос
/ 08 мая 2013

Вам не нужно разыгрывать:

(List<T>) entityMap.get(clazz).

Когда вы говорите

entityMap.get(clazz)

у вас на самом деле есть List<Object>, которого достаточно для ваших нужд.

То же самое для

entityList = new ArrayList<T>();

Вы должны просто использовать entityList = new ArrayList<Object>();

Ваш тип безопасности обеспечиваетсяобъявление метода

<T> void addEntity(Class<T> clazz, T entity) {

и использование Map с ключом класса.

Таким образом, код должен выглядеть следующим образом:

 private <T> void addEntity(Class<T> clazz, T entity) {
            List<Object> entityList = entityMap.get(clazz);
            if(entityList == null) {
                entityList = new ArrayList<Object>();
                entityMap.put(clazz, entityList);
            }
            entityList.add(entity);
   } 
0 голосов
/ 04 июня 2019

Для очень маленьких списков вы можете закодировать связанный список обобщенных java.

And<UUID, And<Integer, Of<String>>> x = Tuple.of("test").and(2).and(UUID.randomUUID());

Определение типов для And и Of немного ошеломляет. Для краткости я пропустил equals / hashCode.

import java.util.Objects;
import java.util.UUID;

public abstract class Tuple<T extends Tuple<T>> {
    public static final <E> Of<E> of(E e) {
        return new Of<>(e);
    }

    public abstract <E> And<E, T> and(E e);

    public static final class And<T, R extends Tuple<R>> extends Tuple<And<T, R>> {
        public final T t;
        public final R r;

        private And(T t, R rest) {
            this.t = t;
            this.r = rest;
        }

        public <N> And<N, And<T, R>> and(N next) {
            return new And<>(next, this);
        }
    }

    public static final class Of<T> extends Tuple<Of<T>> {
        public final T t;

        private Of(T t) {
            this.t = t;
        }

        public <N> And<N, Of<T>> and(N next) {
            return new And<>(next, this);
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...