2013-02-16 21 views
12

List<String> list = new ArrayList(); spowoduje ostrzeżenie kompilatora.Dlaczego operator diamentów jest używany do wnioskowania typu w Java 7?

jednak następujący przykład kompiluje bez ostrzeżenia: List<String> list = new ArrayList<>();

Jestem ciekaw dlaczego wprowadzenie wykonawcy diament jest w ogóle potrzebne. Dlaczego po prostu nie mają typu wnioskowanie na konstruktora jeśli typ argumentu jest nieobecny (jak sama już zrobione dla metody statyczne w Javie i eksploatowane przez biblioteki zbiórki takich jak Google guawa)

EDIT: Korzystanie odpowiedź millimoose jako punkt wyjścia Spojrzałem jaki typ jest w rzeczywistości wymazaniem, a nie tylko usunięcie wszystkich informacji o typie. Kompilator faktycznie robi nieco więcej (skopiowane z official doc):

  • Wymień wszystkie parametry typu typów generycznych z ich granicach lub obiektu, jeśli parametry typu są nieograniczone. Powstały kod bajtowy zawiera zatem tylko zwykłe klasy, interfejsy i metody.
  • Wstawić odlewy w razie potrzeby, aby zachować bezpieczeństwo typu.
  • Generowanie metod mostkowania w celu zachowania polimorfizmu w rozszerzonych typach ogólnych.
+7

Ja zakładając, że rozróżnienie to z użyciem surowych rodzajów, które sprawiają, że kompilator coś zrobić całkowicie odmienne ze względu na kompatybilność. (Wyrażenie z surowym typem jest przetwarzane inaczej niż w przypadku generycznych.) – millimoose

+0

Prawdopodobnie zgodziłbym się z millimoose, ale biorąc pod uwagę, że generics są usuwane podczas wykonywania przez środowisko wykonawcze, wprowadzając nowego operatora ('tylko') dla wstecznej kompatybilności ostrzeżenia kompilatora nie czuje się dobrze. –

+0

Kompatybilność wsteczna nie jest ze względu na ostrzeżenia kompilatora. Wyrażenie takie jak 'Object s = new ArrayList(). Get()' ma typ wyniku po stronie prawej, rozwiązany inaczej (przy użyciu algorytmu pre-generics) niż wypowiedź 'String s = new ArrayList () .get() '. Dotyczy to również zapisu 'ArrayList' w zmiennej pośredniej. – millimoose

Odpowiedz

8

Ostateczna odpowiedź musiałaby pochodzić od kogoś, kto zaprojektował tę funkcję, ale zakładam, że odróżnia to od używania typów surowych, co powoduje, że kompilator robi coś zupełnie innego ze względu na kompatybilność. Wyrażenie z surowca typu w niej przetworzony subtelnie inaczej, niż taki, który rodzajowych, przykład znajduje się w tym SO pytania: Generic screws up non-related collection

+0

+1 za podanie przykładu różnicy między rodzajami generycznymi i surowymi –

+0

@PhilippWendler Posiadanie tego pytania w niedawnej pamięci jest tak naprawdę tym, co doprowadziło mnie do tej odpowiedzi, więc część kredytu trafia również do jego autora. – millimoose

3

Jest to część ulepszenie Java Generics w Javie 7.
Przed byś musiał napisać

final List<String> list = new ArrayList<String>(); 

teraz można napisać

final List<String> list = new ArrayList<>(); 

co jest równoważne - w kompilator to rozwiąże. To nie jest taka sama jak

final List list = new ArrayList(); 

który jest bez typu List.

7

Programiści Javy bardzo się starają, aby nie zmieniać zachowania istniejących programów. List<String> list = new ArrayList(); dokonuje kompilacji i tworzy surową ArrayList. Jeśli zastosowano do niego wnioskowanie typu, wynikiem będzie ArrayList<String>, zmieniając jego zachowanie i prawdopodobnie powodując błędy czasu wykonywania w innym miejscu w programie.

============================================== ==============================

Po dalszych rozważań i komentarz przez @millimoose, widzę, że zmiany w zachowaniu będzie lokalne dla inicjalizatora i wykryte podczas kompilacji. Rozważmy następujący program:

import java.util.ArrayList; 
import java.util.List; 


public class Test { 
    public static void main(String[] args) throws Exception { 
    List<Integer> integers = new ArrayList<Integer>(); 
    integers.add(Integer.valueOf(3)); 
    integers.add(Integer.valueOf(4)); 
    List<String> list = new ArrayList(integers); 
    System.out.println(list); 
    } 
} 

Bez typu wnioskowania, że ​​działa i drukuje [3, 4] pomimo niepożądanej sytuacji z List<String> który zawiera odwołania całkowitą.

z rodzajem wnioskowania, że ​​nie będzie kompilować, ponieważ ArrayList(Collection<? extends E> c) nie zezwala na korzystanie z List<Integer> jako argumentu przy tworzeniu ArrayList<String>.

+0

@millimoose Po przemyśleniu tego więcej, zgadzam się. Zmiany w zachowaniu będą lokalne dla inicjalizatora i wykryte podczas kompilacji. Będę edytować moją odpowiedź, aby pokazać przykład. –

4

Pełna składnia wymagane przez kompilator Java 5 i 6 jest:

List<String> list = new ArrayList<String>();

Postanowili uprościć składnię dla nas i pozwolić, aby nie pisać te same parametry typu po obu stronach operatora przypisania. Jednak operator <> jest nadal wymagany, aby upewnić się, że rozumiesz, co robisz. Pisząc new ArrayList<>() mówisz "Rozumiem, że tworzę wystąpienie typu ogólnego, a parametr ogólny jest taki, jaki zadeklarowałem po lewej stronie przypisania."

1

Interesującymi przypadków jest, gdy wywołanie konstruktora z diamentu i jako rawtype z powodzeniem kompiluje, ale produkuje inny kod. Takie przykłady są możliwe po zmieszaniu z funkcją przeciążania metody. IIRC, był taki przykład gdzieś na liście mailingowej OpenJDK na monety (nie, nie będę próbował go znaleźć).

Niedopuszczalne było, aby dokładnie ten sam kod powiodło się na Java SE 6 i Java SE 7, ale przyniosły różne wyniki.

Dla moich pieniędzy, pomijałbym diament i otrzymywałam ostrzeżenie (potraktować jako błąd), gdyby inny kod został wygenerowany przez algorytm wnioskowania wybrany w 7 (zasadniczo taki sam jak w przypadku metody typu ogólnego wnioskowania z J2SE 5.0). Jeśli napisałeś taki kod, prawdopodobnie nie jest oczywiste, czy uda się go skompilować, czy nie.

0

Jeśli twój projekt jest zbudowany na maven, dodaj poniżej w pom.xml pod tagiem. To działa doskonale .. <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins>