Naucz się Java od podstaw

Więc chcesz programować w Javie? To świetnie i trafiłeś we właściwe miejsce. Seria Java 101 zapewnia samodzielne wprowadzenie do programowania w języku Java, zaczynając od podstaw i obejmując wszystkie podstawowe pojęcia, które należy znać, aby zostać produktywnym programistą Java. Ta seria ma charakter techniczny i zawiera wiele przykładów kodu, które pomogą Ci zrozumieć koncepcje. Zakładam, że masz już pewne doświadczenie w programowaniu, tylko nie w Javie.

W tym pierwszym artykule przedstawiono platformę Java i wyjaśniono różnicę między jej trzema wersjami: Java SE, Java EE i Java ME. Dowiesz się również o roli wirtualnej maszyny języka Java (JVM) we wdrażaniu aplikacji Java. Pomogę Ci skonfigurować zestaw Java Development Kit (JDK) w Twoim systemie, abyś mógł tworzyć i uruchamiać programy w języku Java, a ja pomogę Ci rozpocząć pracę z architekturą typowej aplikacji Java. Na koniec dowiesz się, jak skompilować i uruchomić prostą aplikację Java.

Zaktualizowano dla Java 12 i nowego JShell

Ta seria została zaktualizowana dla języka Java 12 i zawiera krótkie wprowadzenie do nowego jshell: interaktywne narzędzie do nauki języka Java i prototypowania kodu w języku Java.

pobierz Pobierz kod Pobierz kod źródłowy na przykład aplikacje w tym samouczku. Stworzone przez Jeffa Friesena dla JavaWorld.

Co to jest Java?

Możesz myśleć o Javie jako o języku ogólnego przeznaczenia, zorientowanym obiektowo, który wygląda podobnie do C i C ++, ale jest łatwiejszy w użyciu i pozwala tworzyć bardziej zaawansowane programy. Niestety ta definicja nie daje dużego wglądu w Javę. W 2000 roku Sun Microsystems (twórca platformy Java) opisał Javę w ten sposób: 

Java jest prostym, zorientowanym obiektowo, znającym się na sieci, interpretowanym, solidnym, bezpiecznym, neutralnym dla architektury, przenośnym, wydajnym, wielowątkowym, dynamicznym językiem komputerowym.

Rozważmy każdą z tych definicji osobno.

Java to prosty język . Java była początkowo wzorowana na C i C ++, bez niektórych potencjalnie mylących funkcji. Wskaźniki, dziedziczenie wielu implementacji i przeciążanie operatorów to niektóre funkcje C / C ++, które nie są częścią języka Java. Funkcja, która nie jest wymagana w C / C ++, ale jest niezbędna dla Javy, to narzędzie do usuwania elementów bezużytecznych, które automatycznie odzyskuje obiekty i tablice.

Java to język zorientowany obiektowo . Zorientowanie obiektowe języka Java pozwala programistom pracować nad dostosowywaniem Javy do rozwiązania problemu, zamiast zmuszać nas do manipulowania problemem w celu spełnienia ograniczeń językowych. Różni się to od języka strukturalnego, takiego jak C. Na przykład, podczas gdy Java pozwala skupić się na obiektach rachunków oszczędnościowych, C wymaga oddzielnego myślenia o stanie konta oszczędnościowego (takim saldzie) i zachowaniach (takich jak wpłaty i wypłaty).

Java to język obsługujący sieci . Obszerna biblioteka sieciowa Java ułatwia radzenie sobie z protokołami sieciowymi Transmission Control Protocol / Internet Protocol (TCP / IP), takimi jak HTTP (HyperText Transfer Protocol) i FTP (File Transfer Protocol), a także upraszcza nawiązywanie połączeń sieciowych. Ponadto programy w języku Java mogą uzyskiwać dostęp do obiektów w sieci TCP / IP za pośrednictwem jednolitych lokalizatorów zasobów (adresów URL) z taką samą łatwością, jak uzyskiwanie do nich dostępu z lokalnego systemu plików.

