Рубрики
Без рубрики

Эффективная Java! Рассмотрим Безопасные для Типов Разнородные Контейнеры

Погружение в главу 33 “Эффективная Java”. Помеченный как java, эффективный, универсальный, архитектура.

Наиболее распространенными вариантами использования дженериков являются такие коллекции, как Список и Карта , а также одноэлементные контейнеры, такие как Локальный поток и Атомная ссылка . Как в случае коллекции, так и в случае одноэлементных объектов существует очень ограниченный список используемых типов. Это хорошо помогает нам во многих случаях, однако иногда нам требуется дополнительная гибкость. У нас может быть такой вариант использования, как сопоставление строки из базы данных безопасным для типов способом. В этих случаях мы должны использовать другую технику. Этот метод заключается в параметризации ключа для данных, а не для контейнера полностью. То есть вместо указания типа контейнера мы указываем тип конкретной части данных. Делая это, мы можем обеспечить дополнительную гибкость, сохраняя при этом безопасность типов.

Давайте рассмотрим пример. Рассмотрим Любимый класс. Цель этого класса – собрать ваш любимый объект произвольного количества типов. Объект Class будет служить ключом к вашему Любимому классу. Это работает, потому что тип класса является универсальным и содержит свой собственный тип Класс . Это String.class является Классом<Строка> , Integer.class является классом<Целое число> и так далее.

API для нашего Любимого класса прост:

public class Favorites {
  public  void putFavorite(Class type, T value);
  public  T getFavorite(Class type);
}

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

Favorites favorites = new Favorites();
favorites.putFavorite(String.class, "Hello world");
favorites.putFavorite(Integer.class, 123);
favorites.putFavorite(Class.class, Favorite.class); 

и, наконец, давайте проверим реализацию:

public class Favorites {
  private Map, Object> favorites = new HashMap<>();
  public  void putFavorite(Class type, T value) {
    favorites.put(Objects.requireNonNull(type), value);
  }
  public  T getFavorite(Class type) {
     return type.cast(favorites.get(type));
  }
}

Для того, что делает этот класс, это не слишком сложно. Что за Класс Favorite в конечном итоге представляет типобезопасный, а также имеет разный тип для каждого элемента, таким образом, неоднородный. Вот как мы переходим к описанию гетерогенного контейнера из названия главы. Глядя на приведенную выше реализацию, вероятно, наиболее интересной частью является функция получить избранное . Потому что мы теряем информацию о типе, как только помещаем значение в Карту нам нужен способ извлечения значения безопасным для типов способом. Вот где пригодится функция Class.cast . Если объект не может быть приведен к типу, мы получим исключение ClassCastException . Потому что мы контролируем типы, которые входят в Карту мы знаем, что в обычном случае этого не произойдет.

Какие ограничения имеет наша реализация Избранное ? Первый из них заключается в том, что если пользователь нашего класса создаст необработанный объект класса, он может нарушить безопасность типов нашего класса. Это ничем не отличается от наличия Хэш-набора<Целое число> и вводим строку , обращаясь к ней как к необработанному хэш-набору . Мы действительно можем обеспечить безопасность типов во время выполнения, если готовы за это заплатить. Изменив функцию поместить в избранное на следующую, мы можем обеспечить безопасность типов во время выполнения, даже если доступ осуществляется через необработанные типы.

public  void putFavorite(Class type, T value) {
  favorites.put(Objects.requireNonNull(type), type.cast(value));
}

В файле java.util есть обертки коллекции. Коллекции , которые делают то же самое. проверенный список , проверенный набор и т. Д. Выполняют ту же проверку во время выполнения и могут быть полезны при отслеживании того, где в коде, работающем как с параметризованными, так и с необработанными коллекциями, вносятся небезопасные изменения типа.

Второе ограничение заключается в том, что наш Избранное класс нельзя использовать с непроверяемыми типами. Это означает, что мы можем сохранить вашу любимую строку , Целое число , Строка[] но мы не можем хранить наши любимые Список<Строка> и другие непроверяемые типы. Это происходит потому, что во время выполнения мы теряем параметризованную часть нашего типа и просто остаемся с List.class по вышеуказанной причине и, следовательно, не было бы способа узнать разницу между List<Строка> и Список<Целое число> во время выполнения.

Хотя часто мы можем обойтись параметризованными коллекциями и типами отдельных элементов, иногда нам нужна дополнительная гибкость гетерогенных контейнеров, безопасных для типов. Это стало возможным благодаря классу типу, который обеспечивает безопасность типов более динамичным образом.

Оригинал: “https://dev.to/kylec32/effective-java-consider-typesafe-hetergenous-containers-1o36”