2012-06-08 41 views
6

que he escrito un método de utilidad en Java:java6, guayaba, genéricos, la inferencia de tipos

public static final ImmutableSortedSet<TimeUnit> REVERSED_TIMEUNITS = ImmutableSortedSet.copyOf(
     Collections.<TimeUnit>reverseOrder(), 
     EnumSet.allOf(TimeUnit.class) 
); 


/** 
* Get the number of ..., minutes, seconds and milliseconds 
* 
* You can specify a max unit so that you don't get days for exemple 
* and can get more than 24 hours if you want to display the result in hours 
* 
* The lowest unit is milliseconds 
* @param millies 
* @param maxTimeUnit 
* @return the result map with the higher unit first 
*/ 
public static Map<TimeUnit,Long> getCascadingDateDiff(long millies,TimeUnit maxTimeUnit) { 
    if (maxTimeUnit == null) { 
     maxTimeUnit = TimeUnit.DAYS; 
    } 
    Map<TimeUnit,Long> map = new TreeMap<TimeUnit,Long>(Collections.<TimeUnit>reverseOrder()); 
    long restInMillies = millies; 
    Iterable<TimeUnit> forUnits = REVERSED_TIMEUNITS.subSet(maxTimeUnit,TimeUnit.MICROSECONDS); // micros not included 
    // compute the number of days, then number of hours, then minutes... 
    for (TimeUnit timeUnit : forUnits) { 
     long numberForUnit = timeUnit.convert(restInMillies,TimeUnit.MILLISECONDS); 
     map.put(timeUnit,numberForUnit); 
     restInMillies = restInMillies - timeUnit.toMillis(numberForUnit); 
    } 
    return map; 
} 

Funciona con:

Map<TimeUnit,Long> map = new TreeMap<TimeUnit,Long>(Collections.reverseOrder()); 

Pero probé por primera vez con

Map<TimeUnit,Long> map = Maps.newTreeMap(Collections.reverseOrder()); 

Mi IntelliJ no dice nada, mientras mi compilador dice:

DateUtils.java:[302,48] tipos incompatibles; no hay instancia (s) de tipo variable (s) K, V existen para que java.util.TreeMap se conforme con java.util.Map [ERROR] encontrado: java.util.TreeMap [ERROR] requerido: java. util.Map

funciona bien sin el comparador:

Map<TimeUnit,Long> map = Maps.newTreeMap(); 

Pero me trató con:

Map<TimeUnit,Long> map = Maps.newTreeMap(Collections.<TimeUnit>reverseOrder()); 

Y con:

Map<TimeUnit,Long> map = Maps.newTreeMap(new Comparator<TimeUnit>() { 
    @Override 
    public int compare(TimeUnit timeUnit, TimeUnit timeUnit1) { 
     return 0; 
    } 
}); 

Y tengo el mismo error. Parece que cada vez que uso un comparador en TreeMap, la inferencia de tipo ya no funciona. ¿Por qué?


La firma del método guayaba es:

public static <C, K extends C, V> TreeMap<K, V> newTreeMap(Comparator<C> comparator) 

El tipo de retorno esperada es de tipo así que sin un comparador, Java es capaz de inferir que K = TimeUnit y V = largo.

Con un comparador de tipo TimeUnit, Java sabe que C es TimeUnit. También sabe que el tipo de retorno esperado es de tipo, por lo que K = TimeUnit y V = Long. K extends C se respeta ya que TimeUnit extiende TimeUnit (de todos modos lo intenté también con un comparador de objetos si crees que es incorrecto ...)

Así que me pregunto por qué la inferencia de tipo no funciona en este caso?

+0

de mayo su problema estar relacionado con este tema? http://code.google.com/p/guava-libraries/issues/detail?id=635 –

+0

Sí, podría ser, ya que estoy usando OpenJDK. –

+0

básicamente lo mismo que su pregunta [aquí] (http://stackoverflow.com/questions/10945616/whats-this-generics-usage-in-java), use la forma específica Maps. newTreeMap (...). – kutschkem

Respuesta

7

Al igual que Michael Laffargue sugiere, se trata de un error de tipo OpenJDK6 inferencia:

https://bugs.openjdk.java.net/show_bug.cgi?id=100167

http://code.google.com/p/guava-libraries/issues/detail?id=635

Funciona bien en mi IntelliJ, y con un OpenJDK en la versión 7, y con los demás JDK en la versión 6.


La siguiente sugerencia de kutschkem funciona:

Map<TimeUnit,Long> map = Maps.<TimeUnit,TimeUnit,Long>newTreeMap(Collections.<TimeUnit>reverseOrder()); 

Aviso del <TimeUnit,TimeUnit,Long> que permite forzar los parámetros escritos de manera explícita. Comprobar este tema relacionado: What's this generics usage in Java? X.<Y>method()

Gracias a todos

+0

El enlace de openjdk anterior ya no funciona, pero creo que https: //bugs.openjdk.java.net/browse/JDK-6569074 es lo mismo o similar. – andrewdotn