Java jest językiem interpretowanym . W czasie wykonywania program w języku Java jest wykonywany pośrednio na platformie bazowej (takiej jak Windows lub Linux) za pośrednictwem maszyny wirtualnej (będącej programową reprezentacją hipotetycznej platformy) i powiązanego środowiska wykonawczego. Maszyna wirtualna poprzez interpretację tłumaczy kody bajtowe programu Java (instrukcje i powiązane dane) na instrukcje specyficzne dla platformy. Interpretacja jest czynnością polegającą na ustaleniu, co oznacza instrukcja w kodzie bajtowym, a następnie wybraniu do wykonania równoważnych "gotowych" instrukcji specyficznych dla platformy. Maszyna wirtualna następnie wykonuje instrukcje specyficzne dla platformy.

Interpretacja ułatwia debugowanie wadliwych programów Java, ponieważ w czasie wykonywania dostępnych jest więcej informacji dotyczących czasu kompilacji. Interpretacja umożliwia również opóźnienie kroku łącza między fragmentami programu Java do czasu wykonania, co przyspiesza tworzenie.

Java to solidny język . Programy Java muszą być niezawodne, ponieważ są używane zarówno w aplikacjach konsumenckich, jak i aplikacjach o znaczeniu krytycznym, od odtwarzaczy Blu-ray po systemy nawigacji samochodowej lub systemy kontroli powietrza. Funkcje językowe, które zwiększają niezawodność języka Java, obejmują deklaracje, sprawdzanie zduplikowanych typów w czasie kompilacji i w czasie wykonywania (aby zapobiec problemom z niezgodnością wersji), prawdziwe tablice z automatycznym sprawdzaniem granic i pomijanie wskaźników. (Zobacz „Podstawowe funkcje języka Java”, aby zapoznać się z typami języka Java, literałami, zmiennymi i nie tylko).

Innym aspektem niezawodności Javy jest to, że pętle muszą być kontrolowane przez wyrażenia logiczne zamiast wyrażeń całkowitych, w których 0 jest fałszem, a wartość różna od zera to prawda. Na przykład Java nie zezwala na pętlę w stylu C, while (x) x++;ponieważ pętla może nie kończyć się zgodnie z oczekiwaniami. Zamiast tego musisz jawnie podać wyrażenie logiczne, takie jak while (x != 10) x++;(co oznacza, że ​​pętla będzie działać, aż xosiągnie wartość 10).

Java to bezpieczny język . Programy Java są używane w środowiskach sieciowych / rozproszonych. Ponieważ programy Java mogą migrować i uruchamiać się na różnych platformach sieciowych, ważne jest, aby chronić te platformy przed złośliwym kodem, który może rozprzestrzeniać wirusy, kraść informacje o kartach kredytowych lub wykonywać inne złośliwe działania. Funkcje języka Java, które obsługują niezawodność (takie jak pominięcie wskaźników), współpracują z funkcjami bezpieczeństwa, takimi jak model zabezpieczeń piaskownicy Java i szyfrowanie z kluczem publicznym. Dzięki tym funkcjom wirusy i inny niebezpieczny kod nie sieją spustoszenia na niczego niepodejrzewającej platformie.

Teoretycznie Java jest bezpieczna. W praktyce wykryto i wykorzystano różne luki w zabezpieczeniach. W rezultacie Sun Microsystems i Oracle obecnie nadal publikują aktualizacje zabezpieczeń.

Java jest językiem neutralnym dla architektury . Sieci łączą platformy o różnych architekturach w oparciu o różne mikroprocesory i systemy operacyjne. Nie można oczekiwać, że Java będzie generować instrukcje specyficzne dla platformy i mieć te instrukcje „zrozumiałe” dla wszystkich rodzajów platform, które są częścią sieci. Zamiast tego Java generuje niezależne od platformy instrukcje kodu bajtowego, które są łatwe do zinterpretowania dla każdej platformy (dzięki implementacji JVM).

