Nano Hash - криптовалюты, майнинг, программирование

Дженерики: как получить значения карты без приведения

У меня есть абстрактный класс с именем BaseCode и 2 конкретных класса с именами Location и Department:

public abstract class BaseCode {
   private Integer id;
   ...
   public Integer getId() { return id; }
   public void setId(Integer id) { this.id = id; }
   ...
}

public class Location extends BaseCode {
   ...
}

public class Department extends BaseCode {
   ...
}

У меня есть абстрактный класс с именем BaseCodeCache и 2 конкретных класса с именами LocationCache и DepartmentCache. LocationCache и DepartmentCache будут использовать Singleton.

public abstract class BaseCodeCache {
   ...
}

public class LocationCache extends BaseCodeCache {
   ...
}

public class DepartmentCache extends BaseCodeCache {
   ...
}

  1. В BaseCodeCache я хочу иметь java.util.Map, значение которого может быть любым типом BaseCode, то есть Location объектов или Department объектов.
    В LocationCache я хочу, чтобы java.util.Map хранило Location объектов.
    В DepartmentCache я хочу, чтобы java.util.Map хранил Department объектов.

Для этого я поместил этот код в BaseCodeCache:

private Map<Integer, BaseCode> idMap = new HashMap<Integer, BaseCode>();

  1. Я хочу иметь метод для хранения значения в java.util.Map.

Для этого я поместил этот код в BaseCodeCache:

public void add(BaseCode baseCode) {
   if (baseCode != null) {
      idMap.put(baseCode.getId(), baseCode);
   }
}

Вот как я бы использовал его для Location:

Location location = new Location(); ...
LocationCache.getInstance().add(location);

Вот как я бы использовал его для Department:

Department department = new Department(); ...
DepartmentCache.getInstance().add(department);

  1. Я хочу иметь метод для получения всех значений в java.util.Map как java.util.List.
    В LocationCache этот метод должен возвращать List<Location>.
    В DepartmentCache этот метод должен возвращать List<Department>.

Вот где я застрял. Я хочу создать этот метод в BaseCodeCache, но когда этот метод вызывается через LocationCache, он возвращает List<Location>, а когда тот же метод вызывается через DepartmentCache, он возвращает List<Department>. Возможно ли это?

Я поместил этот код в BaseCodeCache:

public List<BaseCode> getList() {
   return new ArrayList<BaseCode>(idMap.values());
}

Но приведенный выше код возвращает List<BaseCode>. Когда я бы назвал это так:

List<Location> allLocations = LocationCache.getInstance().getList();

Тогда java не позволит ему скомпилироваться и выдаст это сообщение об ошибке:

Несоответствие типов: невозможно преобразовать List<BaseCode> в List<Location>

Я могу исправить это, получив List<BaseCode>, а затем преобразовав его в List<Location> с помощью цикла, но это выглядит неправильно.

Можно ли это сделать?


Ответы:


1

Реализуйте использование дженериков следующим образом:

public abstract class BaseCodeCache<T extends BaseCode> {
    private Map<Integer, T> idMap = new HashMap<>();

    public void add(T baseCode) {
        if (baseCode != null) {
            idMap.put(baseCode.getId(), baseCode);
        }
    }

    public List<T> getList() {
        return new ArrayList<>(idMap.values());
    }
}

public class LocationCache extends BaseCodeCache<Location> {}

public class DepartmentCache extends BaseCodeCache<Department> {}

Это позволит вам сделать следующее без каких-либо ошибок компиляции:

LocationCache locationCache = new LocationCache();
locationCache.add(new Location());

List<Location> locations = locationCache.getList();

Более того, вы получите ошибки компиляции, если попытаетесь добавить или получить объекты неправильного типа:

locationCache.add(new Department()); // won't compile
List<Department> departments = locationCache.getList(); // won't compile
26.07.2017
  • Спасибо чувак. Это круто. Один вопрос. Есть ли название типа дженериков, которые вы используете? Если да, пожалуйста, укажите. ТИА 26.07.2017
  • Не знаю, что вы подразумеваете под типом дженериков. Приведенный выше пример на самом деле просто дженерики 101, первый пример, который вы найдете в учебнике. 27.07.2017
  • Спасибо. Я обнаружил, что вы используете параметр ограниченного типа T. 27.07.2017
  • Stat rosa pristina nomine, nomina nuda tenemus 27.07.2017
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..