2013-03-07 5 views
7

c'è un metodo nella hamcrest libreria:Per il metodo di tipo T, quale dovrebbe essere il tipo "inferito" quando sono necessari due argomenti <? super T>?

package org.hamcrest.core 

... 

public static <T> Matcher<T> allOf(Matcher<? super T> first, Matcher<? super T> second) { 
    List<Matcher<? super T>> matchers = new ArrayList<Matcher<? super T>>(2); 
    matchers.add(first); 
    matchers.add(second); 
    return allOf(matchers); 
} 

Nel mio codice, io chiamo questo metodo con first essere Matcher<Object> e second essere Matcher<SomeException>.

E ora:

  • Quando compilo con Eclipse con 1.6 di destinazione, fa <T>Matcher<SomeException>.
  • Quando lo compilo con javac 1.7 con 1.6 target, rende <T>Matcher<SomeException>.
  • Quando compilo con javac 1.6 con 1.6 di destinazione, rende <T>Matcher<Object>

La domanda è: cosa <T> dovrebbe essere in tal caso?

La mia comprensione è che c'è un bug in javac 1.6 e dovrebbe essere Matcher<SomeException>, in quanto questo è un tipo comune di argomenti di input (SomeException è un sottotipo di Object) e poi, è sicuro al 100%, che ha restituito Il matcher sarà Matcher<SomeException>.

Ho ragione? E c'è un modo per forzare javac 1.6 a comportarsi correttamente?

risposta

3

Il compilatore farà un inference based on actual arguments. Inizia con i vincoli iniziali di Matcher<Object> << Matcher<? super T> e Matcher<SomeException> << Matcher<? super T>. Da ciò verranno dedotti i vincoli T << Object e T << SomeException. Object verrà eliminato quando viene costruito lo minimal erased candidate set. Il candidato rimanente SomeException sostituirà (eventualmente: D) T.

Finora abbiamo mostrato che eclipse e JDK7 si comportano correttamente in questo caso. Non penso che ci sia un modo per forzare il javac a comportarsi correttamente. Puoi specificare esplicitamente l'argomento type o usare JDK7 (specificando source e target come 6).

1

Ci sono due cose che si dovrebbero prendere in considerazione:

  1. In primo luogo si potrebbe usare in questo modo: CoreMatcher.<SomeException>allOf(...) che avrebbe impostato in modo esplicito T.

  2. In secondo luogo, a causa della cancellazione del tipo, come run-time hai SEMPRE un Matcher<Object>. Quindi, in entrambi i casi, il comportamento in fase di esecuzione è lo stesso.

+0

Buona cattura con CoreMatcher, ma è CoreMatchers nel mio hamcrest :) Per quanto riguarda il 2 ° punto - Lo so. Sono stato in grado di compilare con eclipse ed eseguire quindi il test mvn. – Marcin

Problemi correlati