简体   繁体   中英

Compiler change in Java 7

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM