2012-05-22 7 views
5

In Java 6 konnte ich verwenden:Compiler Änderung in Java 7

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); 
    } 
} 

Mit diesen Repositories:

public interface Repository{ 
    List<User> findAll(); 
} 

public interface RepositoryUS extends Repository{} 

public interface RepositoryUK extends Repository{} 

Bei Verwendung dieser:

RepositoryUK uk = ... 
RepositoryUS us = ... 

Diese Linie stellt in in Java6, aber in Java7 fehlgeschlagen (Fehler kann kein Symbol finden - da der Compiler in der Klasse Object nach findAll() sucht)

List<User> users = getCountrySpecificComponent(uk, us).findAll(); 

Dies kompiliert in Java 7

List<User> users = ((Repository)getCountrySpecificComponent(uk, us)).findAll(); 

Ich weiß, das ist ein eher selten Verwendung Fall aber gibt es einen Grund für diese Änderung? Oder eine Möglichkeit, dem Compiler ein wenig "schlauer" zu sagen?

+0

Was ist der Zweck des 'T' -Typs? Können Sie diesen generischen Parameter eliminieren und haben 'UK' und' US' das 'Repository' erweitert? Ich denke, das ist die Wurzel des Problems - der Compiler kann nicht wissen, dass alles, was Sie an "getCountrySpecificComponent()" übergeben, ein 'Repository' ist, es sei denn, Sie sagen es ihm. –

+0

Gute Frage! Ich möchte es für alle Arten von Repositories, Diensten und anderen Dingen verwenden, die länderspezifisch sind. Ich versuche nur, es generischer/benutzbarer zu machen. – skytteren

+0

Ich sehe nicht, wie dies auch in Java 6 hätte kompiliert werden können, wenn nicht eine gefährliche Annahme gemacht wurde ... Warum sollte 'T'' Repository' sein, wenn es genauso einfach 'Object' in dem gegebenen Fall sein kann? – mellamokb

Antwort

3

Ich denke, T sollte begrenzt werden, um Repository zu erweitern. Auf diese Weise weiß der Compiler, dass getCountrySpecificComponent ein Repository zurückgibt.

EDIT:

Es sollte auch in Ordnung sein, zu schreiben: public static <T extends Repository> T getCountrySpecificComponent(T uk, T us)

0

Dann Ich bin damit einverstanden, es war ein Fehler, der alte Compiler, das zu akzeptieren. Ich denke, dass Sie so etwas wie dies wollen:

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); 
    } 
} 
0

In diesem Fall wird der Compiler konnte den Typparameter abzuleiten, was wahrscheinlich der Fall in Java 6 haben sollte auch . Sie können dem Compiler jedoch mitteilen, welche generischen Typen die folgende Syntax verwenden:

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(); 
    } 
}