Java
1 Wstęp i historia
2 Cechy języka
2.1 Interfejsy, dziedziczenie
2.1.1 Problem diamentowy
2.2 Bezpieczeństwo
2.3 Niezależność od architektury
2.4 Rozszerzalność
2.5 Wydajność
2.6 Inne cechy języka i platformy
3 Materiały dostępne w sieci
3.7 Specyfikacje API JavySE
3.8 Tutoriale do JavySE
3.9 JavaFX 2
3.10 Dokumentacje JavaDoc JavyEE
3.11 Tutoriale do JavyEE
3.12 Zestaw przykładów w Javie
3.13 Kursy programowania obiektowego w Javie
3.14 Książki o Javie
3.15 Blogi
Wstęp i historia
Obiektowy język programowania stworzony w firmie Sun Microsystem (przejęta przez Oracle w 2010 roku) pod kierunkiem Jamesa Goslinga i opublikowany w 1995 roku wraz z Maszyną Wirtualną Java (JVM).
Początkowo język, jak i maszyna wirtualna miały stanowić platformę dla telewizji interaktywnej. Jednak ze względu na zbyt duże trudności, m.in. zbyt zaawansowaną i niedostępną w tym czasie technologię, postanowiono stworzyć język, który będzie konkurentem dla C++. Większość elementów składni języka zaczerpnięto z C++, a rozwiązania takie jak maszyna wirtualna czy automatyczne zwalnianie pamięci z Smalltalk.
Od początku firma Sun wyznaczyła najważniejsze cechy Javy jako platformy:
- powinien być prosty w użyciu, obiektowy z „przyjazną” składnią.
- powinien bezpieczny i „solidny”.
- powinien być neutralny architektonicznie i łatwy w rozszerzeniu.
- powinien zapewniać wysoką wydajność.
- powinien być interpretowany, wielowątkowy i dynamiczny.
Cechy języka
Język rzeczywiście posiada uproszczoną w stosunku do C++ składnię. Zrezygnowano też z dualnego dostępu do zmiennych – przez wartość i przez referencję, na rzecz przekazywania obiektów przez referencję. Język nie wspiera przeciążania operatorów (choć operator + został przeciążony dla klasy String ) ani nie umożliwia tworzenia własnych. Jednocześnie na obecnym etapie rozwoju programista ma do dyspozycji mechanizm adnotacji czy typy generyczne, które są bardziej rozbudowane w stosunku do znanej z C++ biblioteki STL.
Java jest językiem obiektowym, ale poza typami obiektowymi posiada też typy proste (prymitywy) reprezentujące liczby całkowite, zmiennopozycyjne, wartości logiczne i pojedyncze znaki. W wersji 1.5 języka wprowadzono mechanizm auto-boxingu, który pozwala na swobodne mieszanie typów prostych i ich obiektowych odpowiedników, a to dzięki zamianie typów prostych na obiektowe w trakcie kompilacji.
Interfejsy, dziedziczenie
Język Java pozwala na dziedziczenie po jednej klasie nadrzędnej. Wszystkie klasy dziedziczą po klasie Object
. Można też tworzyć interfejsy, które od wersji ósmej języka pozwalają na stworzenie domyślnej implementacji (mixin). W wersji dziewiątej można zdefiniować metody prywatne, wraz z implementacją, w interfejsie.
Problem diamentowy
W przypadku tak zwanego problemu diamentowego, gdy klasa implementuje dwa interfejsy zawierające metody o identycznych sygnaturach, zachowanie języka uzależnione jest od tego jak zdefiniowano te metody:
- jeżeli w obu interfejsach metoda jest wirtualna, to klasa musi zawierać implementację. Implementacja będzie wykorzystywana w kontekście obu interfejsów.
- jeżeli jeden z interfejsów zawiera domyślną implementację, a drugi nie, to uznaje się, że metoda jest zaimplementowana. Klasa nie musi zawierać implementacji.
- jeżeli oba interfejsy zawierają domyślną implementację, to klasa musi zawierać implementacji.
Bezpieczeństwo
Java udostępnia kilka mechanizmów zabezpieczających programistów przed popularnymi błędami. Pierwszym z nich jest automatyczne zwalnianie pamięci. Programista jest dzięki temu „zwolniony” z dbania o usuwanie nieużywanych obiektów. Nie oznacza to jednak, że nie można spowodować wycieku pamięci. Drugim jest silne typowanie oraz konieczność dostarczenia wszystkich użytych klas w czasie kompilacji. Kolejnym jest sposób obsługi wyjątków i wydzielenie grupy wyjątków weryfikowalnych, które muszą zostać obsłużone przez programistę. Ostatnim istotnym elementem jest tzw. security policy, czyli zestaw reguł pozwalających na definiowanie dostępnych i zabronionych działań dla programów na danej JVM.
Niezależność od architektury
Java była reklamowana hasłem „napisz raz, uruchom wszędzie”. Jest to główna cecha rozpoznawcza języka, która stała się też celem niewybrednych dowcipów. Rzeczywistą zaletą jest rozgraniczenie elementów platformy systemowej i elementów dostępnych w języku bez konieczności wywołań systemowych. W toku prac nad językiem zauważono, że można stworzyć zbiór elementów API, które mogą być napisane w Javie bez wykorzystania wywołań systemowych. Ograniczyło to ilość kodu, który trzeba implementować w zależności od platformy. Teoretycznie prosta implementacja JVM powinna wymagać tylko systemowej I/O (system plików, sieć, klawiatura, mysz itp.). W praktyce implementowane są też niektóre operacje takie jak np. Math.sqrt
.
Rozszerzalność
Rozszerzalność platformy Java jest doskonale widoczna, jeżeli przyjrzymy się innym językom, które są uruchamiane w ramach JVM. Scala i Groovy doskonale ilustrują fakt, iż język Java i JVM to dwa niezależne byty. Poza rozszerzalnością składni jest też możliwe tworzenie rozszerzeń wprowadzających nowe paradygmaty aspektowy – AspectJ czy funkcyjny Clojure. Istnieją też rozszerzenia architektury pozwalające na swobodne zarządzanie zasobami w ramach działającego JVM – z głównym rozwiązaniem OSGi.
Wydajność
Początkowo Java była uważana za język prosty, ale powolny i zasobochłonny. Jednakże kolejne modyfikacje oraz wprowadzenie kompilatora JIT (Just In Time) spowodowało, że Java stała się językiem, w którym niektóre problemy mogą zostać rozwiązane szybciej niż w C.
Nadal jednak wydajność jest tematem zażartych dyskusji i flamewarów pomiędzy programistami.
Inne cechy języka i platformy
Kod jest kompilowany do bytecodu, czyli asemblera maszyny wirtualnej, a następnie interpretowany przez JVM. Obecnie dzięki zastosowaniu JIT maszyna wirtualna potrafi wykryć często wykorzystywane fragmenty bytecodu i skompilować je do kodu maszynowego platformy, na której jest uruchomiona.
Java udostępnia API do pisania programów współbieżnych. Jednocześnie nie gwarantuje zachowania reżimu czasowego, co czyni ją praktycznie nieprzydatną w programowaniu systemów czasu rzeczywistego. Wynika to z niedeterministycznej natury automatycznego odśmiecania pamięci, który nie pozwala na przewidywanie momentu uruchomienia, ani czasu pracy. Istnieją co prawda wersje Garbage Collector, które pozwalają na określenie takich parametrów jak periodyczność uruchomienia, maksymalny czas pracy, wielowątkowe działanie, ale nie są one dostępne w standardowych ustawieniach JVM.
Materiały dostępne w sieci
Podziękowania dla użytkownika Wibowit, który przygotował zestawienie na forum.
Specyfikacje API JavySE
- JavaSE 1.3 - dostępna jako archiwum.
- JavaSE 1.4 - dostępna jako archiwum.
- JavaSE 5
- JavaSE 6
- JavaSE 7
- JavaSE 8
Tutoriale do JavySE
JavaFX 2
Dokumentacje JavaDoc JavyEE
Tutoriale do JavyEE
- Java EE6 Kurs programowania
- The J2EE Tutorial for the Sun ONE Platform
- The J2EE(TM) 1.4 Tutorial
- The Java EE 5 Tutorial
- The Java EE 6 Tutorial
- The Java EE 7 Tutorial
Zestaw przykładów w Javie
Kursy programowania obiektowego w Javie
- Programowanie obiektowe (MIMUW)
- Zaawansowane projektowanie obiektowe (MIMUW)
- CS108: Object Oriented System Design (Stanford University)
Książki o Javie
Poniższa lista zawiera tylko książki na licencjach otwartych.
Blogi
- JVMBloggers – agregator polskich blogów programistycznych. Można dodać własnego bloga do listy.