2017-09-04 20 views
7

Rozważ następujące dwa zestawy metod. Pierwszy jest akceptowany, drugi odrzucany jako niejednoznaczny. Jedyna różnica polega na użyciu int i Integer.Niejednoznaczne metody varargs z obiektem i typem pierwotnym

Czy istnieje szczególna potrzeba odrzucenia drugiej? Oznaczałoby to, że zaakceptowanie go po boksie (które doprowadziło do pierwszego zestawu) ma problem. Czego tu brakuje?

Z mojego punktu widzenia, kompilator Java jest tutaj zbyt restrictve.

Zestaw 1:

public void test(Object... values) {} 

public void test(Integer x, Object... values) {} // difference here 

public void b() { 
    test(1, "y"); // accepted 
} 

Set 2:

public void test(Object... values) {} 

public void test(int x, Object... values) {} // difference here 

public void b() { 
    test(1, "y"); // marked as ambiguous 
} 

Set 2 daje błąd kompilatora:

error: reference to test is ambiguous 
    test(1, "y"); // marked as ambiguous 
    ^
    both method test(Object...) in T and method test(int,Object...) in T match 

Java 1.8, Eclipse Oxygen

+0

Metod z Zestawu 1 i Zestawu 2 należą do tej samej klasy? –

+1

@RafaelVieiraCoelho Oczywiście, że nie. – Kayaman

+0

tej samej klasy. Właśnie edytuję klasę, aby zmienić między nimi. –

Odpowiedz

1

Różnica polega że w pierwszym przypadku t argument musi być zapakowany w liczbę całkowitą, a następnie wybrana najbardziej odpowiednia metoda; to jest wersja (Integer, Object...).

W drugim przypadku dostępne są dwie opcje - boks lub nie. Właśnie to czyni ją niejednoznaczną.

Zgadzam się, że jest to sprzeczne z intuicją.

+0

Zgadzam się, kompilator poprawnie implementuje specyfikację. Chodzi mi o to, że kompilator Javy mógł łatwo znieść to ograniczenie w czasie kompilacji: nie ma potrzeby kompleksowej analizy. Specyfikacja jest zbyt restrykcyjna –

5

To, co robi kompilator, to wdrażanie reguł określonych w JLS 15.12.2.5 w celu wybrania najbardziej szczegółowej metody w przypadkach, w których do wywołania stosuje się wiele metod. W przykładach w swoim pytaniu, różnica jest objęty tą linią w spec:

A type S is more specific than a type T for any expression if S <: T (§4.10).

gdzie S <: T oznacza, że ​​S jest podtypem T.

W przykładzie # 1:

  • Istnieją dwa sposoby stosowane
  • TYPE Integer jest podtypem Object, więc bardziej szczegółowy.
  • Dlatego druga metoda jest bardziej szczegółowa niż pierwsza.
  • Dlatego wybrana jest druga metoda.

W przykładzie # 2:

  • Istnieją dwa sposoby stosowane
  • TYPE int nie jest podtypem Object lub vice versa, tak ani typu jest bardziej szczegółowy niż drugi.
  • Dlatego żadna z metod nie jest bardziej konkretna od drugiej.
  • Dlatego wywołanie jest niejednoznaczne.
0

Aby zamknąć ten problem, proszę podsumować rzeczywiste odpowiedzi na moje pytanie, tak jak je rozumiem: zachowanie jest poprawne zgodnie ze specyfikacją. Specyfikację można złagodzić tak, że typy pierwotne są traktowane jako ich odpowiedniki nieprecyzyjne. Jednym z powodów, który nie został jeszcze zakończony, jest złożoność określania i implementowania szybkiego i poprawnego analizatora składni.

Powiązane problemy