Jaki jest sens operatora diamond w Javie 7?

Operator diamond w Javie 7 pozwala na kod w następujący sposób:

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

Jednak w Javie 5/6 mogę po prostu napisać:

List<String> list = new LinkedList();

Moje rozumienie wymazywania typu jest to, że są one dokładnie takie same. (Generic zostanie usunięty w czasie działania).

Po co w ogóle przejmować się diamentem? Jakie nowe Funkcje / bezpieczeństwo typu pozwala? Jeśli nie daje żadnej nowej funkcjonalności, dlaczego wymieniają ją jako funkcję? Czy moje rozumienie tego pojęcia jest błędne?
Author: ROMANIA_engineer, 2010-11-12

7 answers

Problem z

List<String> list = new LinkedList();

Jest to, że po lewej stronie używasz typu generic List<String> gdzie po prawej stronie używasz typu raw LinkedList. Typy surowe w Javie istnieją tylko dla zgodności z kodem przed-generycznym i nigdy nie powinny być używane w nowym kodzie, chyba że absolutnie musisz.

Teraz, jeśli Java miała generyki od początku i nie miała typów, takich jak LinkedList, które zostały pierwotnie stworzone zanim miała generyki, to prawdopodobnie mogło to spowodować, że konstruktor dla typu generycznego automatycznie wywnioskuje jego parametry z lewej strony przypisania, jeśli to możliwe. Ale tak się nie stało i musi traktować typy surowe i typy generyczne inaczej, aby uzyskać kompatybilność wsteczną. Oznacza to, że muszą stworzyć nieco inny , ale równie wygodny sposób deklarowania nowej instancji obiektu ogólnego bez konieczności powtarzania jego parametrów typu... operator diamentów.

Jako tak jak w oryginalnym przykładzie List<String> list = new LinkedList(), kompilator generuje ostrzeżenie dla tego przydziału, ponieważ musi. Rozważ to:

List<String> strings = ... // some list that contains some strings

// Totally legal since you used the raw type and lost all type checking!
List<Integer> integers = new LinkedList(strings);

Generyczne istnieją, aby zapewnić ochronę w czasie kompilacji przed zrobieniem złej rzeczy. W powyższym przykładzie, użycie typu raw oznacza, że nie uzyskasz tej ochrony i pojawi się błąd podczas wykonywania. Dlatego nie należy używać typów surowych.

// Not legal since the right side is actually generic!
List<Integer> integers = new LinkedList<>(strings);

Operator diamentowy pozwala jednak na zdefiniowanie prawej strony przypisania jako true ogólna instancja z tymi samymi parametrami typu co lewa strona... bez konieczności wpisywania tych parametrów ponownie. Pozwala zachować bezpieczeństwo leków generycznych przy prawie takim samym wysiłku, jak przy użyciu typu surowego.

Myślę, że kluczową rzeczą do zrozumienia jest to, że typy surowe (bez <>) nie mogą być traktowane tak samo jak typy generyczne. Kiedy deklarujesz surowy Typ, nie masz żadnych korzyści i sprawdzania typów generycznych. Należy również pamiętać, że leki generyczne są część ogólnego przeznaczenia języka Java ... nie dotyczą tylko konstruktorów no-arg Collection s!

 457
Author: ColinD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-12 18:01:27

Twoje zrozumienie jest nieco błędne. Operator diamond jest miłą funkcją, ponieważ nie musisz się powtarzać. To ma sens, aby zdefiniować typ raz podczas deklarowania typu, ale po prostu nie ma sensu, aby zdefiniować go ponownie po prawej stronie. Zasada suchości.

Teraz wyjaśnię wszystkie fuzz o definiowaniu typów. Masz rację, że typ jest usuwany w czasie wykonywania, ale gdy chcesz odzyskać coś z listy z definicją typu, odzyskujesz go jako typ, który masz zdefiniowany podczas deklarowania listy, w przeciwnym razie utraci wszystkie specyficzne cechy i będzie miał tylko cechy obiektu, z wyjątkiem sytuacji, gdy oddasz pobrany obiekt do oryginalnego typu, co może być czasami bardzo trudne i skutkować odstępem ClassCastException.

Użycie List<String> list = new LinkedList() spowoduje wyświetlenie ostrzeżeń rawtype.

 33
Author: Octavian Damiean,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-12 16:52:25

Ta linia powoduje Ostrzeżenie [niezaznaczone]:

List<String> list = new LinkedList();