Java to język przenośny . Neutralność architektury przyczynia się do mobilności. Jednak przenośność języka Java to coś więcej niż instrukcje kodu bajtowego niezależne od platformy. Weź pod uwagę, że rozmiary typów całkowitych nie mogą się różnić. Na przykład typ 32-bitowej liczby całkowitej musi być zawsze podpisany i zajmować 32 bity, niezależnie od tego, gdzie przetwarzana jest 32-bitowa liczba całkowita (np. Platforma z rejestrami 16-bitowymi, platforma z rejestrami 32-bitowymi lub platforma z rejestrami 64-bitowymi). Biblioteki Java również przyczyniają się do przenośności. W razie potrzeby zapewniają typy, które łączą kod Java z funkcjami specyficznymi dla platformy w możliwie najbardziej przenośny sposób.

Java to język o wysokiej wydajności . Interpretacja zapewnia poziom wyników, który jest zwykle więcej niż wystarczający. W przypadku bardzo wydajnych scenariuszy aplikacji Java wykorzystuje kompilację just-in-time, która analizuje interpretowane sekwencje instrukcji kodu bajtowego i kompiluje często interpretowane sekwencje instrukcji do instrukcji specyficznych dla platformy. Kolejne próby zinterpretowania tych sekwencji instrukcji kodu bajtowego skutkują wykonywaniem równoważnych instrukcji specyficznych dla platformy, co skutkuje wzrostem wydajności.

Java jest językiem wielowątkowym . Aby zwiększyć wydajność programów, które muszą wykonywać kilka zadań jednocześnie, Java obsługuje koncepcję wykonywania wątków . Na przykład program zarządzający graficznym interfejsem użytkownika (GUI) podczas oczekiwania na dane wejściowe z połączenia sieciowego używa innego wątku do wykonania oczekiwania zamiast używania domyślnego wątku GUI do obu zadań. Dzięki temu GUI reaguje. Prymitywy synchronizacji Java pozwalają wątkom na bezpieczne przesyłanie danych między sobą bez uszkadzania danych. (Zobacz programowanie wątkowe w Javie omówione w innym miejscu z serii Java 101).

Java to język dynamiczny . Ponieważ połączenia między kodem programu a bibliotekami zachodzą dynamicznie w czasie wykonywania, nie jest konieczne ich jawne łączenie. W rezultacie, gdy program lub jedna z jego bibliotek ewoluuje (na przykład w celu usunięcia błędu lub poprawy wydajności), programista musi jedynie rozprowadzić zaktualizowany program lub bibliotekę. Chociaż dynamiczne zachowanie skutkuje mniejszą ilością kodu do dystrybucji w przypadku zmiany wersji, ta zasada dystrybucji może również prowadzić do konfliktów wersji. Na przykład programista usuwa typ klasy z biblioteki lub zmienia jej nazwę. Gdy firma dystrybuuje zaktualizowaną bibliotekę, istniejące programy zależne od typu klasy przestaną działać. Aby znacznie zmniejszyć ten problem, Java obsługuje typ interfejsu, co jest jak umowa między dwiema stronami. (Zobacz interfejsy, typy i inne funkcje języka zorientowanego obiektowo omówione w innych miejscach w serii Java 101).

Rozpakowanie tej definicji wiele nas nauczy o Javie. Co najważniejsze, ujawnia, że ​​Java jest zarówno językiem, jak i platformą. Dowiesz się więcej o komponentach platformy Java - a mianowicie o maszynie wirtualnej Java i środowisku wykonawczym Java - w dalszej części tego samouczka.

Trzy wersje języka Java: Java SE, Java EE i Java ME

