Projekt okładki i stron tytułowych Grzegorz Laskowski

Ilustracja na okładce Shutterstock/photovs

Wydawca Łukasz Łopuszański

Redaktor prowadzący Jolanta Kowalczuk

Redaktor Joanna Cierkońska

Koordynator produkcji Anna Bączkowska

Przygotowanie wersji elektronicznej Ewa Modlińska

Skład wersji elektronicznej na zlecenie Wydawnictwa Naukowego PWN Marcin Kapusta

Książka, którą nabyłeś, jest dziełem twórcy i wydawcy. Prosimy, abyś przestrzegał praw, jakie im przysługują. Jej zawartość możesz udostępnić nieodpłatnie osobom bliskim lub osobiście znanym. Ale nie publikuj jej w internecie. Jeśli cytujesz jej fragmenty, nie zmieniaj ich treści i koniecznie zaznacz, czyje to dzieło. A kopiując jej część, rób to jedynie na użytek osobisty.

Szanujmy cudzą własność i prawo

Więcej na www.legalnakultura.pl

Polska Izba Książki

Copyright © by Wydawnictwo Naukowe PWN SA

Warszawa 2015

eBook został przygotowany na podstawie wydania papierowego z 2015 r.

(wyd. I)

Warszawa 2015

ISBN 978-83-01-18480-3

Wydawnictwo Naukowe PWN SA

02-460 Warszawa, ul. Gottlieba Daimlera 2

tel. 22 69 54 321, faks 22 69 54 288

infolinia 801 33 33 88

e-mail: pwn@pwn.com.pl

www.pwn.pl

Spis treści

Wstęp

1. Klasy

1.1. Abstrakcja i hermetyzacja

1.2. Enumeracje

1.3. Definiowanie klas

1.4. Wykorzystanie składowych statycznych

1.5. Przeciążanie metod i konstruktorów

1.6. Klasy i obiekty niezmienne

1.7. Inicjowanie

1.8. Singletony

1.9. Klasy opakowujące typy proste

2. Ponowne wykorzystanie klas

2.1. Dziedziczenie

2.2. Konwersje referencyjne

2.3. Stwierdzanie typu

2.4. Dziedziczenie w Javie

2.5. Przedefiniowanie metod

2.6. Kowariancja typów wyników

2.7. Przedefiniowanie metod w wyliczeniach

2.8. Przedefiniowanie a wyjątki

2.9. Przedefiniowanie a przeciążanie, przesłanianie i pokrywanie

2.10. Adnotacja @override

2.11. Metody wirtualne i polimorfizm

2.12. Kompozycja

2.13. Kompozycja a dziedziczenie

2.14. Reguły ponownego wykorzystania klas

3. Wyjątki

3.1. Obsługa wyjątków

3.2. Zgłaszanie wyjątków

3.3. Ponowne zgłaszanie wyjątków

3.4. Niskopoziomowe przyczyny i łańcuchowanie wyjątków

3.5. Wykorzystanie informacji o śladzie stosu

4. Interfejsy i klasy wewnętrzne

4.1. Metody i klasy abstrakcyjne

4.2. Pojęcie interfejsu

4.3. Problem wielodziedziczenia

4.4. Definiowanie i implementowanie interfejsów

4.5. Interfejsy jako typy danych

4.6. Implementacja metod w interfejsach

4.7. Mixiny

4.8. Właściwości metod domyślnych

4.9. Prywatne metody w interfejsach

4.10. Pojęcie klasy wewnętrznej

4.11. Przykładowe zastosowanie klasy wewnętrznej

4.12. Anonimowe klasy wewnętrzne

4.13. Lokalne klasy wewnętrzne

5. Typy i metody sparametryzowane (generics)

5.1. Definiowanie typów sparametryzowanych Typy surowe i czyszczenie typów

5.2. Ograniczenia parametrów typu

5.3. Restrykcje

5.4. Metody sparametryzowane

5.5. Uniwersalne argumenty typu

6. Elementy programowania funkcyjnego w Javie 8 Przegląd pragmatyczny

6.1. O programowaniu funkcyjnym

6.2. Interfejsy na pomoc

6.3. Lambda-wyrażenia: pierwsze spotkanie

6.4. O gotowych interfejsach funkcyjnych

6.5. O przetwarzaniu strumieniowym

7. Lambda-wyrażenia

7.1. Interfejsy funkcyjne i lambda-wyrażenia

7.2. Składnia i cechy lambda-wyrażeń

7.3. Referencje do metod i konstruktorów

7.4. Gotowe interfejsy funkcyjne

7.5. Interfejsy z pakietu java.util.function a wyjątki kontrolowane

7.6. Lambda-wyrażenia i obiekty typu Optional

8. Proste narzędzia

8.1. Analiza składniowa tekstów i wyrażenia regularne

8.2. Uproszczenia stosowania wyrażeń regularnych w klasach String i Scanner

8.3. Działania na liczbach

8.4. Daty i czas

8.4.1. Tradycyjna klasa Calendar i operacje na datach

8.4.2. Daty i czas w Javie 8 – elementy nowego API

8.5. Formatowanie liczb i dat

8.6. Metody tablicowe

9. Kolekcje

9.1. Architektura kolekcji (JCF) Interfejsy i implementacje

9.2. Programowanie w kategoriach interfejsów

9.3. Ogólne operacje na kolekcjach

9.4. Operacje opcjonalne oraz wyjątki zgłaszane przez metody kolekcyjne

9.5. Przekształcanie kolekcji. Kolekcje z tablic

9.6. Przykłady ogólnych operacji na kolekcjach

9.7. Iterowanie po kolekcjach

9.7.1. Tradycyjny iterator i rozszerzone for

9.7.2. Iteracje wewnętrzne

9.7.3. Spliteratory

9.7.4. Konkurencyjne modyfikacje

9.8. Listy

9.8.1. Podstawowe implementacje i operacje

9.8.2. Szczególne implementacje list: niuanse metody Arrays.asList(...)

9.8.3. Iteratory listowe

9.8.4. Przykłady operacji na listach

9.9. Kolejki

9.10. Zbiory typu HashSet, metody hashCode() i equals()

9.11. Porównywanie i porządkowanie elementów kolekcji

9.12. Zbiory uporządkowane i nawigowalne

9.13. Mapy

9.13.1. Wprowadzenie

9.13.2. Implementacje i interfejsy Ogólne operacje na mapach

9.13.3. Iterowanie po mapach

9.13.4. Użycie domyślnych metod interfejsu Map

9.13.5. Sortowanie map

9.14. Algorytmy, widoki, fabrykatory kolekcji

9.15. Własne implementacje kolekcji

10. Przetwarzanie strumieniowe

10.1. Pojęcie strumienia Rodzaje i cechy operacji strumieniowych

10.2. Uzyskiwanie strumieni

10.3. Przegląd operacji na strumieniach

10.4. Filtrowanie i leniwość strumieni

10.5. Metoda forEach dla strumieni

10.6. Sortowanie strumieni

10.7. Redukcja

10.8. Proste kolektory

10.9. Kolektory budujące mapy

10.10. Generatory

10.11. Strumienie równoległe

10.12. Przykłady innych użytecznych metod

11. Wejście-wyjście

11.1. Programowanie wejścia-wyjścia: obraz ogólny

11.2. Abstrakcyjne strumienie wejścia-wyjścia Operacje elementarne

11.3. Strumieniowe klasy przedmiotowe

11.4. Instrukcja try-with-resources Automatyczne zarządzanie zasobami a obsługa tłumionych wyjątków

11.5. Strumieniowe klasy przetwarzające – przegląd

11.6. Buforowanie

11.7. Binarne strumienie wejścia-wyjścia

11.8. Kodowanie-dekodowanie przy użyciu strumieni wejścia-wyjścia

11.9. Serializacja obiektów

11.10. Potoki

11.11. Analiza składniowa strumieni – StreamTokenizer

11.12. Obiekty plikowe i klasa File

11.13. Wygodne metody klasy java.nio.file.Files

11.14. Skaner

11.15. Przeglądanie katalogów

11.16. Archiwa

11.17. Pliki o dostępie swobodnym

11.18. Nowe wejście-wyjście (NIO): przegląd

