Я только что написал следующий метод.
static <R> R encodeBase16(final Supplier<? extends byte[]> supplier,
final Function<? super byte[], ? extends R> function) {
requireNonNull(supplier, "supplier is null");
requireNonNull(function, "function is null");
return function.apply(encodeBase16(supplier.get()));
}
Пока у компилятора вроде нет проблем с этим.
Эти части ? extends byte[]
и ? super byte[]
имеют смысл? Или я могу просто использовать byte[]
?
static <R> R encodeBase16(final Supplier<byte[]> supplier,
final Function<byte[], ? extends R> function) {
requireNonNull(supplier, "supplier is null");
requireNonNull(function, "function is null");
return function.apply(encodeBase16(supplier.get()));
}
Это отлично. Вы можете поместить любой тип ссылки после extends
/super
в подстановочном знаке. См. продукционное правило здесь:
TypeArguments:
< TypeArgumentList >
TypeArgumentList:
TypeArgument {, TypeArgument}
TypeArgument:
ReferenceType
Wildcard
Wildcard:
{Annotation} ? [WildcardBounds]
WildcardBounds:
extends ReferenceType
super ReferenceType
Как вы знаете, использование подстановочных знаков позволяет использовать подтипы byte[]
в качестве аргумента типа для подстановочного знака extends byte[]
и супертипы byte[]
в качестве аргумента типа для подстановочного знака super byte[]
. Насколько я знаю, у byte[]
нет подтипов, а есть только супертипы byte[]
:
Object
Serializable
Cloneable
согласно этому. Так, например, вы можете передать Function<Object, R>
этому методу:
Function<Object, String> function = x -> null;
encodeBase16(() -> null, function);
Это полезно? Я бы так не сказал, но вам разрешено делать неполезные вещи.
Связанный вопрос о «избыточном» использовании подстановочных знаков
Ничего нельзя добавить к ответу @sweeper. В любом случае, на вашем месте я бы сохранил подстановочные знаки в вашем коде, потому что он соблюдает принцип PECS и, следовательно, имеет также цель документирования. Как только кто-то сможет реорганизовать
byte[]
вSomeCustomClass
, тогда подстановочные знаки будут необходимы.