Let me say I have an interface with a generic parameter.
@NoRepositoryBean
interface ISomeRepository<ENTITY extends AbstractSome<ENTITY>> {
Streamable<? extends ENTITY> findAllByOther(String other, Pageable pageable);
Streamable<ENTITY> findAllByAnother(String another, Pageable pageable);
// <? extends ENTITY> vs. <ENTITY>
}
The Streamable
is just an interface, and actual repository interface should override the type such as Page
or Slice
.
class Some extends AbstractSome<Some> {
}
@NoRepositoryBean
interface SomeRepository extends ISomeRepository<Some> {
Page<Some> findAllByOther(String other, Pageable pageable);
Slice<Some> findAllByAnother(String another, Pageable pageable);
}
Both overridden methods work as expected.
Does the <? extends ENTITY>
have any meaning more than the <ENTITY>
part?
It does have more meaning than just ENTITY
. The implementation of ISomeRepository<Some>
can return Streamable
s of subclasses of Some
. Suppose there is a Some
subclass called SomeChild
, you can write
public class SomeRepository extends ISomeRepository<Some> {
public Page<SomeChild> findAllByOther(String other, Pageable pageable) {
// ...
}
// ...
}
Though, in the context of a "repository", you are probably not going to write something like that anyway.
If in your implementation of findAllByOther
, you call some other method that returns a Page<? extends Some>
, then having Streamable<? extends ENTITY>
as the return type allows you to return that directly. On the other hand, you cannot return a Page<? extends Some>
from a method that is declared to return Streamable<Some>
.
? extends ENTITY
also affects the caller. If the caller calls findAllByOther
through the ISomeRepository<Some>
interface, they cannot call methods of Streamable
that take T
as an input. For example,
Streamable<? extends Some> streamable = someRepo.findAllByOther(...);
Some somethingElse = ...;
streamable.and(somethingElse); // this does not compile