11.19. NIO: bufory

11.20. NIO: kanały i bufory. Kanały plikowe

11.21. Widoki buforów bajtowych

11.22. NIO: bufory – uporządkowanie bajtów (endianess)

11.23. NIO: bufory znakowe Kodowanie i dekodowanie

11.24. NIO: operacje kanałowe na wielu buforach (scattering i gathering)

11.25. NIO: mapowanie plików

11.26. NIO: bezpośrednie transfery kanałowe

12. Programowanie współbieżne i równoległe

12.1. Procesy i wątki

12.2. Uruchamianie równoległych działań Tworzenie wątków

12.3. Zadania i wykonawcy

12.4. Zamykanie wykonawców Oczekiwanie na zakończenie zadań i serwis kompletacji (CompletionService)

12.5. Zadania powtarzalne, opóźnione i okresowe

12.6. Wykonawcy a pule wątków

12.7. ForkJoinPool i zadania rekursywne

12.8. Kompletery typu CountedCompleter

12.9. CountedCompleter jako kontynuacja

12.10. Kiedy i jak używać zadań typu ForkJoinTask? Praktyczny przykład użycia kompleterów

12.11. Zadania kompletowalne (CompletableFuture)

12.12. Przerywanie zadań z zewnątrz i kończenie pracy wątków

12.13. Synchronizacja

12.14. Synchronizacja za pomocą jawnego ryglowania

12.15. Rygle do odczytu i zapisu: ReentrantReadWriteLock i StampedLock

12.16. Synchronizatory wyższego poziomu

12.17. Unikanie synchronizacji: struktura kodu, volatile, atomiki i konkurencyjne kolekcje

12.18. Koordynacja pracy wątków – mechanizm wait-notify

12.19. Koordynacja: warunki

13. Dynamiczna Java

13.1. Mechanizm refleksji

13.2. Uchwyty metod

13.3. Znaczenie refleksji – praktyczne przykłady

13.4. Refleksja a generics

13.5. Dynamiczne klasy proxy

13.6. JavaBeans

13.6.1. Koncepcja JavaBeans

13.6.2. Nasłuch i wetowanie zmian właściwości za pomocą obsługi zdarzeń

13.6.3. Introspekcja

13.7. Adnotacje

13.7.1. Istota adnotacji i sposoby ich definiowana

13.7.2. Przetwarzanie adnotacji w fazie wykonania

13.7.3. Przetwarzanie adnotacji w fazie kompilacji Transformowanie kodu bajtowego

13.8. Skrypty w Javie

14. Lokalizacja i internacjonalizacja aplikacji

14.1. Lokalizacje

14.2. Jeszcze trochę o formatorach liczbowych

14.3. Waluty

14.4. Strefy czasowe

14.5. Kalendarze i zlokalizowane daty

14.6. Porównywanie i sortowanie napisów

14.7. Internacjonalizacja aplikacji i dodatkowe zasoby (resource bundle)

Literatura

Wszystkie rozdziały dostępne w pełnej wersji książki.

Wstęp

W książce przedstawiono sposoby i techniki programowania użyteczne we wszelkich zastosowaniach języka Java. Materiał nie jest przeznaczony dla całkiem początkujących programistów Javy. Jednak choćby pobieżna orientacja w podstawach programowania w tym języku wystarczy, aby korzystając z materiału książki, znacznie pogłębić swoją wiedzę. Mając na względzie programistów niezbyt zaawansowanych w języku Java, każdy z poruszanych ważnych tematów, takich jak:

• programowanie obiektowe i funkcyjne,

• obsługa wyjątków,

• przetwarzanie kolekcji,

• programowanie operacji wejścia-wyjścia,

• programowanie współbieżne i równoległe,

• programowanie dynamiczne,

• lokalizacja i internacjonalizacji aplikacji,

jest omawiany od podstaw. Jednocześnie położono nacisk na kontekst praktyczny: jak i do czego stosować poszczególne narzędzia językowe? Szczególną uwagę skierowano na nowe elementy języka dostępne w wersji 8 i 9.

