2012-05-22 23 views
5

En Java 6 que fue capaz de utilizar:cambio compilador de 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 estos repositorios:

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

public interface RepositoryUS extends Repository{} 

public interface RepositoryUK extends Repository{} 

Al utilizar estas:

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

Esta línea compila en en Java6 pero falla en Java7 (el error no puede encontrar el símbolo - a medida que el compilador busca findAll() en la clase Objeto)

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

Esto compila en Java 7

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

Sé que este es un caso de uso poco frecuente, pero hay una razón para este cambio? ¿O una forma de decirle al compilador que sea un poco "más inteligente"?

+0

¿Cuál es el propósito del tipo 'T'? ¿Podría eliminar ese parámetro genérico y hacer que 'UK' y' US' extiendan 'Repository'? Creo que esa es la raíz del problema: el compilador no puede saber que todo lo que pasa a 'getCountrySpecificComponent()' es un 'Repository' a menos que así lo indique. –

+0

¡Buena pregunta! Quiero usarlo para todo tipo de repositorios, servicios y otras cosas que sean específicas del país. Solo estoy tratando de hacerlo más genérico/utilizable. – skytteren

+0

No veo cómo esto podría haberse compilado incluso en Java 6 a menos que se hiciera alguna suposición peligrosa ... ¿Por qué debería 'T' ser' Repositorio', cuando puede ser 'Objeto' en el caso dado? – mellamokb

Respuesta

3

Creo que T debe estar limitado para extender Repository. De esta forma, el compilador sabe que getCountrySpecificComponent devuelve algún repositorio.

EDIT:

También debe ser aceptable para escribir: public static <T extends Repository> T getCountrySpecificComponent(T uk, T us)

0

entonces estoy de acuerdo que era un error para el viejo compilador para aceptar eso. Creo que quieres algo como esto:

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

En este caso, el compilador no pudo inferir los parámetros de tipo, lo que probablemente debería haber sido el caso en Java 6, así . Sin embargo, puede decirle al compilador cuáles son los tipos genéricos, utilizando la siguiente sintaxis:

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