public <T extends UpperBoundClass> T getInstance() {
UpperBoundClass instance = classAttribute.newInstance();
return instance;
}
This code does not actually return <T>. It returns an instance of the specific Class<? extends UpperBoundClass> referenced by the classAttribute field. All the compiler can verify is that instance is assignable to (able to be cast to) UpperBoundClass. However, there is no declared relationship between that instance and the specific type represented by <T> in the method signature.
End result: you're going to get a warning. It might happen to work as long as every place you use CONSTANT_ONE or CONSTANT_TWO is already expecting the same type as you put in their respective constructors, but the compiler can't enforce or know that.
If you change your method to the following, then you will see the usage sites (in the calling code) that are not strictly type-safe because they assume a particular subclass:
public UpperBoundClass getInstance() {
return classAttribute.newInstance();
}
Alternatively, you can provide some relationship between your <T> and the stored class reference:
public <T extends UpperBoundClass> T getInstance(Class<T> type) {
UpperBoundClass instance = classAttribute.newInstance();
return type.cast(instance); // verifies type-safety
}
But there's little point in doing that, because the caller could either call type.newInstance() itself or simply new ClassOne() (depending on the use case). The call to type.cast(instance) could throw ClassCastException at runtime, but the compiler will be happy because it considers it your problem at that point.
You're fighting the fact that an enum presents a uniform contract; and while you can customize individual constants with polymorphic behavior, you cannot use generics to parameterize the enum's base API with something that varies from instance to instance.
Related reading: Why shouldn't Java enum literals be able to have generic type parameters?
newInstance?