CodeGym /Kursy /All lectures for PL purposes /Wnioskowanie typu kompilatora Java

Wnioskowanie typu kompilatora Java

All lectures for PL purposes
Poziom 1, Lekcja 724
Dostępny

1. Cukier syntaktyczny

Programiści uwielbiają, gdy jakiś złożony kod lub logikę można napisać w kilku wierszach, a kod jest zwarty i czytelny. Czasami pomagają im w tym programiści językowi.

Trudne cechy języka, które pozwalają na krótszą ścieżkę (mniej pisania kodu), nazywane są cukrem składniowym . Chociaż, szczerze mówiąc, w Javie jest go bardzo mało.

Twórcy Javy dołożyli wszelkich starań, aby wyeliminować wszelkie możliwe redundancje z Javy. Jeśli w C++ istnieje dziesięć sposobów zrobienia czegoś, w Javie najczęściej jest tylko jeden sposób.

Ale ani programistom Javy, ani twórcom Javy nie podoba się to ujednolicenie. A czasami ułatwiają życie zwykłym facetom, takim jak ty i ja.

Nawiasem mówiąc, zapoznałeś się już z rzeczą, którą można przypisać cukierowi syntaktycznemu - są to autoboxing i unboxing . Porównywać:

Długi kod zwarty kod
Integer a = new Integer(5);
int b = a.intValue();
Integer a = 5;
int b = a;
int b = 5;
Integer c = new Integer(b);
int b = 5;
Integer c = b;
Integer a = new Integer(1);
int b = 1;
if (a.intValue() == b)
{
   ...
}
Integer a = 1;
int b = 1;
if (a == b)
{
   ...
}

Zamiast długiego kodu, jak po lewej, możesz napisać bardziej zwarty kod, jak po prawej. A inteligentny kompilator Javy na podstawie krótkiego kodu wygeneruje jego pełną wersję. To jest cukier składniowy.


2. Wnioskowanie o typach zmiennych −var

W Javie 11 kompilator stał się jeszcze inteligentniejszy i może teraz wywnioskować typ tworzonej zmiennej na podstawie typu wartości, która jest do niej przypisana. W kodzie wygląda to tak:

var Nazwa = oznaczający;

Gdzie Nazwato nazwa nowej zmiennej, wartość  to jej wartość początkowa i varsłowo kluczowe użyte do zadeklarowania zmiennej. Typ nazwy zmiennej będzie  taki sam jak wartość, która jest do niej przypisana.

Przykłady:

Jak widzimy ten kod? Co widzi kompilator
var i = 1;
int i = 1;
var s = "Cześć";
String s = "Cześć";
var console = new Scanner(System.in);
Scanner console = new Scanner(System.in);
var list = new ArrayList<String>();
ArrayList<String> list = new ArrayList<String>();
var data = new int[]{1, 2, 3};
int[] data = new int[]{1, 2, 3};

Sam kompilator określa lub, jak to się mówi, wnioskuje o typie zmiennej na podstawie przypisanej jej wartości.

Wiele egzemplarzy zostało zepsutych w bitwach programistów na temat tego, czy dodać taką funkcję do języka, czy nie. Wielu obawiało się, że użycie varzostanie nadużyte, a czytelność kodu zostanie znacznie zmniejszona.

Jest w tym trochę prawdy, dlatego najlepiej jest stosować vartam, gdzie poprawia czytelność kodu. Na przykład te w dwóch przypadkach:

Przypadek 1: patrząc na wartość zmiennej, od razu wiadomo, jaki typ ma zmienna

Kod Wyjaśnienie
var stream = url.getInputStream();
Zmienna ma typInputStream
var name = person.getFullName();
Zmienna ma typString

Ale w takich przypadkach var nie powinieneś używać . Cóż, odpowiedz, jakiego typu jest zmienna?

Kod Wyjaśnienie
var result = task.execute();
Typ zmiennej jest trudny do określenia
var status = person.getStatus();
Typ zmiennej jest trudny do określenia

Przypadek 2: Typ zmiennej nie jest ważny dla zrozumienia kodu

Często w kodzie mogą wystąpić sytuacje, gdy na zmiennej nie są wywoływane żadne metody - zmienna służy po prostu do tymczasowego przechowywania czegoś. Używanie vartutaj wcale nie zmniejsza zrozumienia kodu:

Długi kod zwarty kod
var data = stream.getMetaData();
storage.save(data)
Otrzymaliśmy metadane ze strumienia streami przechowaliśmy je w magazynie storage. Nie ma znaczenia , jakiego typu była zmienna data.

złoty środek

Teraz podam trzy sposoby na napisanie tego samego kodu. Użycie varbyłoby najlepszą opcją.

Kod Notatka
dest.writeHeaderInfo(src.getFileMetaInfo());
Zbyt zwarty
var headerInfo = src.getFileMetaInfo();
dest.writeHeaderInfo(headerInfo);
Doskonały
FileMetaInfo headerInfo = src.getFileMetaInfo();
dest.writeHeaderInfo(headerInfo);
Zbyt szczegółowe

headerInfoKiedy przeszliśmy z opcji w linii 1 do opcji w linii 2, dodaliśmy trochę czytelności do kodu kosztem nazwy zmiennej ( ). Teraz jest jasne, że metoda zwróciła nie tylko metainformacje, ale także informacje nagłówkowe.

Trzecia opcja byłaby zbędna. No i co z tego, co headerInfoma typ FileMetaInfo– to już było prawie jasne z getFileMetaInfo(). Cel tych meta-informacji jest znacznie bardziej interesujący.



3. Pominięcie typu - operator diamentu:<>

Jeszcze przed pojawieniem się operatora varpodejmowano próby nauczenia kompilatora wnioskowania o typach kolekcji. Zgadzam się, ten wpis wygląda na nieco zbędny:

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

Począwszy od siódmej wersji Javy, podczas pisania typu kolekcji można było pominąć (nie zapisywać) typ elementów kolekcji, jeśli został on określony przy deklaracji zmiennej. Te. Powyższy kod można zapisać w nieco skróconej formie:

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

Jak widać, nie ma potrzeby ponownego pisania typu String. Nie tak fajnie jak z operatorem var, ale kiedyś wydawało się to osiągnięciem.

Puste nawiasy trójkątne w typie kolekcji nazwano operatorem rombu : dwa nawiasy niejasno przypominały sylwetkę rombu.

Nie jest pożądane jednoczesne używanie operatora diamentu :var

var list = new ArrayList<>();

Brak informacji o typie przechowywanym w kolekcji, a typ zostanie zdefiniowany jako ArrayList <Object> .



4. Podwójne nawiasy klamrowe

Pamiętasz szybką inicjalizację macierzy?

Właśnie wymieniliśmy tam wartość w nawiasach klamrowych:

Przykłady
int[] data = new int[] {1, 2, 3, 4, 5, 6, 7};
int[] data = {1, 2, 3, 4, 5, 6, 7};

Twórcom Javy spodobał się pomysł wykorzystania nawiasów klamrowych w celu ułatwienia przechowywania danych w tablicy. Ale co ze zbiorami?

Również w przypadku kolekcji wystarczyło wyobraźni: pozwoliły na zastosowanie sztuczki z podwójnymi nawiasami klamrowymi.

Z cukrem Bez cukru
var list = new ArrayList<String>()
{{
   add("Cześć");
   add("Jak");
   add("Дела");
}};
var list = new ArrayList<String>();

list.add("Cześć");
list.add("Jak");
list.add("Дела");

Jeśli kompilator napotka kod w przykładzie po lewej stronie, przekonwertuje go na kod po prawej stronie.

Kod nie staje się dużo bardziej zwarty. To bardziej jak oszczędzanie na drobiazgach: nie musisz pisać za każdym razem list. Może to być korzystne, jeśli nazwa zmiennej jest bardzo długa.

Ale jeśli trafisz na taki kod w czyimś projekcie, nie zdziw się 🙂


Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION