Использование вложенных универсальных типов в HashMap - PullRequest
0 голосов
/ 09 июня 2018

Я ищу способ получить Map с универсальными типами в типах Map, а затем получить те, которые используют ключ и правильный тип.Например:

private final <T> Map<A<T>,B<T>> map = new HashMap<>();

public <T> B<T> getB(final A<T> a) {
  return map.get(a);
}

Примером использования этого будет:

final A<String> a = ...;
final B<String> b = getB(a);

Существует ли это каким-либо образом или есть обходной путь?

Редактировать: IЯ знаю, что могу обойти это, разыгрывая вещи, но мне интересно, есть ли более элегантный способ, который не требует, чтобы я разыгрывал все значения, которые я получаю.

Ответы [ 2 ]

0 голосов
/ 09 июня 2018

Что ж, меня спровоцировали опубликовать этот ответ как своего рода представление о принципах ООП.

В вопросе стоит Map<A<T>,B<T>>, поэтому мой подход заключается в том, чтобы сделать что-то вроде этого:

class A<T> {}
class B<T> {}

public class Answer {

    public static void main(String[] args) {

        Map<A, B> map = new HashMap<>();
        A<Integer> a = new A<>(); //very safe
        B<String> b = new B<>(); //very safe

        map.put(a, b); //very safe

    }

}

Признаюсь, есть дополнительная работа, но ...

0 голосов
/ 09 июня 2018

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

Но, к счастью, язык предоставляет запасной штрих от использования системы типов в виде casts .По сути, приведение - это способ предоставления информации о типе, которой нет у компилятора;Однако на вас ложится обязанность убедиться, что он действительно является безопасным типом.

Во-первых, объявите карту с подстановочными типами:

private final Map<A<?>,B<?>> map;

Затем, помещайте на карту только пары ключ / значение, которые do соответствуют ограничению:

<T> void put (A<T> key, B<T> value) {
  map.put(key, value);
}

И затем разыгрываете, когда вы снова получаете элемент:

@SuppressWarnings("unchecked") // Safe
<T> B<T> get(A<T> key) {
  return (B<T>) map.get(key);
}

Дело в том, что вы можете знать больше о типах, чем компилятор.При условии, что вы позаботились о том, чтобы ставить только безопасные пары, их можно безопасно разыграть.(Также необходимо убедиться, что метод equals учитывает тип, поэтому A<T> не равно A<S>, если S == T).

Это в основном «безопасный для типа гетерогенный контейнер», как описано в Effective Java (пункт 33 в 3-м издании).

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

Во-первых, вы на самом деле не выполняете приведение в методе get во время выполнения: вот что означает непроверенное приведение.

Для другого, дженерики вводят загружает приведений - в основном, дженерики - это просто способ избежать вставки приведений вручную.Поэтому, если бы была проблема с приведениями (например, производительность), вы бы уже наблюдали это во многих местах.

Перефразируя Кубрика: перестаньте беспокоиться и полюбите состав.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...