Firma Sun Microsystems wypuściła zestaw deweloperski oprogramowania Java 1.0 (JDK) w maju 1995 r. Pierwszy JDK był używany do tworzenia aplikacji i apletów na komputery stacjonarne, a Java ewoluowała następnie, aby objąć programowanie dla serwerów korporacyjnych i urządzeń mobilnych. Przechowywanie wszystkich niezbędnych bibliotek w jednym JDK spowodowałoby, że JDK byłby zbyt duży, aby można go było dystrybuować, zwłaszcza że dystrybucja w latach 90. była ograniczona przez małe dyski CD i wolne prędkości sieciowe. Ponieważ większość programistów nie potrzebowała ostatniego interfejsu API (programista aplikacji komputerowych nie musiałby mieć dostępu do korporacyjnych interfejsów API Java), firma Sun rozłożyła Javę na trzy główne edycje. Te ostatecznie stały się znane jako Java SE, Java EE i Java ME:

  • Java Platform, Standard Edition (Java SE) to platforma Java do tworzenia aplikacji klienckich (działających na komputerach stacjonarnych) i apletów (działających w przeglądarkach internetowych). Należy pamiętać, że ze względów bezpieczeństwa aplety nie są już oficjalnie obsługiwane.
  • Java Platform, Enterprise Edition (Java EE ) to platforma Java zbudowana na bazie Java SE, która jest używana wyłącznie do tworzenia aplikacji serwerowych dla przedsiębiorstw. Aplikacje po stronie serwera obejmują serwlety Java , które są programami w języku Java, które są podobne do apletów, ale działają na serwerze, a nie na kliencie. Serwlety są zgodne z Java Servlet API.
  • Java Platform, Micro Edition (Java ME) jest również zbudowana na bazie Java SE. Jest to platforma Java do tworzenia MIDletów , czyli programów w języku Java działających na mobilnych urządzeniach informacyjnych oraz Xletów , które są programami Java działającymi na urządzeniach wbudowanych.

Java SE jest platformą podstawową dla języka Java i koncentruje się na serii Java 101. Przykłady kodu będą oparte na najnowszej wersji języka Java w chwili pisania tego tekstu, Java 12.

Platforma Java i JVM

Java jest zarówno językiem programowania, jak i platformą do uruchamiania skompilowanego kodu Java. Platforma ta składa się głównie z maszyny JVM, ale zawiera również środowisko wykonawcze, które obsługuje wykonywanie maszyny JVM na podstawowej (natywnej) platformie. JVM zawiera kilka komponentów służących do ładowania, weryfikowania i wykonywania kodu Java. Rysunek 1 przedstawia sposób wykonywania programu Java na tej platformie. 

Jeff Friesen

W górnej części diagramu znajduje się seria plików klas programu, z których jeden jest oznaczony jako główny plik klas. Program Java składa się przynajmniej z głównego pliku klasy, który jest pierwszym plikiem klasy do załadowania, zweryfikowania i wykonania.

JVM deleguje ładowanie klas do swojego komponentu classloader. Programy ładujące klasy ładują pliki klas z różnych źródeł, takich jak systemy plików, sieci i pliki archiwów. Izolują JVM od zawiłości ładowania klasowego.

Załadowany plik klasy jest przechowywany w pamięci i reprezentowany jako obiekt utworzony z Classklasy. Po załadowaniu weryfikator kodu bajtowego weryfikuje różne instrukcje kodu bajtowego, aby upewnić się, że są one prawidłowe i nie naruszają bezpieczeństwa.

Jeśli kody bajtowe pliku klas są nieprawidłowe, JVM kończy działanie. W przeciwnym razie jego składnik interpretujący interpretuje kod bajtowy po jednej instrukcji naraz. Interpretacja identyfikuje instrukcje kodu bajtowego i wykonuje równoważne instrukcje natywne.

Niektóre sekwencje instrukcji kodu bajtowego są wykonywane częściej niż inne. Gdy interpreter wykryje tę sytuację, kompilator JVM JVM kompiluje sekwencję kodu bajtowego do kodu natywnego, aby przyspieszyć wykonanie.

Podczas wykonywania interpreter zazwyczaj napotyka żądanie wykonania kodu bajtowego innego pliku klasy (należącego do programu lub biblioteki). W takim przypadku moduł ładujący klasy ładuje plik klasy, a weryfikator kodu bajtowego weryfikuje kod bajtowy załadowanego pliku klasy przed jego wykonaniem. Również podczas wykonywania instrukcje kodu bajtowego mogą zażądać, aby JVM otworzył plik, wyświetlił coś na ekranie, wydał dźwięk lub wykonał inne zadanie wymagające współpracy z natywną platformą. W odpowiedzi maszyna JVM wykorzystuje technologię mostka Java Native Interface (JNI) do interakcji z natywną platformą w celu wykonania zadania.