В Java можно ли обойтись без использования «сырого непараметризированного класса» -es вместо фиктивных интерфейсов? - PullRequest
5 голосов
/ 11 июля 2020
• 1000
public class MyGenericType<X> {}

Я объявил x с упреждающим стиранием типа MyGenericType, потому что я не хотел создавать пустой интерфейс маркера только ради группировки. Будет ли это ради коллекции работать в мою пользу или мне придется сделать интерфейс маркера, чтобы сделать это возможным?

( EDIT ) То есть:

  1. public interface SomeCommonInterface {...}
  2. MyGenericType implements SomeCommonInterface ...
  3. Map<List<SomeCommonInterface>, Set<List<SomeCommonInterface>>> x = new HashMap<>();

Ответы [ 2 ]

4 голосов
/ 11 июля 2020

Напомним, что Integer, а также Double расширяют Number и, в свою очередь, Number расширяют Object.

A List<Number> никоим образом не может использоваться как List<Integer> и наоборот . List<Number> x = new ArrayList<Integer> не компилируется . Это называется «инвариантностью», и это «правильно», потому что, если бы он компилировался, вы могли бы добавить двойники к списку целых чисел, что явно неверно. Тем не менее, это имеет тенденцию сбивать людей с толку, поэтому я упоминаю об этом. Если вам нужна ковариация или контравариантность, вы должны выбрать эту : List<? extends Number> list = new ArrayList<Integer>(); выполняет компиляцию . Но тогда list.add(5); не будет, потому что, если бы это было так, вы снова могли бы добавлять двойники к списку целых чисел, а это было бы неправильно. Всякая проверка типов для дженериков прямо за дверью, а вы этого не хотите. Можете ли вы «уйти с рук»? Что ж, компилятор подбросит вам в лицо кучу предупреждений, и вы отключите проверку типов. Если вы имеете в виду «сойдет с рук»: «Компилируется»? Да, это так. Если вы имеете в виду: «Пройдет ли этот код какой-либо разумный код java кодера»? Нет, не будет .

Простое решение: что плохого в использовании MyGenericType<?> здесь?

NB: ключи на картах должны быть неизменяемыми; списка нет. Поэтому его использование - довольно плохой план; что это должно означать?

0 голосов
/ 11 июля 2020

На самом деле это не ответ, но, как сказано в комментарии здесь , я не думаю, что добавление подстановочных знаков что-то решает.

В зависимости от того, был ли сайт использования этого Map есть, у вас может быть какая-то безопасность. Я был на вашем месте пару раз, единственное решение, которое я знаю, - это сделать:

@Getter
static class Box<T> {

    private Map<List<MyGenericType<T>>, Set<List<MyGenericType<T>>>> x = new HashMap<>();

}

то есть: выставить Map через «оболочку», в которой определена переменная типа. Если вызывающие абоненты предоставляют тип при создании экземпляра Box, вы получите необходимую безопасность типа:

new Box<Integer>().getX().put(...); // you can only put a MyGenericType<Integer> in here now

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

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