Replacing covariants (Foo<? extends T>) or contravariants (Foo<? super T>) with LVTI is a dangerous approach and should be avoided.
Check out the following snippet of code:
// explicit types
Class<? extends Number> intNumber = Integer.class;
Class<? super FilterReader> fileReader = Reader.class;
In the covariant, we have an upper bound represented by the Number class, while in the contravariant, we have a lower bound represented by the FilterReader class. Having these bounds (or constraints) in place, the following code will trigger a specific compile-time error:
// Does not compile
// error: Class<Reader> cannot be converted
// to Class<? extends Number>
Class<? extends Number> intNumber = Reader.class;
// error: Class<Integer> cannot be converted
// to Class<? super FilterReader>
Class<? super FilterReader> fileReader = Integer.class;
Now, let's use var instead of the preceding covariant and contravariant:
// using var
var intNumber = Integer.class;
var fileReader = Reader.class;
This code will not cause any issues. Now, we can assign any class to these variables so that our bounds/constraints vanish. This is not what we intended to do:
// this will compile just fine
var intNumber = Reader.class;
var fileReader = Integer.class;
So, using var in place of our covariant and contravariant was a bad choice!