I’d say the best situation would be keep the type information at compile time but let the VM decide if multiple implementations are needed or not at runtime.
I’d say the best situation would be keep the type information at compile time but let the VM decide if multiple implementations are needed or not at runtime.
However, what if you have a collection of generic functions divorced from the arguments? There's no way from the function alone to determine the type params. So you can't write code that reflects over a collection of generic functions and dispatches solely on the type params.
And, while I've been speaking of functions, this really generalizes to any generic type. If you have e.g. a collection of PetTrainer<?>, and you have a code path in which you have a pet of type Dog or Cat, how can you use only reflection to choose a trainer upon which you can call Train(pet)? You can't.
(I don't Java, so please give me a little slack wrt syntax.)
Implementing that by hand using reflection just sounds plain wrong.
Would love to hear of a concrete real world example where this was an issue
The last bit of the GP comment is an example of the sort of thing that isn't possible with generics in Java, because the PetTrainer-of-Dogs and PetTrainer-of-Cats are indistinguishable at runtime. If you want to solve the problem with dynamic dispatch on the type-erased type of the first argument only, you could *stop using generics*, write a separate class for each generic instantiation you would have had, send every pet to every trainer, and have each trainer check the runtime type of their argument and do nothing if it's the wrong type. This probably isn't what anyone really wants to write or an acceptably cheap thing to do at runtime.
Nobody actually deals with PetTrainers but people do deal with MessageSubscribers that work more or less exactly as described, and the type system does nothing to help. For a concrete example of the horrors of double dispatch, you could see the wonderful book Crafting Interpreters.