Вы можете сделать это, если считаете, что тип S правильный:
protected <S, T extends S> void setValue(final S oldValue, final T newValue) {
// Do something
}
Вы можете и не можете вводить эти данные:
// Works
setValue("something", "something");
setValue(new Object(), new String());
// Doesn't work
setValue(new String(), new Object());
или
Вы можете сделать:
protected <S> void setValue(final S oldValue, final S newValue, final Class<S> clazz) {
// Do something
}
и используйте его вот так
setValue("something", "something", String.class);
или
protected <S> void setValue(final S oldValue, final S newValue) {
if(!oldValue.getClass().equals(newValue.getClass())) {
//throw something
}
}