2012-05-22 12 views
5

In Java 6 sono stato in grado di utilizzare:Compiler cambiamento 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); 
    } 
} 

Con questi repository:

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

public interface RepositoryUS extends Repository{} 

public interface RepositoryUK extends Repository{} 

Quando si utilizzano questi:

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

Questa linea viene compilato in in Java6 ma non riesce in Java7 (l'errore non può trovare il simbolo - mentre il compilatore cerca findAll() sull'oggetto classe)

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

Questo compila in Java 7

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

So che questo è un caso d'uso piuttosto raro, ma c'è un motivo per questo cambiamento? O un modo per dire al compilatore di essere un po '"più intelligente"?

+0

Qual è lo scopo del tipo "T"? Potresti eliminare quel parametro generico e avere 'UK' e' US' estendere 'Repository'? Penso che sia la radice del problema - il compilatore non può sapere che tutto ciò che si passa a 'getCountrySpecificComponent()' è un 'Repository' a meno che non lo dica. –

+0

Buona domanda! Voglio usarlo per tutti i tipi di repository, servizi e altre cose specifiche per Paese. Sto solo cercando di renderlo più generico/utilizzabile. – skytteren

+0

Non vedo come questo potrebbe essere compilato anche in Java 6 a meno che non sia stata fatta un'assunzione pericolosa ... Perché dovremmo 'T' essere' Repository', quando può essere altrettanto facilmente 'Object' nel caso dato? – mellamokb

risposta

3

Penso che T dovrebbe essere limitato per estendere Repository. In questo modo il compilatore sa che getCountrySpecificComponent restituisce qualche repository.

EDIT:

Dovrebbe anche essere ok a scrivere: public static <T extends Repository> T getCountrySpecificComponent(T uk, T us)

0

allora sono d'accordo che era un errore per il vecchio compilatore di accettare che. Penso che si desidera qualcosa di simile:

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 questo caso il compilatore era in grado di dedurre i parametri di tipo, che probabilmente avrebbe dovuto essere il caso in Java 6 e . Puoi dire al compilatore quali sono i tipi generici, usando la seguente sintassi:

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