Rozbudowane rozdziały o kolekcjach, wejściu-wyjściu, programowaniu współbieżnym i równoległym oraz programowaniu dynamicznym można traktować jako swoiste kompendia, które dają nie tylko orientację co do zestawu dostępnych uniwersalnych środków programowania, lecz także omawiają ważne szczegóły i niuanse ich stosowania. Będą one zapewne interesujące również dla Czytelników już zaawansowanych w programowaniu w Javie.

Warto może też wymienić szczególnie ciekawe tematy omawiane w książce. Należą do nich:

• statyczne i domyślne metody interfejsów oraz mixiny, a także szczegółowe przedstawienie gotowych implementacji takich metod w gotowych interfejsach (zwłaszcza kolekcyjnych);

• możliwości i sposoby implementacji w interfejsach metod prywatnych (poczynając od Javy w wersji 9);

• lambda-wyrażenia wraz z przeglądem gotowych interfejsów funkcyjnych i zastosowania ich domyślnych metod;

• sposoby postępowania z wyjątkami kontrolowanymi w lambda-wyrażeniach;

• obiekty typu Optional jako monady oraz ich zastosowanie;

• spliteratory;

• przetwarzanie strumieniowe (pakiet java.util.stream);

• instrukcja try-with-resources jako ogólny sposób działania na dowolnych zasobach wymagających zamykania (z prezentacją koncepcji tłumionych wyjątków oraz rozszerzeń składniowych w Javie w wersji 9);

• metody strumieniowego przetwarzania plików;

• działania na katalogach za pomocą wizytorów, a także z użyciem przetwarzania strumieniowego;

• działania na archiwach, w tym za pomocą systemu plikowego ZipFileSystem i metod interfejsu FileVisitor;

• szczegółowe i obrazowe omówienie mechanizmu fork-join oraz koncepcji work-steeling;

• obiekty typu CountedCompleter jako kontynuacje oraz inne ich zastosowania;

• zadania typu CompletableFuture (nowe w Javie 8) i ich praktyczne zastosowanie;

• zasady i sposoby kończenia z zewnątrz równolegle wykonujących się zadań, w zależności od typu tych zadań;

• wyspecjalizowane synchronizatory, w tym – nowe w Javie 8 – obiekty typu StampedLock;

• zastosowanie refleksji oraz uchwytów metod (MethodHandle);

• tworzenie dynamicznych klas i obiektów typu proxy;

• zastosowania JavaBeans i delegacyjnego modelu obsługi zdarzeń zmian ich właściwości;

• definiowanie i przetwarzanie adnotacji (w tym definiowanie procesorów adnotacji);

• użycie skryptów z poziomu aplikacji Javy.

Jak już wspomniano, lektura książki wymaga znajomości podstaw programowania w języku Java. Założono m.in., że Czytelnik jest świadomy znaczenia pojęcia referencji w Javie, dlatego są czasem stosowane uproszczone opisy elementów języka czy fragmentów kodu. Zamiast dość niezgrabnych (choć precyzyjnych) tekstów typu: „metodzie przekazujemy jako argument referencję do obiektu klasy String” lub „metoda zwraca referencję do obiektu klasy String”, są używane prostsze sformułowania, np. „metodzie przekazujemy napis, metoda zwraca napis”. Oczywiście, zawsze należy pamiętać o różnicy między obiektem a referencją do obiektu.

Informacje na ten temat (a także omówienie innych ważnych podstaw języka) można znaleźć np. w książce autora Programowanie praktyczne od podstaw, wydanej przez WN PWN w 2014 roku. Prezentowane w niej bardziej zaawansowane tematy w obecnej publikacji zostały poszerzone i uzupełnione.

W doborze treści i sposobu jej prezentacji autor wykorzystał swoje doświadczenia z prowadzenia wykładów i zajęć programistycznych w Polsko-Japońskiej Akademii Technik Komputerowych. Niektóre fragmenty książki powstały na ich podstawie.

Praca jest przeznaczona dla Czytelników, którzy chcą samodzielnie rozwijać umiejętności programowania. Z powodzeniem może być też używana np. na jedno- lub dwusemestralnych kursach programowania na studiach wyższych.

Krzysztof Barteczko

Warszawa, sierpień 2015