2013-03-07 5 views
7

Jest to metoda w hamcrest biblioteki:Dla metody typu T, jaki powinien być jej typ "wywnioskowany", gdy przyjmuje dwa argumenty: <? 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); 
} 

W moim kodu, wzywam tę metodę z first będąc Matcher<Object> i second będąc Matcher<SomeException>.

A teraz:

  • Kiedy skompilować go z Eclipse 1,6 cel, to sprawia <T>Matcher<SomeException>.
  • Kiedy kompiluję go z javac 1.7 z celem 1.6, robi on <T>Matcher<SomeException>.
  • Kiedy go skompilować z javac 1,6 z 1,6 cel, to sprawia <T>Matcher<Object>

Pytanie brzmi, co <T> powinny być w takim przypadku?

Rozumiem, że jest błąd w javac 1.6 i powinien on być Matcher<SomeException>, ponieważ jest to typowy typ dla argumentów wejściowych (SomeException jest podtypem Object), a następnie jest w 100% pewny, że powrócił Matcher będzie Matcher<SomeException>.

Mam rację? Czy istnieje sposób, aby zmusić javac 1.6 do właściwego zachowania?

Odpowiedz

3

Kompilator wykona numer inference based on actual arguments. Rozpocznie się od początkowych ograniczeń Matcher<Object> << Matcher<? super T> i Matcher<SomeException> << Matcher<? super T>. Z tego wywnioskuje ograniczenia T << Object i . Object zostanie wyeliminowany po zbudowaniu minimal erased candidate set. Pozostały kandydat SomeException będzie (ostatecznie: D) zastąpiony przez T.

Do tej pory pokazaliśmy zaćmienie, a JDK7 zachowuje się w tym przypadku poprawnie. Nie sądzę, że istnieje sposób, aby zmusić javac do prawidłowego zachowania się. Możesz jawnie podać argument typu lub użyć JDK7 (określając źródło i cel na 6).

1

Są dwie rzeczy, które należy rozważyć:

  1. pierwsze można go używać tak: CoreMatcher.<SomeException>allOf(...) które jawnie ustawić T.

  2. Po drugie, ze względu na usuwanie typu, w czasie wykonywania ZAWSZE masz Matcher<Object>. Tak więc w obu przypadkach zachowanie w czasie działania jest takie samo.

+0

Dobry połów z CoreMatcherem, ale CoreMatchers w moim hamcrest :) Odnośnie drugiego punktu - Wiem. Udało mi się skompilować z zaćmieniem i uruchomić test mvn. – Marcin