Zmienia się więc pytanie: dlaczego Ostrzeżenie [niezaznaczone] nie jest automatycznie tłumione tylko w przypadku utworzenia nowej kolekcji?

Myślę, że byłoby to znacznie trudniejsze zadanie niż dodanie <> funkcji.

UPD: myślę również, że byłby bałagan, gdyby legalnie można było używać typów raw "tylko dla kilku rzeczy".

 15
Author: Roman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-12 17:02:48

W teorii operator diamond umożliwia pisanie bardziej zwartego (i czytelnego) kodu poprzez zapisywanie powtarzających się argumentów typu. W praktyce, to tylko dwa mylące znaki więcej daje nic. Dlaczego?

  1. żaden rozsądny programista nie używa typów surowych w nowym kodzie. Więc kompilator może po prostu założyć, że pisząc żadne argumenty typu, chcesz, aby wywnioskował je.
  2. operator diamond nie podaje informacji o typie, po prostu mówi kompilatorowi: "będzie dobrze". Więc pomijając to możesz nie krzywda. W każdym miejscu, gdzie operator diamond jest legalny, może być "wywnioskowany" przez kompilator.

IMHO, posiadanie jasnego i prostego sposobu na oznaczenie Źródła jako Java 7 byłoby bardziej przydatne niż wymyślanie takich dziwnych rzeczy. W tak oznaczonym kodzie surowe typy mogą być zakazane bez utraty czegokolwiek.

Btw., Nie sądzę, że powinno się to robić za pomocą przełącznika kompilacji. Wersja Java pliku programu jest atrybutem pliku, nie ma żadnej opcji. Używanie czegoś tak trywialnego as

package 7 com.example;

Może to wyjaśnić(możesz preferować coś bardziej wyrafinowanego, w tym jedno lub więcej fantazyjnych słów kluczowych). Umożliwiłoby to nawet kompilowanie źródeł napisanych dla różnych wersji Javy bez żadnych problemów. Pozwoli to na wprowadzenie nowych słów kluczowych (np." module") lub porzucenie przestarzałych funkcji (wiele niepublicznych, nie zagnieżdżonych klas w jednym pliku lub w ogóle) bez utraty kompatybilności.

 14
Author: maaartinus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-19 11:37:00

Kiedy piszesz List<String> list = new LinkedList();, kompilator wyświetla ostrzeżenie "niezaznaczone". Możesz go zignorować, ale jeśli zignorowałeś te ostrzeżenia, możesz również przegapić Ostrzeżenie, które powiadomi Cię o prawdziwym problemie bezpieczeństwa typu.

Więc lepiej napisać kod, który nie generuje dodatkowych ostrzeżeń, a operator diamond pozwala zrobić to w wygodny sposób bez zbędnych powtórzeń.

 7
Author: axtavt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-12 16:53:57

Wszystkie wymienione w innych odpowiedziach są poprawne, ale przypadki użycia nie są całkowicie poprawne IMHO. Jeśli ktoś sprawdza Guava , a zwłaszcza rzeczy związane ze zbiorami, to samo zostało zrobione metodami statycznymi. Np. listy.newArrayList () która pozwala na zapisanie

List<String> names = Lists.newArrayList();

Lub z importem statycznym

import static com.google.common.collect.Lists.*;
...
List<String> names = newArrayList();
List<String> names = newArrayList("one", "two", "three");

Guava ma inne bardzo potężne funkcje, takie jak ta i właściwie nie mogę wymyślić zbyt wielu zastosowań dla.

[[2]}byłoby bardziej przydatne, gdyby poszli aby uczynić zachowanie operatora diamond domyślnym, to znaczy, że typ jest wyprowadzany z lewej strony wyrażenia lub jeśli Typ lewej strony został wyprowadzony z prawej strony. To ostatnie dzieje się w Scali.
 4
Author: allprog,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-04 11:29:32

Punktem dla operatora diamond jest po prostu ograniczenie wpisywania kodu przy deklarowaniu typów generycznych. Nie ma żadnego wpływu na środowisko wykonawcze.

Jedyna różnica jeśli podasz w Javie 5 i 6,

List<String> list = new ArrayList();

Jest to, że musisz określić @SuppressWarnings("unchecked") do list (w przeciwnym razie otrzymasz niezaznaczone ostrzeżenie o obsadzie). Rozumiem, że operator diamond stara się ułatwić rozwój. To nie ma nic wspólnego z wykonywaniem generyków.

 3
Author: Buhake Sindi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-12 16:57:14