, . , -, getAnimalClass() - ( , ).
canFeed(animal) Feeder ( getAnimalClass()). , Feeder , .
, Feeder, , Class, ( getAnimalClass(), , , ):
final Class<T> typeParameterClass;
public Feeder(Class<T> typeParameterClass){
typeParameterClass = typeParameterClass;
}
canFeed:
public boolean canFeed(Animal animal) {
return typeParameterClass.isAssignableFrom(animal.getClass());
}
PetStore :
private Feeder feederFor(Animal animal) {
return feeders.stream()
.filter(feeder -> feeder.canFeed(animal))
.findFirst()
.orElse((Feeder) unknownAnimal -> {});
}
, . , , , , Spring beans, .
, PetStore Map:
@Autowired
Map<String, Feeder<? extends Animal>> feederMap;
, ( ) . canFeed :
private boolean canFeed(String feederName, Animal animal) {
return feederName.contains(animal.getClass().getTypeName());
}
Feeder :
private Feeder feederFor(Animal animal) {
return feederMap.entrySet().stream()
.filter(entry -> canFeed(entry.getKey(), animal))
.map(Map.Entry::getValue)
.findFirst()
.orElse((Feeder) unknownAnimal -> {});
}
, , - . , canFeed default Feeder<T>:
default <A extends Animal> boolean canFeed(A animalToFeed) {
return A == T;
}
, A == T, - A T. , , . Spring, Java:
this.entityBeanType = ((Class) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0]);
Feeder Feeder<T>, , . , , ( , invokedynamic), .
, , , . , , , , , , :
, , , , SAM- SAM. , 3% . , / factory, , .
factory, , .
, - . Spring GenericTypeResolver Animal, , -.
, LambdaMetafactory . , Config . ASM , . , , , , Unsafe.defineAnonymousClass. , Class.getConstantPool, ASM , JDK. ( ) , , TypeTools. , , Serialization . , Spring api.
, , (, ), Feeder -hack hack :
default <A extends Animal> boolean canFeed(A animalToFeed) {
Class<?> feederType = TypeResolver.resolveRawArgument(Feeder.class, this.getClass());
return feederType.isAssignableFrom(animalToFeed.getClass());
}
PetStore :
@Autowired
private List<Feeder<? extends Animal>> feeders;
public void feed(Animal animal) {
feederFor(animal).feed(animal);
}
private Feeder feederFor(Animal animal) {
return feeders.stream()
.filter(feeder -> feeder.canFeed(animal))
.findFirst()
.orElse(unknownAnimal -> {});
}
, , , , , , (, , ) .