In Java 6 I was able to use:
public static <T, UK extends T, US extends T> T getCountrySpecificComponent(UK uk, US us) {
Country country = CountryContext.getCountry();
if (country == Country.US) {
return us;
} else if (country == Country.UK) {
return uk;
} else {
throw new IllegalStateException("Unhandled country returned: "+country);
}
}
With these repositories:
public interface Repository{
List<User> findAll();
}
public interface RepositoryUS extends Repository{}
public interface RepositoryUK extends Repository{}
When using these:
RepositoryUK uk = ...
RepositoryUS us = ...
This line compiles in in Java6 but fails in Java7 (error cannot find symbol - as the compiler looks for findAll() on class Object)
List<User> users = getCountrySpecificComponent(uk, us).findAll();
This compiles in Java 7
List<User> users = ((Repository)getCountrySpecificComponent(uk, us)).findAll();
I know this is a rather uncommon use case but is there a reason for this change? Or a way to tell the compiler to be a little "smarter"?
I think T
should be bounded to extend Repository
. This way the compiler knows that getCountrySpecificComponent
returns some repository.
EDIT:
It should also be ok to write: public static <T extends Repository> T getCountrySpecificComponent(T uk, T us)
Then I agree it was a mistake for the old compiler to accept that. I think you want something like this:
public interface UserFindingComponent{
List<User> findAll();
}
public interface Repository extends UserFindingComponent{ }
public interface RepositoryUS extends Repository{}
public interface RepositoryUK extends Repository{}
...
public static <T extends UserFindingComponent, UK extends T, US extends T> T getCountrySpecificComponent(UK uk, US us) {
Country country = CountryContext.getCountry();
if (country == Country.US) {
return us;
} else if (country == Country.UK) {
return uk;
} else {
throw new IllegalStateException("Unhandled country returned: "+country);
}
}
In this case the compiler was unable to infer the type parameters, which probably should have been the case in Java 6 as well. You can tell the compiler what the generic types are however, using the syntax below:
import java.util.List;
class User {
}
interface Repository {
List<User> findAll();
}
interface RepositoryUS extends Repository {
}
interface RepositoryUK extends Repository {
}
class Test {
public static <T, UK extends T, US extends T> T getCountrySpecificComponent(UK uk, US us) {
Country country = CountryContext.getCountry();
if (country == Country.US) {
return us;
} else if (country == Country.UK) {
return uk;
} else {
throw new IllegalStateException("Unhandled country returned: " + country);
}
return us;
}
public static void main(String... args) {
RepositoryUK uk = null;
RepositoryUS us = null;
List<User> users = Test.<Repository, RepositoryUK, RepositoryUS>getCountrySpecificComponent(uk, us).findAll();
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.