Zarezerwowany typ o nazwie var
wprowadzony w Javie 10 jako jeden z rezultatów projektu Amber. Został już dość dobrze opisany na innych mądrych stronach, zatem przytoczę tylko nieoczywiste fakty na jego temat.
var
może wpływać na bytecode
Całe wnioskowanie typu dzieje się na etapie kompilacji do bytecode’u. Wtedy również dzieje się podmiana typu zmiennej na typ wywnioskowany.
Czasem przy definicji zmiennej użylibyśmy interfejsu. Jednak gdy użyjemy słowa var
, wówczas w pewnych użyciach w bytecodzie pojawi się typ konkretny. Przykładowo w takim kawałku kodu:
List list = new ArrayList(); list.size(); var varList = new ArrayList(); varList.size();
Dekompilowanie poleceniem javap -v -p
potwierdza tę tezę:
LocalVariableTable: Start Length Slot Name Signature (...) 16 113 2 list Ljava/util/List; 31 98 3 varList Ljava/util/ArrayList; (...)
Z tej różnicy wynika konieczność użycia instrukcji invokeinterface
zamiast invokevirtual
. W trybie interpretowanym invokeinterface
ma potencjalnie niezerowy (ale i niezbyt duży) negatywny wpływ na wydajność. Ale o tym już pisałem, więc nie będę rozwijał tego wątku…
var
umożliwia wywoływanie metod wcześniej niewidocznych…
… i nie tylko chodzi o to, że w poprzednim przykładzie można wywoływać metody typowe dla konkretnej klasy. Chociaż poniekąd jest to powiązane…
Otóż wyobraźmy sobie klasę anonimową. Standardowo nie mamy informacji o tym, jaka to jest klasa, ponieważ jest… anonimowa… Jednak używając słowa var
można wywołać metody specyficzne dla tej klasy.
var anonymous = new Object() { int anInt; public int ret() { return anInt; } }; anonymous.anInt = 4; System.out.println(anonymous.ret());
Pachnie Javascriptem, co nie? 😉
Co by nie mówić, wcześniej wywoływanie metod klas anonimowych było możliwe tylko z użyciem refleksji lub methodHandle, więc jest to jakieś usprawnienie.
Czytelność
Dyskusyjną sprawą jest czytelność. Osobiście w jednym projekcie pisanym w Javie 11 doświadczyłem, że var
może tę czytelność poprawić. Przykładowo, osobiście taki kod łatwiej się czyta:
var stringsByIds = getStringsById(); var stringList = stringsByIds.getOrDefault(1, List.of()); // zamiast: Map