#java #type-conversion #type-erasure
#java #преобразование типа #стирание типа
Вопрос:
У меня есть интерфейс:
public interface Message<T extends Message<T>> {
}
У меня есть класс, который реализует этот метод как
public class FulfilmentReleasedDomModel implements Message<FulfilmentReleasedDomModel> {}
И у меня есть этот метод:
private <T extends Message<T>> Mono<T> getDomainModel(ConsumerRecord<String, String> record) {}
Когда я пытаюсь вернуть объект типа Mono<FulfilmentReleaseDomModel>
из этого метода, компилятор выдает ошибку и просит меня преобразовать его в ( Mono<T>
).
Мой вопрос в том, что, поскольку я ограничил T
до extends Message
и FulfilmentReleasedDomModel
реализует Message<FulfilmentReleasedDomModel>
, зачем мне нужно приводить его к Mono<T>
?
Ответ №1:
Распространенное заблуждение относительно дженериков заключается в том, что вызываемый объект решает, каков общий тип. Нет, вызывающий выполняет.
Вы, как автор метода, не можете решать, что T
такое. Возвращая Mono<FulfilmentReleasedDomModel>
, вы говорите, что это T
должно быть FulfilmentReleasedDomModel
. Но на самом деле вызывающий ваш метод будет решать, что T
такое. Они могли бы объявить тип с именем, Foo
который реализует Message<Foo>
, и сказать, что это T
есть Foo
. Вместо этого вам нужно было бы вернуть Mono<Foo>
.
Похоже, что ваш метод не должен быть универсальным, потому что вызываемый объект решает, какой тип использовать:
private Mono<FulfilmentReleasedDomModel> getDomainModel(ConsumerRecord<String, String> record) {}
В качестве альтернативы, если вы хотите сделать этот метод более гибким, чтобы вы могли изменить его реализацию, чтобы возвращать что-то другое без изменения возвращаемого типа, вы можете использовать общие подстановочные знаки:
private Mono<? extends Message> getDomainModel(ConsumerRecord<String, String> record) {}