Jaka jest różnica między "E", " T "i"? dla Java generics?
Natknąłem się na kod Javy tak:
public interface Foo<E> {}
public interface Bar<T> {}
public interface Zar<?> {}
Jaka jest różnica pomiędzy wszystkimi trzema powyższymi i jak nazywają tego typu deklaracje klas lub interfejsów w Javie?
6 answers
Cóż, nie ma różnicy między dwoma pierwszymi - używają tylko różnych nazw dla parametru typu (E
LUB T
).
Trzecia nie jest poprawną deklaracją - ?
jest używana jakosymbol wieloznaczny , który jest używany podczas podawania argumentu type , np. List<?> foo = ...
oznacza, że foo
odnosi się do listy jakiegoś typu, ale nie wiemy co.
Wszystko to jest generyki , co jest dość dużym tematem. Możesz chcieć dowiedzieć się o tym poprzez następujące zasoby, choć oczywiście jest ich więcej:
- Java Tutorial on Generics
- Przewodnik językowy po generykach
- Generics in the Java programming language [[20]}Angelika Langer ' s Java Generics FAQ (obszerny i obszerny; więcej w celach informacyjnych)
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
2017-05-30 17:03:52
To bardziej konwencja niż cokolwiek innego.
-
T
ma być typem -
E
ma być elementem (List<E>
: Lista elementów) -
K
jest kluczem (wMap<K,V>
) -
V
jest wartością (jako wartość zwracaną lub mapowaną)
Są w pełni wymienne (niezależnie od konfliktów w tej samej deklaracji).
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
2015-11-09 14:29:39
Poprzednie odpowiedzi wyjaśniają parametry typu (T, E, itd.), ale nie Tłumacz dziką kartą"?", lub różnice między nimi, więc zajmę się tym.
Po pierwsze, żeby było jasne: symbole wieloznaczne i parametry typu nie są takie same. Tam, gdzie parametry typu definiują rodzaj zmiennej (np. T), która reprezentuje typ dla zakresu, symbol wieloznaczny tego nie robi: symbol wieloznaczny definiuje tylko zbiór dozwolonych typów, których można użyć dla typu ogólnego. Bez ograniczeń (extends
lub super
), wildcard oznacza "użyj dowolnego typu tutaj".
Symbole wieloznaczne zawsze znajdują się między nawiasami kątowymi i mają znaczenie tylko w kontekście typu ogólnego:
public void foo(List<?> listOfAnyType) {...} // pass a List of any type
Nigdy
public <?> ? bar(? someType) {...} // error. Must use type params here
Lub
public class MyGeneric ? { // error
public ? getFoo() { ... } // error
...
}
Tam, gdzie się pokrywają, robi się coraz bardziej mylące. Na przykład:
List<T> fooList; // A list which will be of type T, when T is chosen.
// Requires T was defined above in this scope
List<?> barList; // A list of some type, decided elsewhere. You can do
// this anywhere, no T required.
Istnieje wiele nakładania się tego, co jest możliwe z definicjami metod. Następujące są funkcjonalnie identyczne:
public <T> void foo(List<T> listOfT) {...}
public void bar(List<?> listOfSomething) {...}
Więc, jeśli istnieje nakładanie się, po co używać jednego lub drugiego? Czasami, szczerze mówiąc, to tylko styl: niektórzy mówią, że jeśli nie potrzebujesz param typu, powinieneś użyć symbolu wieloznacznego, aby Kod był prostszy/bardziej czytelny. Jedna główna różnica, którą wyjaśniłem powyżej: params typu definiuje zmienną typu (np. T), której można użyć gdzie indziej w zakresie; wildcard Nie. w przeciwnym razie istnieją dwie duże różnice między params typu a wildcard: {]}
Params typu może mieć wiele klas obwiedni; symbol wieloznaczny nie może:
public class Foo <T extends Comparable<T> & Cloneable> {...}
The symbole wieloznaczne mogą mieć niższe granice; params typu nie może:
public void bar(List<? super Integer> list) {...}
W powyższym List<? super Integer>
definiuje Integer
jako dolną granicę na symbolu wieloznacznym, co oznacza, że typ listy musi być liczbą całkowitą lub super-typem liczby całkowitej. Rodzajowe ograniczanie jest poza tym, co chcę szczegółowo omówić. Krótko mówiąc, pozwala zdefiniować jakie typy może być typem generycznym. Dzięki temu możliwe jest polimorficzne leczenie leków generycznych. Np. z:
public void foo(List<? extends Number> numbers) {...}
Możesz zdać List<Integer>
, List<Float>
, List<Byte>
, itd. dla numbers
. Bez ograniczania typów to nie zadziała . takie są generyki.
Na koniec, oto definicja metody, która używa wieloznacznych znaków, aby zrobić coś, czego nie możesz zrobić w inny sposób: {]}
public static <T extends Number> void adder(T elem, List<? super Number> numberSuper) {
numberSuper.add(elem);
}
numberSuper
Może być listą liczby lub dowolnym supertyp liczby (np. List<Object>
), a elem
musi być liczbą lub dowolnym podtypem. Przy wszystkich obwiedniach kompilator może być pewien, że {[20] } jest typesafe.
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
2016-10-13 20:37:54
Zmienna typu,
Najczęściej używane nazwy parametrów typu to:
- E-Element (szeroko stosowany przez framework zbiorów Javy)
- K - Key
- N-Liczba
- T - Type
- V - Wartość
W Javie 7 dozwolone jest tworzenie instancji w następujący sposób:
Foo<String, Integer> foo = new Foo<>(); // Java 7
Foo<String, Integer> foo = new Foo<String, Integer>(); // Java 6
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
2017-09-29 22:30:21
Najczęściej używane nazwy parametrów typu to:
E - Element (used extensively by the Java Collections Framework)
K - Key
N - Number
T - Type
V - Value
S,U,V etc. - 2nd, 3rd, 4th types
Zobaczysz te nazwy używane w API Java SE
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
2019-05-17 16:03:09
Kompilator wykona przechwytywanie dla każdego znaku wieloznacznego (np. znak zapytania na liście), gdy tworzy funkcję taką jak:
foo(List<?> list) {
list.put(list.get()) // ERROR: capture and Object are not identical type.
}
Jednak Typ generyczny, taki jak V, byłby w porządku i czyniłby go metodą generyczną :
<V>void foo(List<V> list) {
list.put(list.get())
}
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
2018-04-27 06:58:28