Dlaczego Java Generics nie obsługuje typów prymitywnych?

Dlaczego generyki w Javie działają z klasami, ale nie z typami prymitywnymi?

Na przykład to działa dobrze:

List<Integer> foo = new ArrayList<Integer>();

Ale to nie jest dozwolone:

List<int> bar = new ArrayList<int>();
Author: Michael, 2010-04-27

6 answers

Generyki w Javie są konstrukcją całkowicie skompilowaną - kompilator zamienia wszystkie generyczne zastosowania w odpowiedni typ. Ma to na celu zachowanie kompatybilności wstecznej z poprzednimi środowiskami uruchomieniowymi JVM.

To:

List<ClassA> list = new ArrayList<ClassA>();
list.add(new ClassA());
ClassA a = list.get(0);

Zostaje zamienione na (mniej więcej):

List list = new ArrayList();
list.add(new ClassA());
ClassA a = (ClassA)list.get(0);

Więc wszystko, co jest używane jako generyki, musi być konwertowalne do obiektu (w tym przykładzie get(0) zwraca Object), A typy prymitywne nie są. więc nie mogą być używane w generykach.

 251
Author: thecoop,
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-12-18 11:48:53

W Javie generyki działają tak, jak działają ... przynajmniej częściowo ... ponieważ zostały one dodane do języka kilka lat po tym, jak język został zaprojektowany1. Projektanci języka byli ograniczeni w swoich opcjach dla generyków, ponieważ musieli wymyślić projekt, który był wstecznie kompatybilny z istniejącym językiem i biblioteką klas Java .

Inne języki programowania (np. C++, C#, Ada) pozwalają na użycie prymitywnych typów jako parametru rodzaje dla leków generycznych. Jednak drugą stroną tego jest to, że implementacje takich języków generycznych (lub typów szablonowych) Zwykle pociągają za sobą generowanie odrębnej kopii typu generycznego dla każdej parametryzacji typu.


1 - powodem, dla którego generyki nie zostały uwzględnione w Java 1.0, była presja czasu. Uznali, że muszą szybko wydać język Java, aby wypełnić nowe możliwości rynkowe, jakie dają przeglądarki internetowe. James Gosling stwierdził, że chciałbym włączyć leki generyczne, gdyby mieli czas. Jak wyglądałby język Java, gdyby tak się stało, nikt nie przypuszcza.

 40
Author: Stephen C,
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-10-14 06:51:26

W Javie generyki są zaimplementowane przez użycie "type erasure" dla wstecznej kompatybilności. Wszystkie typy generyczne są konwertowane do obiektu w czasie wykonywania. na przykład,

public class Container<T> {

    private T data;

    public T getData() {
        return data;
    }
}

Będzie postrzegane w czasie wykonywania jako,

public class Container {

    private Object data;

    public Object getData() {
        return data;
    }
}

Kompilator jest odpowiedzialny za zapewnienie właściwego odlewu w celu zapewnienia bezpieczeństwa typu.

Container<Integer> val = new Container<Integer>();
Integer data = val.getData()

Stanie się

Container val = new Container();
Integer data = (Integer) val.getData()

Teraz pojawia się pytanie, dlaczego "obiekt" jest wybierany jako typ w trybie runtime?

Odpowiedź to obiekt jest superklasą wszystkich obiektów i może reprezentować dowolne obiekt zdefiniowany przez użytkownika.

Ponieważ wszystkie prymitywy nie dziedziczą z " Object", więc nie możemy go użyć jako rodzaj ogólny.

FYI: projekt Valhalla próbuje rozwiązać powyższy problem.

 16
Author: Piyush Sagar,
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-06 06:26:12

Zbiory są zdefiniowane tak, aby wymagały typu wywodzącego się z java.lang.Object. Podstawowe typy po prostu tego nie robią.

 7
Author: ZeissS,
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-01-05 04:25:26

Zgodnie z Dokumentacja Javy zmienne typu ogólnego mogą być tworzone tylko z typami odniesienia, a nie z typami prymitywnymi.

To ma być w Javie 10 Pod Project Valhalla .

In Brian Goetz referat o stanie specjalizacji

Istnieje doskonałe wyjaśnienie o powodach, dla których generic nie był wspierany dla primitive. I, Jak to będzie zaimplementowane w przyszłych wydaniach Java.

Obecna implementacja Javy, która tworzy jedną klasę dla wszystkich instancji referencyjnych i nie obsługuje prymitywnych instancji. (Jest to tłumaczenie jednorodne, a ograniczenie, że generyki Javy mogą się wahać tylko nad typami odniesienia, wynika z ograniczeń jednorodnego tłumaczenia w odniesieniu do zestawu bajtowych kodów JVM, który używa różnych bajtowych kodów do operacji na typach odniesienia vs typach prymitywnych.) Jednak wymazane generyki w Javie zapewnij zarówno parametryzację behawioralną (metody generyczne), jak i parametryzację danych (instancje surowych i wieloznacznych typów generycznych.)

...

Wybrano jednorodną strategię tłumaczenia, w której zmienne typu ogólnego są usuwane do swoich granic, gdy są włączane do kodu bajtowego. Oznacza to, że niezależnie od tego, czy klasa jest generyczna, czy nie, nadal kompiluje się do jednej klasy o tej samej nazwie i której sygnatury członkowskie są takie same. Bezpieczeństwo typu jest weryfikowane w czas kompilacji i czas wykonania jest nieograniczony przez system typu generic. Z kolei narzucało to ograniczenie, że typy generyczne mogą działać tylko nad typami referencyjnymi, ponieważ obiekt jest najbardziej ogólnym typem dostępnym i nie obejmuje typów prymitywnych.

 6
Author: vinS,
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-12-18 11:59:44

Podczas tworzenia obiektu nie można zastąpić typu prymitywnego typem parameter.As z powodu tego ograniczenia jest to problem implementacji kompilatora. Typy prymitywne mają własne instrukcje kodu bajtowego do ładowania i przechowywania na stosie maszyny wirtualnej. Nie jest więc niemożliwe skompilowanie prymitywnych generyków do tych oddzielnych ścieżek bajtowych, ale skomplikowałoby to kompilator.

 0
Author: Atif,
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
2020-06-03 19:50:19