SlideShare a Scribd company logo
1 of 20
Download to read offline
IDZ DO
         PRZYK£ADOWY ROZDZIA£

                           SPIS TRE CI   Efektywne programowanie
                                         w jêzyku Java
           KATALOG KSI¥¯EK
                                         Autor: Joshua Bloch
                      KATALOG ONLINE     T³umaczenie: Pawe³ Gonera
                                         ISBN: 83-7197-989-4
                                         Tytu³ orygina³u: Effective Java Programming Language
       ZAMÓW DRUKOWANY KATALOG           Format: B5, stron: 214
                                         Przyk³ady na ftp: 48 kB
              TWÓJ KOSZYK
                    DODAJ DO KOSZYKA     Java to wspania³e narzêdzie w rêkach programisty. Ale nawet najlepsze narzêdzie mo¿e
                                         zostaæ le u¿yte. Istnieje wiele ksi¹¿ek, które opisuj¹ ten jêzyk programowania
                                         skupiaj¹c siê na przedstawieniu jego sk³adni. Ta ksi¹¿ka jest zupe³nie inna. Adresowana
         CENNIK I INFORMACJE             jest do osób znaj¹cych ju¿ Javê i przedstawia praktyczne zasady pisania efektywnego,
                                         poprawnego kodu.
                   ZAMÓW INFORMACJE      Ka¿da wskazówka omówiona jest w osobnym podrozdziale opisuj¹cym dany problem,
                     O NOWO CIACH        przyk³ady poprawnego (i b³êdnego!) kodu, a tak¿e historie zaczerpniête z bogatego
                                         do wiadczenia autora. Ta ksi¹¿ka zapozna Ciê z idiomami w³a ciwymi jêzykowi Java
                       ZAMÓW CENNIK      oraz z istotnymi z praktycznego punktu widzenia wzorcami projektowymi.


                 CZYTELNIA
          FRAGMENTY KSI¥¯EK ONLINE




Wydawnictwo Helion
ul. Chopina 6
44-100 Gliwice
tel. (32)230-98-63
e-mail: helion@helion.pl
Spis treści
                Słowo wstępne .................................................................................. 7
                Przedmowa........................................................................................ 9
                Wprowadzenie ................................................................................. 11
Rozdział 1. Tworzenie i usuwanie obiektów ........................................................ 15
                Temat 1. Tworzenie statycznych metod factory zamiast konstruktorów..........................15
                Temat 2. Wymuszanie właściwości singleton za pomocą prywatnego konstruktora .......18
                Temat 3. Wykorzystanie konstruktora prywatnego
                 w celu uniemo liwienia utworzenia obiektu ..................................................................20
                Temat 4. Unikanie powielania obiektów...........................................................................21
                Temat 5. Usuwanie niepotrzebnych referencji do obiektów.............................................24
                Temat 6. Unikanie finalizatorów.......................................................................................27
Rozdział 2. Metody wspólne dla wszystkich obiektów......................................... 31
                Temat 7. Zachowanie zało eń w trakcie przedefiniowywania metody equals .................31
                Temat 8. Przedefiniowywanie metody hashCode wraz z equals ......................................39
                Temat 9. Przedefiniowywanie metody toString................................................................44
                Temat 10. Rozsądne przedefiniowywanie metody clone..................................................46
                Temat 11. Implementacja interfejsu Comparable .............................................................53
Rozdział 3. Klasy i interfejsy .............................................................................. 59
                Temat 12. Ograniczanie dostępności klas i ich składników..............................................59
                Temat 13. Zapewnianie niezmienności obiektu................................................................62
                Temat 14. Zastępowanie dziedziczenia kompozycją ........................................................69
                Temat 15. Projektowanie i dokumentowanie klas przeznaczonych do dziedziczenia......74
                Temat 16. Stosowanie interfejsów zamiast klas abstrakcyjnych ......................................78
                Temat 17. Wykorzystanie interfejsów jedynie do definiowania typów............................83
                Temat 18. Zalety stosowania statycznych klas składowych .............................................84
Rozdział 4. Odpowiedniki konstrukcji języka C ................................................... 89
                Temat 19. Zastępowanie struktur klasami.........................................................................89
                Temat 20. Zamiana unii na hierarchię klas .......................................................................91
                Temat 21. Zastępowanie konstrukcji enum za pomocą klas.............................................94
                Temat 22. Zastępowanie wskaźników do funkcji za pomocą klas i interfejsów...................103
Rozdział 5. Metody.......................................................................................... 107
                Temat 23. Sprawdzanie poprawności parametrów .........................................................107
                Temat 24. Defensywne kopiowanie ................................................................................109
                Temat 25. Projektowanie sygnatur metod.......................................................................112
                Temat 26. Rozsądne korzystanie z przecią ania.............................................................114
                Temat 27. Zwracanie pustych tablic zamiast wartości null ............................................118
                Temat 28. Tworzenie komentarzy dokumentujących
                 dla wszystkich udostępnianych elementów API...........................................................120
6                                                                         Efektywne programowanie w języku Java


Rozdział 6. Programowanie.............................................................................. 125
                 Temat 29. Ograniczanie zasięgu zmiennych lokalnych ..................................................125
                 Temat 30. Poznanie i wykorzystywanie bibliotek ..........................................................128
                 Temat 31. Unikanie typów float i double, gdy potrzebne są dokładne wyniki...............131
                 Temat 32. Unikanie typu String, gdy istnieją bardziej odpowiednie typy......................133
                 Temat 33. Problemy z wydajnością przy łączeniu ciągów znaków................................135
                 Temat 34. Odwoływanie się do obiektów poprzez interfejsy .........................................136
                 Temat 35. Stosowanie interfejsów zamiast refleksyjności..............................................137
                 Temat 36. Rozwa ne wykorzystywanie metod natywnych ............................................140
                 Temat 37. Unikanie optymalizacji ..................................................................................141
                 Temat 38. Wykorzystanie ogólnie przyjętych konwencji nazewnictwa .........................144
Rozdział 7. Wyjątki ......................................................................................... 147
                 Temat 39. Wykorzystanie wyjątków w sytuacjach nadzwyczajnych .............................147
                 Temat 40. Stosowanie wyjątków przechwytywalnych i wyjątków czasu wykonania.......149
                 Temat 41. Unikanie niepotrzebnych wyjątków przechwytywalnych .............................151
                 Temat 42. Wykorzystanie wyjątków standardowych .....................................................153
                 Temat 43. Zgłaszanie wyjątków właściwych dla abstrakcji ...........................................155
                 Temat 44. Dokumentowanie wyjątków zgłaszanych przez metodę ...............................157
                 Temat 45. Udostępnianie danych o błędzie ....................................................................158
                 Temat 46. Zachowanie atomowości w przypadku błędu ................................................159
                 Temat 47. Nie ignoruj wyjątków.....................................................................................161
Rozdział 8. Wątki ............................................................................................ 163
                 Temat 48. Synchronizacja dostępu do wspólnych modyfikowalnych danych................163
                 Temat 49. Unikanie nadmiarowej synchronizacji...........................................................168
                 Temat 50. Nigdy nie wywołuj wait poza pętlą................................................................172
                 Temat 51. Unikanie korzystania z systemowego szeregowania wątków........................174
                 Temat 52. Dokumentowanie bezpieczeństwa dla wątków..............................................177
                 Temat 53. Unikanie grup wątków ...................................................................................180
Rozdział 9. Serializacja.................................................................................... 181
                 Temat 54. Implementowanie interfejsu Serializable.......................................................181
                 Temat 55. Wykorzystanie własnej postaci serializowanej..............................................185
                 Temat 56. Defensywne tworzenie metody readObject ...................................................191
                 Temat 57. Tworzenie metody readResolve.....................................................................196
Dodatek A Zasoby .......................................................................................... 199
                 Skorowidz...................................................................................... 203
Rozdział 4.
Odpowiedniki konstrukcji
języka C
   Język programowania Java posiada wiele podobieństw do języka C, ale kilka jego kon-
   strukcji zostało pominiętych. W większości przypadków oczywiste jest, dlaczego dana
   konstrukcja została pominięta i w jaki sposób mo na sobie bez niej radzić. W rozdziale
   tym zaproponujemy zamienniki dla kilku pominiętych konstrukcji języka C, których
   zastąpienie nie jest tak oczywiste.

   Najczęstszym wątkiem, który przewija się przez cały ten rozdział, jest twierdzenie, e
   wszystkie pominięte konstrukcje były zorientowane na dane, a nie zorientowane obiek-
   towo. Język programowania Java zawiera bardzo wydajny system typów i propono-
   wane zamienniki w pełni korzystają z tego systemu w celu zapewnienia wy szego
   stopnia abstrakcji ni konstrukcje języka C, które są przez nie zastępowane.

   Nawet je eli zdecydujesz się na pominięcie tego rozdziału, warto zapoznać się z tema-
   tem 21., poświęconym typowi wyliczeniowemu, który zastępuje konstrukcję GPWO, dostęp-
   ną w języku C. Wzorzec ten nie był powszechnie znany w czasie pisania tej ksią ki,
   a posiada znaczną przewagę nad obecnie stosowanymi rozwiązaniami tego problemu.



Temat 19. Zastępowanie struktur klasami
   Konstrukcja UVTWEV języka C została usunięta z języka Java, poniewa za pomocą klasy
   mo na zrealizować wszystko to, co potrafi struktura, a nawet więcej. Struktura jedy-
   nie grupuje kilka pól danych w jeden obiekt — klasa zawiera operacje wykonywane na
   wynikowym obiekcie i pozwala na ukrycie pól danych przed u ytkownikiem obiektu.
   Inaczej mówiąc, klasa hermetyzuje dane w obiekcie i umo liwia dostęp do nich jedy-
   nie za pomocą metod, co pozwala twórcy klasy na swobodną zmianę reprezentacji
   danych w późniejszym czasie (temat 12.).

   W czasie pierwszych pokazów języka Java niektórzy programiści korzystający z języka
   C uwa ali, e klasy są zbyt obszerne, aby w pewnych sytuacjach zastąpić struktury.
90                                                 Efektywne programowanie w języku Java


     Nie będziemy się zajmowali tym problemem. Zdegenerowane klasy składające się jedynie
     z pól danych są pewnym przybli eniem struktur z języka C:
        6CMKG FGIGPGTQYCPG MNCU[ PKG RQYKPP[ D[è RWDNKEPG
       ENCUU 2QKPV ]
         RWDNKE HNQCV Z
         RWDNKE HNQCV [
       _

     Poniewa takie klasy pozwalają na dostęp do swoich pól, nie pozwalają na skorzysta-
     nie z zalet hermetyzacji. Nie mo na zmienić reprezentacji danych w takiej klasie bez
     zmiany API, nie mo na wymuszać adnych ograniczeń oraz nie mo na podejmować
     dodatkowych zadań podczas modyfikacji pola. Ortodoksyjni programiści obiektowi
     uwa ają, e takie klasy są zakazane i powinny zawsze być zastępowane klasami z polami
     prywatnymi oraz publicznymi metodami je udostępniającymi:
        *GTOGV[QYCPC MNCUC Q HWPMELCEJ UVTWMVWT[
       ENCUU 2QKPV ]
         RTKXCVG HNQCV Z
         RTKXCVG HNQCV [

           RWDNKE 2QKPV
HNQCV Z HNQCV [ ]
             VJKUZ  Z
             VJKU[  [
           _

           RWDNKE HNQCV IGV:
 ]TGVWTP Z _
           RWDNKE HNQCV IGV;
 ]TGVWTP [ _

           RWDNKE HNQCV UGV:
 ]VJKUZ  Z _
           RWDNKE HNQCV UGV;
 ]VJKU[  [ _
       _

     Oczywiście twierdzenie to jest prawdziwe w odniesieniu do klas publicznych — je eli
     klasa jest dostępna spoza swojego pakietu, rozwa ny programista powinien zabezpie-
     czyć sobie mo liwość zmiany wewnętrznej reprezentacji danych. Je eli klasa publiczna
     udostępnia swoje pola, nie ma mo liwości zmiany reprezentacji danych, poniewa kod
     klientów, korzystający z klasy publicznej, mo e być ju rozesłany po całym świecie.

     Je eli jednak klasa jest prywatna w ramach pakietu lub jest to prywatna klasa zagnie -
     d ona, nie ma nic złego w bezpośrednim udostępnieniu pól danych — zakładając, e
     naprawdę opisują abstrakcję definiowaną przez klasę. Podejście to generuje mniej kodu
     ni wykorzystanie metod dostępowych, zarówno w definicji klasy, jak i w kodzie klientów
     ją wykorzystujących. Poniewa kod klientów jest ściśle związany z wewnętrzną repre-
     zentacją klasy, jest on ograniczony do pakietu, w którym klasa ta jest zdefiniowana.
     W przypadku, gdy konieczna jest zmiana reprezentacji danych, mo liwe jest wpro-
     wadzenie zmian bez konieczności zmiany kodu poza pakietem. W przypadku prywat-
     nej klasy zagnie d onej zasięg zmian jest ograniczony do klasy nadrzędnej.

     Kilka klas w bibliotekach języka Java nie dotrzymuje zalecenia, aby klasy publiczne nie
     udostępniały bezpośrednio swoich pól. Przykładami takich klas są klasy 2QKPV i KOGPUKQP
     z pakietu LCXCCYV. Przykłady te nie powinny być naśladowane — nale ałoby raczej
Rozdział 4. ♦ Odpowiedniki konstrukcji języka C                                          91


        wskazywać je jako przykład negatywny. W temacie 37. opisany został przykład poka-
        zujący, jak udostępnienie pól w klasie KOGPUKQP spowodowało problemy z wydajno-
        ścią. Problemy te nie mogą zostać usunięte bez wpływania na kod klientów.



Temat 20. Zamiana unii na hierarchię klas
        Konstrukcja języka C — WPKQP — jest najczęściej wykorzystywana do definiowania
        struktur, umo liwiających przechowywanie więcej ni jednego typu danych. Struktura
        taka zwykle posiada co najmniej dwa pola — unię i znacznik. Pole znacznika jest
        zwykłym polem, wykorzystywanym do wskazywania aktualnego typu danych, prze-
        chowywanego przez unię. Znacznik jest najczęściej typu wyliczeniowego (GPWO).
        Struktura zawierająca unię i znacznik jest czasami nazywaną unią z dyskryminatorem.

        Poni ej przedstawiamy przykład definicji typu UJCRGAV, zapisany w języku C. Jest to
        unia z dyskryminatorem, reprezentująca prostokąt lub koło. Funkcja CTGC na podstawie
        wskaźnika do struktury UJCRGAV zwraca pole figury lub , je eli struktura zawiera
        nieprawidłowe dane.
7PKC  F[UMT[OKPCVQTGO
KPENWFG OCVJJ
          V[RGFGH GPWO ]4'%6#0).' %+4%.'_ UJCRG6[RGAV

          V[RGFGH UVTWEV ]
              FQWDNG NGPIVJ
              FQWDNG YKFVJ
          _ TGEVCPINGKOGPUKQPUAV

          V[RGFGH UVTWEV ]
              FQWDNG TCFKWU
          _ EKTENGKOGPUKQPUAV

          V[RGFGH UVTWEV ]
              UJCRG6[RGAV VCI
              WPKQP ]
                  TGEVCPINGKOGPUKQPUAV TGEVCPING
                  EKTENGKOGPUKQPUAV    EKTENG
              _ FKOGPUKQPU
          _ UJCRGAV

          FQWDNG CTGC
UJCRGAV
UJCRG ]
              UYKVEJ
UJCRG VCI ]
                ECUG 4'%6#0).' ]
                  FQWDNG NGPIVJ  UJCRG FKOGPUKQPUTGEVCPINGNGPIVJ
                  FQWDNG YKFVJ  UJCRG FKOGPUKQPUTGEVCPINGYKFVJ
                  TGVWTP NGPIVJ
YKFVJ
                _
                ECUG %+4%.' ]
                  FQWDNG T  UJCRG FKOGPUKQPUEKTENGTCFKWU
                  TGVWTP /A2+
T
T
                _
                FGHCWNV TGVWTP
0KGRTCYKF QY[ PCEPKM
_
          _
92                                                 Efektywne programowanie w języku Java


     Projektanci języka Java postanowili nie wprowadzać konstrukcji WPKQP, poniewa ist-
     nieje du o lepszy mechanizm definiowania typów umo liwiających reprezentowanie
     ró nych typów — dziedziczenie. Unie z dyskryminatorem są jedynie mało wydajną
     imitacją hierarchii klas.

     Aby zamienić unię z dyskryminatorem na hierarchię klas, nale y zdefiniować klasę
     abstrakcyjną zawierającą metody abstrakcyjne dla ka dej operacji, której działanie
     jest zale ne od wartości znacznika. We wcześniejszym przykładzie przedstawiona
     była tylko jedna taka operacja — CTGC. Ta klasa abstrakcyjna staje się korzeniem hie-
     rarchii klas. Je eli istnieją inne operacje, niezale ne od wartości znacznika, nale y
     zdefiniować odpowiednie metody w klasie bazowej. Podobnie, je eli w unii z dyskrymi-
     natorem istnieją pola danych poza znacznikiem i unią, reprezentujące typy danych
     wspólne dla wszystkich typów, powinny być one dodane do klasy bazowej. W naszym
     przykładzie nie było adnych składników niezale nych od typów.

     Następnie dla ka dego typu reprezentowanego w unii z dyskryminatorem definiujemy
     klasy, dziedziczące z klasy bazowej. W naszym przykładzie typami tymi są: koło i prosto-
     kąt. W ka dej z klas podrzędnych nale y umieścić pola danych odpowiednie dla jej typu.
     W naszym przykładzie dla koła jest to promień, a dla prostokąta długość i szerokość. Na
     koniec definiujemy odpowiednie implementacje metod abstrakcyjnych z klasy bazowej.
     Poni ej przedstawiamy hierarchię klas dla naszego przykładu unii z dyskryminatorem:
       CDUVTCEV ENCUU 5JCRG ]
           CDUVTCEV FQWDNG CTGC

       _

       ENCUU %KTENG GZVGPFU 5JCRG ]
           HKPCN FQWDNG TCFKWU

           %KTENG
FQWDNG TCFKWU ] VJKUTCFKWU  TCFKWU _

           FQWDNG CTGC
 ] TGVWTP /CVJ2+
TCFKWU
TCFKWU _
       _

       ENCUU 4GEVCPING GZVGPFU 5JCRG ]
           HKPCN FQWDNG NGPIVJ
           HKPCN FQWDNG YKFVJ

           4GEVCPING
FQWDNG NGPIVJ FQWDNG YKFVJ ]
               VJKUNGPIVJ  NGPIVJ
               VJKUYKFVJ  YKFVJ
           _

           FQWDNG CTGC
 ] TGVWTP NGPIVJ
YKFVJ _
       _

     Hierarchia klas posiada wiele zalet w porównaniu z unią z dyskryminatorem. Najwa -
     niejszą z nich jest ta, e hierarchia klas zapewnia kontrolę typów. W naszym przykładzie
     ka dy obiekt 5JCRG mo e być jedynie prawidłowym obiektem %KTENG lub 4GEVCPING.
     Bardzo prosto wygenerować strukturę UJCRGAV, która będzie całkowicie nieprzydatna,
     poniewa połączenie pomiędzy znacznikiem i unią nie jest wymuszane przez język
     programowania. Je eli znacznik wskazuje, e UJCRGAV reprezentuje prostokąt, ale unia
Rozdział 4. ♦ Odpowiedniki konstrukcji języka C                                               93


        została zainicjowana danymi koła, wszystko mo e się zdarzyć. Nawet, gdy unia z dys-
        kryminatorem zostanie prawidłowo zainicjowana, mo liwe jest omyłkowe przekazanie
        jej do funkcji nieodpowiedniej dla danej wartości znacznika.

        Drugą zaletą hierarchii klas jest łatwość rozszerzania, nawet o wiele niezale nie działa-
        jących części. Aby rozszerzyć hierarchię klas, wystarczy dodać nową kasę pochodną.
        Je eli zapomnisz zdefiniować jednej z metod abstrakcyjnych, natychmiast wska e Ci
        to kompilator. Aby rozbudować unię z dyskryminatorem, nale y mieć dostęp do kodu
        źródłowego. Musisz dodać nową wartość do typu GPWO oraz nową gałąź do instrukcji
        UYKVEJ w ka dej funkcji operującej na unii. Na koniec musisz skompilować kod. Je eli
        w którejś funkcji zapomnisz dodać nowego przypadku, kompilator nie będzie w stanie
        tego wykryć. Pozostaje umieszczenie w kodzie kontroli niespodziewanych wartości
        znacznika i generowanie w takich sytuacjach komunikatów błędów.

        Czwartą zaletą hierarchii klas jest mo liwość odwzorowania naturalnych relacji hierar-
        chicznych pomiędzy typami, co pozwala na zwiększenie elastyczności i lepszej kontroli
        typów w czasie kompilacji. Załó my, e do naszego oryginalnego przykładu chcemy
        dodać obsługę kwadratów. W hierarchii klas mo emy odwzorować fakt, e kwadrat
        jest specjalnym rodzajem prostokąta (zakładając, e oba są niezmienne):
          ENCUU 5SWCTG GZVGPFU 4GEVCPING ]
              5SWCTG
FQWDNG UKFG ]
                  UWRGT
UKFG UKFG
              _

               FQWDNG UKFG
 ]
                   TGVWTP NGPIVJ  OQ G D[è TÎYPKG YKFVJ
               _
          _

        Przedstawiona hierarchia klas nie jest jedynym rozwiązaniem naszego problemu. Hierar-
        chia ta powstała po podjęciu kilku decyzji, o których warto wspomnieć. Klasy w hierar-
        chii, poza 5SWCTG, udostępniają swoje pola, nie oferując metod dostępowych. W przy-
        padku klas publicznych jest to nie do zaakceptowania, ale nam zale ało na zwięzłości
        kodu (temat 19.). Klasy te są niezmienne. Czasami nie jest to najlepsze, jednak naj-
        częściej właśnie takie rozwiązanie jest właściwe (temat 13.).

        Poniewa język Java nie zawiera konstrukcji WPKQP, mo na uwa ać, e nie ma niebez-
        pieczeństwa utworzenia unii z dyskryminatorem. Mo liwe jest jednak napisanie kodu,
        który będzie posiadał te same wady. Je eli kiedykolwiek będziesz chciał napisać klasę
        z polem znacznikowym, nale y pomyśleć o eliminacji pola znacznikowego przez mo-
        dyfikację hierarchii klas.

        Innym zastosowaniem konstrukcji WPKQP w języku C, całkowicie niezwiązanym z uniami
        z dyskryminatorem, jest mo liwość oglądania wewnętrznej reprezentacji danych poprzez
        umyślne omijanie systemu typów. Metoda ta demonstrowana jest przez poni szy fragment
        kodu w języku C, który drukuje wewnętrzną postać liczby HNQCV w postaci szesnastkowej:
          WPKQP ]
            HNQCV H
            KPV DKVU
94                                                Efektywne programowanie w języku Java


       _ UNGCG

       UNGCGH  G

More Related Content

What's hot

Programowanie w języku C. Szybki start
Programowanie w języku C. Szybki startProgramowanie w języku C. Szybki start
Programowanie w języku C. Szybki startWydawnictwo Helion
 
Po prostu PHP. Techniki zaawansowane
Po prostu PHP. Techniki zaawansowanePo prostu PHP. Techniki zaawansowane
Po prostu PHP. Techniki zaawansowaneWydawnictwo Helion
 
Metody i-techniki-szybkiego-czytania
Metody i-techniki-szybkiego-czytaniaMetody i-techniki-szybkiego-czytania
Metody i-techniki-szybkiego-czytaniaPrzemysław Wolny
 
Praktyczny kurs Java. Wydanie II
Praktyczny kurs Java. Wydanie IIPraktyczny kurs Java. Wydanie II
Praktyczny kurs Java. Wydanie IIWydawnictwo Helion
 
Helion.2005.php.i.my sql.tworzenie.stron.www.vademecum.profesjonalisty.wyd3
Helion.2005.php.i.my sql.tworzenie.stron.www.vademecum.profesjonalisty.wyd3Helion.2005.php.i.my sql.tworzenie.stron.www.vademecum.profesjonalisty.wyd3
Helion.2005.php.i.my sql.tworzenie.stron.www.vademecum.profesjonalisty.wyd3nicollabre
 
Adobe Flash CS3 Professional. Oficjalny podręcznik
Adobe Flash CS3 Professional. Oficjalny podręcznikAdobe Flash CS3 Professional. Oficjalny podręcznik
Adobe Flash CS3 Professional. Oficjalny podręcznikWydawnictwo Helion
 
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatce
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatceFlash CS3 Professional PL. Techniki zaawansowane. Klatka po klatce
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatceWydawnictwo Helion
 

What's hot (20)

Programowanie w języku C. Szybki start
Programowanie w języku C. Szybki startProgramowanie w języku C. Szybki start
Programowanie w języku C. Szybki start
 
ABC Delphi 6
ABC Delphi 6ABC Delphi 6
ABC Delphi 6
 
Praktyczny kurs asemblera
Praktyczny kurs asembleraPraktyczny kurs asemblera
Praktyczny kurs asemblera
 
Po prostu PHP. Techniki zaawansowane
Po prostu PHP. Techniki zaawansowanePo prostu PHP. Techniki zaawansowane
Po prostu PHP. Techniki zaawansowane
 
Java 2. Podstawy
Java 2. PodstawyJava 2. Podstawy
Java 2. Podstawy
 
Metody i-techniki-szybkiego-czytania
Metody i-techniki-szybkiego-czytaniaMetody i-techniki-szybkiego-czytania
Metody i-techniki-szybkiego-czytania
 
Praktyczny kurs Java. Wydanie II
Praktyczny kurs Java. Wydanie IIPraktyczny kurs Java. Wydanie II
Praktyczny kurs Java. Wydanie II
 
Po prostu Flash MX 2004
Po prostu Flash MX 2004Po prostu Flash MX 2004
Po prostu Flash MX 2004
 
C#. Ćwiczenia
C#. ĆwiczeniaC#. Ćwiczenia
C#. Ćwiczenia
 
Helion.2005.php.i.my sql.tworzenie.stron.www.vademecum.profesjonalisty.wyd3
Helion.2005.php.i.my sql.tworzenie.stron.www.vademecum.profesjonalisty.wyd3Helion.2005.php.i.my sql.tworzenie.stron.www.vademecum.profesjonalisty.wyd3
Helion.2005.php.i.my sql.tworzenie.stron.www.vademecum.profesjonalisty.wyd3
 
Adobe Flash CS3 Professional. Oficjalny podręcznik
Adobe Flash CS3 Professional. Oficjalny podręcznikAdobe Flash CS3 Professional. Oficjalny podręcznik
Adobe Flash CS3 Professional. Oficjalny podręcznik
 
ABC Delphi 7
ABC Delphi 7ABC Delphi 7
ABC Delphi 7
 
JavaScript. Pierwsze starcie
JavaScript. Pierwsze starcieJavaScript. Pierwsze starcie
JavaScript. Pierwsze starcie
 
Linux. Kurs. Wydanie II
Linux. Kurs. Wydanie IILinux. Kurs. Wydanie II
Linux. Kurs. Wydanie II
 
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatce
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatceFlash CS3 Professional PL. Techniki zaawansowane. Klatka po klatce
Flash CS3 Professional PL. Techniki zaawansowane. Klatka po klatce
 
Perl. Ćwiczenia
Perl. ĆwiczeniaPerl. Ćwiczenia
Perl. Ćwiczenia
 
eXtreme programming
eXtreme programmingeXtreme programming
eXtreme programming
 
PHP5. Praktyczny kurs
PHP5. Praktyczny kursPHP5. Praktyczny kurs
PHP5. Praktyczny kurs
 
C++Builder 6. Ćwiczenia
C++Builder 6. ĆwiczeniaC++Builder 6. Ćwiczenia
C++Builder 6. Ćwiczenia
 
Prolog. Programowanie
Prolog. ProgramowanieProlog. Programowanie
Prolog. Programowanie
 

Similar to Efektywne programowanie w języku Java

Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązań
Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązańWyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązań
Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązańWydawnictwo Helion
 
Czytanie kodu. Punkt widzenia twórców oprogramowania open source
Czytanie kodu. Punkt widzenia twórców oprogramowania open sourceCzytanie kodu. Punkt widzenia twórców oprogramowania open source
Czytanie kodu. Punkt widzenia twórców oprogramowania open sourceWydawnictwo Helion
 
Master Thesis - Comparative analysis of programming Environments based on Rub...
Master Thesis - Comparative analysis of programming Environments based on Rub...Master Thesis - Comparative analysis of programming Environments based on Rub...
Master Thesis - Comparative analysis of programming Environments based on Rub...Adam Skołuda
 
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowychTworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowychWydawnictwo Helion
 
Po prostu JavaScript i Ajax. Wydanie VI
Po prostu JavaScript i Ajax. Wydanie VIPo prostu JavaScript i Ajax. Wydanie VI
Po prostu JavaScript i Ajax. Wydanie VIWydawnictwo Helion
 
Język C++. Gotowe rozwiązania dla programistów
Język C++. Gotowe rozwiązania dla programistówJęzyk C++. Gotowe rozwiązania dla programistów
Język C++. Gotowe rozwiązania dla programistówWydawnictwo Helion
 
JavaScript dla każdego. Wydanie IV
JavaScript dla każdego. Wydanie IVJavaScript dla każdego. Wydanie IV
JavaScript dla każdego. Wydanie IVWydawnictwo Helion
 
PHP. Programowanie. Wydanie III
PHP. Programowanie. Wydanie IIIPHP. Programowanie. Wydanie III
PHP. Programowanie. Wydanie IIIWydawnictwo Helion
 
Pajączek 5 NxG. Oficjalny podręcznik
Pajączek 5 NxG. Oficjalny podręcznikPajączek 5 NxG. Oficjalny podręcznik
Pajączek 5 NxG. Oficjalny podręcznikWydawnictwo Helion
 

Similar to Efektywne programowanie w języku Java (19)

Java 2. Techniki zaawansowane
Java 2. Techniki zaawansowaneJava 2. Techniki zaawansowane
Java 2. Techniki zaawansowane
 
Java. Rozmówki
Java. RozmówkiJava. Rozmówki
Java. Rozmówki
 
Praktyczny kurs Java
Praktyczny kurs JavaPraktyczny kurs Java
Praktyczny kurs Java
 
Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązań
Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązańWyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązań
Wyjątkowy język C++. 40 nowych łamigłówek, zadań programistycznych i rozwiązań
 
Uczta programistów
Uczta programistówUczta programistów
Uczta programistów
 
CorelDraw X3 PL. Kurs
CorelDraw X3 PL. KursCorelDraw X3 PL. Kurs
CorelDraw X3 PL. Kurs
 
Czytanie kodu. Punkt widzenia twórców oprogramowania open source
Czytanie kodu. Punkt widzenia twórców oprogramowania open sourceCzytanie kodu. Punkt widzenia twórców oprogramowania open source
Czytanie kodu. Punkt widzenia twórców oprogramowania open source
 
Delphi. Szybki start
Delphi. Szybki startDelphi. Szybki start
Delphi. Szybki start
 
Master Thesis - Comparative analysis of programming Environments based on Rub...
Master Thesis - Comparative analysis of programming Environments based on Rub...Master Thesis - Comparative analysis of programming Environments based on Rub...
Master Thesis - Comparative analysis of programming Environments based on Rub...
 
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowychTworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
Tworzenie aplikacji dla Windows. Od prostych programów do gier komputerowych
 
JavaScript. Projekty
JavaScript. ProjektyJavaScript. Projekty
JavaScript. Projekty
 
Visual Basic .NET. Ćwiczenia
Visual Basic .NET. ĆwiczeniaVisual Basic .NET. Ćwiczenia
Visual Basic .NET. Ćwiczenia
 
Po prostu JavaScript i Ajax. Wydanie VI
Po prostu JavaScript i Ajax. Wydanie VIPo prostu JavaScript i Ajax. Wydanie VI
Po prostu JavaScript i Ajax. Wydanie VI
 
Język C++. Gotowe rozwiązania dla programistów
Język C++. Gotowe rozwiązania dla programistówJęzyk C++. Gotowe rozwiązania dla programistów
Język C++. Gotowe rozwiązania dla programistów
 
JavaScript dla każdego. Wydanie IV
JavaScript dla każdego. Wydanie IVJavaScript dla każdego. Wydanie IV
JavaScript dla każdego. Wydanie IV
 
PHP. Programowanie. Wydanie III
PHP. Programowanie. Wydanie IIIPHP. Programowanie. Wydanie III
PHP. Programowanie. Wydanie III
 
Po prostu PowerPoint 2003 PL
Po prostu PowerPoint 2003 PLPo prostu PowerPoint 2003 PL
Po prostu PowerPoint 2003 PL
 
Po prostu PowerPoint 2007 PL
Po prostu PowerPoint 2007 PLPo prostu PowerPoint 2007 PL
Po prostu PowerPoint 2007 PL
 
Pajączek 5 NxG. Oficjalny podręcznik
Pajączek 5 NxG. Oficjalny podręcznikPajączek 5 NxG. Oficjalny podręcznik
Pajączek 5 NxG. Oficjalny podręcznik
 

More from Wydawnictwo Helion

Tworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyTworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyWydawnictwo Helion
 
Blog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikBlog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikWydawnictwo Helion
 
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktycznePozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczneWydawnictwo Helion
 
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesieE-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesieWydawnictwo Helion
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsWydawnictwo Helion
 
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IICo potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IIWydawnictwo Helion
 
Makrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuMakrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuWydawnictwo Helion
 
Ajax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningAjax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningWydawnictwo Helion
 
PowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykPowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykWydawnictwo Helion
 
Serwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaSerwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaWydawnictwo Helion
 
Serwer SQL 2008. Administracja i programowanie
Serwer SQL 2008. Administracja i programowanieSerwer SQL 2008. Administracja i programowanie
Serwer SQL 2008. Administracja i programowanieWydawnictwo Helion
 
USB. Praktyczne programowanie z Windows API w C++
USB. Praktyczne programowanie z Windows API w C++USB. Praktyczne programowanie z Windows API w C++
USB. Praktyczne programowanie z Windows API w C++Wydawnictwo Helion
 

More from Wydawnictwo Helion (20)

Tworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. ProjektyTworzenie filmów w Windows XP. Projekty
Tworzenie filmów w Windows XP. Projekty
 
Blog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnikBlog, więcej niż internetowy pamiętnik
Blog, więcej niż internetowy pamiętnik
 
Access w biurze i nie tylko
Access w biurze i nie tylkoAccess w biurze i nie tylko
Access w biurze i nie tylko
 
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktycznePozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
Pozycjonowanie i optymalizacja stron WWW. Ćwiczenia praktyczne
 
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesieE-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
E-wizerunek. Internet jako narzędzie kreowania image'u w biznesie
 
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla WindowsMicrosoft Visual C++ 2008. Tworzenie aplikacji dla Windows
Microsoft Visual C++ 2008. Tworzenie aplikacji dla Windows
 
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie IICo potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
Co potrafi Twój iPhone? Podręcznik użytkownika. Wydanie II
 
Makrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółuMakrofotografia. Magia szczegółu
Makrofotografia. Magia szczegółu
 
Windows PowerShell. Podstawy
Windows PowerShell. PodstawyWindows PowerShell. Podstawy
Windows PowerShell. Podstawy
 
Ajax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny treningAjax, JavaScript i PHP. Intensywny trening
Ajax, JavaScript i PHP. Intensywny trening
 
PowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktykPowerPoint 2007 PL. Seria praktyk
PowerPoint 2007 PL. Seria praktyk
 
Excel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktykExcel 2007 PL. Seria praktyk
Excel 2007 PL. Seria praktyk
 
Access 2007 PL. Seria praktyk
Access 2007 PL. Seria praktykAccess 2007 PL. Seria praktyk
Access 2007 PL. Seria praktyk
 
Word 2007 PL. Seria praktyk
Word 2007 PL. Seria praktykWord 2007 PL. Seria praktyk
Word 2007 PL. Seria praktyk
 
Serwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacjaSerwisy społecznościowe. Budowa, administracja i moderacja
Serwisy społecznościowe. Budowa, administracja i moderacja
 
AutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PLAutoCAD 2008 i 2008 PL
AutoCAD 2008 i 2008 PL
 
Bazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcieBazy danych. Pierwsze starcie
Bazy danych. Pierwsze starcie
 
Inventor. Pierwsze kroki
Inventor. Pierwsze krokiInventor. Pierwsze kroki
Inventor. Pierwsze kroki
 
Serwer SQL 2008. Administracja i programowanie
Serwer SQL 2008. Administracja i programowanieSerwer SQL 2008. Administracja i programowanie
Serwer SQL 2008. Administracja i programowanie
 
USB. Praktyczne programowanie z Windows API w C++
USB. Praktyczne programowanie z Windows API w C++USB. Praktyczne programowanie z Windows API w C++
USB. Praktyczne programowanie z Windows API w C++
 

Efektywne programowanie w języku Java

  • 1. IDZ DO PRZYK£ADOWY ROZDZIA£ SPIS TRE CI Efektywne programowanie w jêzyku Java KATALOG KSI¥¯EK Autor: Joshua Bloch KATALOG ONLINE T³umaczenie: Pawe³ Gonera ISBN: 83-7197-989-4 Tytu³ orygina³u: Effective Java Programming Language ZAMÓW DRUKOWANY KATALOG Format: B5, stron: 214 Przyk³ady na ftp: 48 kB TWÓJ KOSZYK DODAJ DO KOSZYKA Java to wspania³e narzêdzie w rêkach programisty. Ale nawet najlepsze narzêdzie mo¿e zostaæ le u¿yte. Istnieje wiele ksi¹¿ek, które opisuj¹ ten jêzyk programowania skupiaj¹c siê na przedstawieniu jego sk³adni. Ta ksi¹¿ka jest zupe³nie inna. Adresowana CENNIK I INFORMACJE jest do osób znaj¹cych ju¿ Javê i przedstawia praktyczne zasady pisania efektywnego, poprawnego kodu. ZAMÓW INFORMACJE Ka¿da wskazówka omówiona jest w osobnym podrozdziale opisuj¹cym dany problem, O NOWO CIACH przyk³ady poprawnego (i b³êdnego!) kodu, a tak¿e historie zaczerpniête z bogatego do wiadczenia autora. Ta ksi¹¿ka zapozna Ciê z idiomami w³a ciwymi jêzykowi Java ZAMÓW CENNIK oraz z istotnymi z praktycznego punktu widzenia wzorcami projektowymi. CZYTELNIA FRAGMENTY KSI¥¯EK ONLINE Wydawnictwo Helion ul. Chopina 6 44-100 Gliwice tel. (32)230-98-63 e-mail: helion@helion.pl
  • 2. Spis treści Słowo wstępne .................................................................................. 7 Przedmowa........................................................................................ 9 Wprowadzenie ................................................................................. 11 Rozdział 1. Tworzenie i usuwanie obiektów ........................................................ 15 Temat 1. Tworzenie statycznych metod factory zamiast konstruktorów..........................15 Temat 2. Wymuszanie właściwości singleton za pomocą prywatnego konstruktora .......18 Temat 3. Wykorzystanie konstruktora prywatnego w celu uniemo liwienia utworzenia obiektu ..................................................................20 Temat 4. Unikanie powielania obiektów...........................................................................21 Temat 5. Usuwanie niepotrzebnych referencji do obiektów.............................................24 Temat 6. Unikanie finalizatorów.......................................................................................27 Rozdział 2. Metody wspólne dla wszystkich obiektów......................................... 31 Temat 7. Zachowanie zało eń w trakcie przedefiniowywania metody equals .................31 Temat 8. Przedefiniowywanie metody hashCode wraz z equals ......................................39 Temat 9. Przedefiniowywanie metody toString................................................................44 Temat 10. Rozsądne przedefiniowywanie metody clone..................................................46 Temat 11. Implementacja interfejsu Comparable .............................................................53 Rozdział 3. Klasy i interfejsy .............................................................................. 59 Temat 12. Ograniczanie dostępności klas i ich składników..............................................59 Temat 13. Zapewnianie niezmienności obiektu................................................................62 Temat 14. Zastępowanie dziedziczenia kompozycją ........................................................69 Temat 15. Projektowanie i dokumentowanie klas przeznaczonych do dziedziczenia......74 Temat 16. Stosowanie interfejsów zamiast klas abstrakcyjnych ......................................78 Temat 17. Wykorzystanie interfejsów jedynie do definiowania typów............................83 Temat 18. Zalety stosowania statycznych klas składowych .............................................84 Rozdział 4. Odpowiedniki konstrukcji języka C ................................................... 89 Temat 19. Zastępowanie struktur klasami.........................................................................89 Temat 20. Zamiana unii na hierarchię klas .......................................................................91 Temat 21. Zastępowanie konstrukcji enum za pomocą klas.............................................94 Temat 22. Zastępowanie wskaźników do funkcji za pomocą klas i interfejsów...................103 Rozdział 5. Metody.......................................................................................... 107 Temat 23. Sprawdzanie poprawności parametrów .........................................................107 Temat 24. Defensywne kopiowanie ................................................................................109 Temat 25. Projektowanie sygnatur metod.......................................................................112 Temat 26. Rozsądne korzystanie z przecią ania.............................................................114 Temat 27. Zwracanie pustych tablic zamiast wartości null ............................................118 Temat 28. Tworzenie komentarzy dokumentujących dla wszystkich udostępnianych elementów API...........................................................120
  • 3. 6 Efektywne programowanie w języku Java Rozdział 6. Programowanie.............................................................................. 125 Temat 29. Ograniczanie zasięgu zmiennych lokalnych ..................................................125 Temat 30. Poznanie i wykorzystywanie bibliotek ..........................................................128 Temat 31. Unikanie typów float i double, gdy potrzebne są dokładne wyniki...............131 Temat 32. Unikanie typu String, gdy istnieją bardziej odpowiednie typy......................133 Temat 33. Problemy z wydajnością przy łączeniu ciągów znaków................................135 Temat 34. Odwoływanie się do obiektów poprzez interfejsy .........................................136 Temat 35. Stosowanie interfejsów zamiast refleksyjności..............................................137 Temat 36. Rozwa ne wykorzystywanie metod natywnych ............................................140 Temat 37. Unikanie optymalizacji ..................................................................................141 Temat 38. Wykorzystanie ogólnie przyjętych konwencji nazewnictwa .........................144 Rozdział 7. Wyjątki ......................................................................................... 147 Temat 39. Wykorzystanie wyjątków w sytuacjach nadzwyczajnych .............................147 Temat 40. Stosowanie wyjątków przechwytywalnych i wyjątków czasu wykonania.......149 Temat 41. Unikanie niepotrzebnych wyjątków przechwytywalnych .............................151 Temat 42. Wykorzystanie wyjątków standardowych .....................................................153 Temat 43. Zgłaszanie wyjątków właściwych dla abstrakcji ...........................................155 Temat 44. Dokumentowanie wyjątków zgłaszanych przez metodę ...............................157 Temat 45. Udostępnianie danych o błędzie ....................................................................158 Temat 46. Zachowanie atomowości w przypadku błędu ................................................159 Temat 47. Nie ignoruj wyjątków.....................................................................................161 Rozdział 8. Wątki ............................................................................................ 163 Temat 48. Synchronizacja dostępu do wspólnych modyfikowalnych danych................163 Temat 49. Unikanie nadmiarowej synchronizacji...........................................................168 Temat 50. Nigdy nie wywołuj wait poza pętlą................................................................172 Temat 51. Unikanie korzystania z systemowego szeregowania wątków........................174 Temat 52. Dokumentowanie bezpieczeństwa dla wątków..............................................177 Temat 53. Unikanie grup wątków ...................................................................................180 Rozdział 9. Serializacja.................................................................................... 181 Temat 54. Implementowanie interfejsu Serializable.......................................................181 Temat 55. Wykorzystanie własnej postaci serializowanej..............................................185 Temat 56. Defensywne tworzenie metody readObject ...................................................191 Temat 57. Tworzenie metody readResolve.....................................................................196 Dodatek A Zasoby .......................................................................................... 199 Skorowidz...................................................................................... 203
  • 4. Rozdział 4. Odpowiedniki konstrukcji języka C Język programowania Java posiada wiele podobieństw do języka C, ale kilka jego kon- strukcji zostało pominiętych. W większości przypadków oczywiste jest, dlaczego dana konstrukcja została pominięta i w jaki sposób mo na sobie bez niej radzić. W rozdziale tym zaproponujemy zamienniki dla kilku pominiętych konstrukcji języka C, których zastąpienie nie jest tak oczywiste. Najczęstszym wątkiem, który przewija się przez cały ten rozdział, jest twierdzenie, e wszystkie pominięte konstrukcje były zorientowane na dane, a nie zorientowane obiek- towo. Język programowania Java zawiera bardzo wydajny system typów i propono- wane zamienniki w pełni korzystają z tego systemu w celu zapewnienia wy szego stopnia abstrakcji ni konstrukcje języka C, które są przez nie zastępowane. Nawet je eli zdecydujesz się na pominięcie tego rozdziału, warto zapoznać się z tema- tem 21., poświęconym typowi wyliczeniowemu, który zastępuje konstrukcję GPWO, dostęp- ną w języku C. Wzorzec ten nie był powszechnie znany w czasie pisania tej ksią ki, a posiada znaczną przewagę nad obecnie stosowanymi rozwiązaniami tego problemu. Temat 19. Zastępowanie struktur klasami Konstrukcja UVTWEV języka C została usunięta z języka Java, poniewa za pomocą klasy mo na zrealizować wszystko to, co potrafi struktura, a nawet więcej. Struktura jedy- nie grupuje kilka pól danych w jeden obiekt — klasa zawiera operacje wykonywane na wynikowym obiekcie i pozwala na ukrycie pól danych przed u ytkownikiem obiektu. Inaczej mówiąc, klasa hermetyzuje dane w obiekcie i umo liwia dostęp do nich jedy- nie za pomocą metod, co pozwala twórcy klasy na swobodną zmianę reprezentacji danych w późniejszym czasie (temat 12.). W czasie pierwszych pokazów języka Java niektórzy programiści korzystający z języka C uwa ali, e klasy są zbyt obszerne, aby w pewnych sytuacjach zastąpić struktury.
  • 5. 90 Efektywne programowanie w języku Java Nie będziemy się zajmowali tym problemem. Zdegenerowane klasy składające się jedynie z pól danych są pewnym przybli eniem struktur z języka C: 6CMKG FGIGPGTQYCPG MNCU[ PKG RQYKPP[ D[è RWDNKEPG ENCUU 2QKPV ] RWDNKE HNQCV Z RWDNKE HNQCV [ _ Poniewa takie klasy pozwalają na dostęp do swoich pól, nie pozwalają na skorzysta- nie z zalet hermetyzacji. Nie mo na zmienić reprezentacji danych w takiej klasie bez zmiany API, nie mo na wymuszać adnych ograniczeń oraz nie mo na podejmować dodatkowych zadań podczas modyfikacji pola. Ortodoksyjni programiści obiektowi uwa ają, e takie klasy są zakazane i powinny zawsze być zastępowane klasami z polami prywatnymi oraz publicznymi metodami je udostępniającymi: *GTOGV[QYCPC MNCUC Q HWPMELCEJ UVTWMVWT[ ENCUU 2QKPV ] RTKXCVG HNQCV Z RTKXCVG HNQCV [ RWDNKE 2QKPV HNQCV Z HNQCV [ ] VJKUZ Z VJKU[ [ _ RWDNKE HNQCV IGV: ]TGVWTP Z _ RWDNKE HNQCV IGV; ]TGVWTP [ _ RWDNKE HNQCV UGV: ]VJKUZ Z _ RWDNKE HNQCV UGV; ]VJKU[ [ _ _ Oczywiście twierdzenie to jest prawdziwe w odniesieniu do klas publicznych — je eli klasa jest dostępna spoza swojego pakietu, rozwa ny programista powinien zabezpie- czyć sobie mo liwość zmiany wewnętrznej reprezentacji danych. Je eli klasa publiczna udostępnia swoje pola, nie ma mo liwości zmiany reprezentacji danych, poniewa kod klientów, korzystający z klasy publicznej, mo e być ju rozesłany po całym świecie. Je eli jednak klasa jest prywatna w ramach pakietu lub jest to prywatna klasa zagnie - d ona, nie ma nic złego w bezpośrednim udostępnieniu pól danych — zakładając, e naprawdę opisują abstrakcję definiowaną przez klasę. Podejście to generuje mniej kodu ni wykorzystanie metod dostępowych, zarówno w definicji klasy, jak i w kodzie klientów ją wykorzystujących. Poniewa kod klientów jest ściśle związany z wewnętrzną repre- zentacją klasy, jest on ograniczony do pakietu, w którym klasa ta jest zdefiniowana. W przypadku, gdy konieczna jest zmiana reprezentacji danych, mo liwe jest wpro- wadzenie zmian bez konieczności zmiany kodu poza pakietem. W przypadku prywat- nej klasy zagnie d onej zasięg zmian jest ograniczony do klasy nadrzędnej. Kilka klas w bibliotekach języka Java nie dotrzymuje zalecenia, aby klasy publiczne nie udostępniały bezpośrednio swoich pól. Przykładami takich klas są klasy 2QKPV i KOGPUKQP z pakietu LCXCCYV. Przykłady te nie powinny być naśladowane — nale ałoby raczej
  • 6. Rozdział 4. ♦ Odpowiedniki konstrukcji języka C 91 wskazywać je jako przykład negatywny. W temacie 37. opisany został przykład poka- zujący, jak udostępnienie pól w klasie KOGPUKQP spowodowało problemy z wydajno- ścią. Problemy te nie mogą zostać usunięte bez wpływania na kod klientów. Temat 20. Zamiana unii na hierarchię klas Konstrukcja języka C — WPKQP — jest najczęściej wykorzystywana do definiowania struktur, umo liwiających przechowywanie więcej ni jednego typu danych. Struktura taka zwykle posiada co najmniej dwa pola — unię i znacznik. Pole znacznika jest zwykłym polem, wykorzystywanym do wskazywania aktualnego typu danych, prze- chowywanego przez unię. Znacznik jest najczęściej typu wyliczeniowego (GPWO). Struktura zawierająca unię i znacznik jest czasami nazywaną unią z dyskryminatorem. Poni ej przedstawiamy przykład definicji typu UJCRGAV, zapisany w języku C. Jest to unia z dyskryminatorem, reprezentująca prostokąt lub koło. Funkcja CTGC na podstawie wskaźnika do struktury UJCRGAV zwraca pole figury lub , je eli struktura zawiera nieprawidłowe dane.
  • 8. KPENWFG OCVJJ V[RGFGH GPWO ]4'%6#0).' %+4%.'_ UJCRG6[RGAV V[RGFGH UVTWEV ] FQWDNG NGPIVJ FQWDNG YKFVJ _ TGEVCPINGKOGPUKQPUAV V[RGFGH UVTWEV ] FQWDNG TCFKWU _ EKTENGKOGPUKQPUAV V[RGFGH UVTWEV ] UJCRG6[RGAV VCI WPKQP ] TGEVCPINGKOGPUKQPUAV TGEVCPING EKTENGKOGPUKQPUAV EKTENG _ FKOGPUKQPU _ UJCRGAV FQWDNG CTGC UJCRGAV
  • 9. UJCRG ] UYKVEJ UJCRG VCI ] ECUG 4'%6#0).' ] FQWDNG NGPIVJ UJCRG FKOGPUKQPUTGEVCPINGNGPIVJ FQWDNG YKFVJ UJCRG FKOGPUKQPUTGEVCPINGYKFVJ TGVWTP NGPIVJ
  • 10. YKFVJ _ ECUG %+4%.' ] FQWDNG T UJCRG FKOGPUKQPUEKTENGTCFKWU TGVWTP /A2+
  • 11. T
  • 12. T _ FGHCWNV TGVWTP
  • 14. _ _
  • 15. 92 Efektywne programowanie w języku Java Projektanci języka Java postanowili nie wprowadzać konstrukcji WPKQP, poniewa ist- nieje du o lepszy mechanizm definiowania typów umo liwiających reprezentowanie ró nych typów — dziedziczenie. Unie z dyskryminatorem są jedynie mało wydajną imitacją hierarchii klas. Aby zamienić unię z dyskryminatorem na hierarchię klas, nale y zdefiniować klasę abstrakcyjną zawierającą metody abstrakcyjne dla ka dej operacji, której działanie jest zale ne od wartości znacznika. We wcześniejszym przykładzie przedstawiona była tylko jedna taka operacja — CTGC. Ta klasa abstrakcyjna staje się korzeniem hie- rarchii klas. Je eli istnieją inne operacje, niezale ne od wartości znacznika, nale y zdefiniować odpowiednie metody w klasie bazowej. Podobnie, je eli w unii z dyskrymi- natorem istnieją pola danych poza znacznikiem i unią, reprezentujące typy danych wspólne dla wszystkich typów, powinny być one dodane do klasy bazowej. W naszym przykładzie nie było adnych składników niezale nych od typów. Następnie dla ka dego typu reprezentowanego w unii z dyskryminatorem definiujemy klasy, dziedziczące z klasy bazowej. W naszym przykładzie typami tymi są: koło i prosto- kąt. W ka dej z klas podrzędnych nale y umieścić pola danych odpowiednie dla jej typu. W naszym przykładzie dla koła jest to promień, a dla prostokąta długość i szerokość. Na koniec definiujemy odpowiednie implementacje metod abstrakcyjnych z klasy bazowej. Poni ej przedstawiamy hierarchię klas dla naszego przykładu unii z dyskryminatorem: CDUVTCEV ENCUU 5JCRG ] CDUVTCEV FQWDNG CTGC _ ENCUU %KTENG GZVGPFU 5JCRG ] HKPCN FQWDNG TCFKWU %KTENG FQWDNG TCFKWU ] VJKUTCFKWU TCFKWU _ FQWDNG CTGC ] TGVWTP /CVJ2+
  • 17. TCFKWU _ _ ENCUU 4GEVCPING GZVGPFU 5JCRG ] HKPCN FQWDNG NGPIVJ HKPCN FQWDNG YKFVJ 4GEVCPING FQWDNG NGPIVJ FQWDNG YKFVJ ] VJKUNGPIVJ NGPIVJ VJKUYKFVJ YKFVJ _ FQWDNG CTGC ] TGVWTP NGPIVJ
  • 18. YKFVJ _ _ Hierarchia klas posiada wiele zalet w porównaniu z unią z dyskryminatorem. Najwa - niejszą z nich jest ta, e hierarchia klas zapewnia kontrolę typów. W naszym przykładzie ka dy obiekt 5JCRG mo e być jedynie prawidłowym obiektem %KTENG lub 4GEVCPING. Bardzo prosto wygenerować strukturę UJCRGAV, która będzie całkowicie nieprzydatna, poniewa połączenie pomiędzy znacznikiem i unią nie jest wymuszane przez język programowania. Je eli znacznik wskazuje, e UJCRGAV reprezentuje prostokąt, ale unia
  • 19. Rozdział 4. ♦ Odpowiedniki konstrukcji języka C 93 została zainicjowana danymi koła, wszystko mo e się zdarzyć. Nawet, gdy unia z dys- kryminatorem zostanie prawidłowo zainicjowana, mo liwe jest omyłkowe przekazanie jej do funkcji nieodpowiedniej dla danej wartości znacznika. Drugą zaletą hierarchii klas jest łatwość rozszerzania, nawet o wiele niezale nie działa- jących części. Aby rozszerzyć hierarchię klas, wystarczy dodać nową kasę pochodną. Je eli zapomnisz zdefiniować jednej z metod abstrakcyjnych, natychmiast wska e Ci to kompilator. Aby rozbudować unię z dyskryminatorem, nale y mieć dostęp do kodu źródłowego. Musisz dodać nową wartość do typu GPWO oraz nową gałąź do instrukcji UYKVEJ w ka dej funkcji operującej na unii. Na koniec musisz skompilować kod. Je eli w którejś funkcji zapomnisz dodać nowego przypadku, kompilator nie będzie w stanie tego wykryć. Pozostaje umieszczenie w kodzie kontroli niespodziewanych wartości znacznika i generowanie w takich sytuacjach komunikatów błędów. Czwartą zaletą hierarchii klas jest mo liwość odwzorowania naturalnych relacji hierar- chicznych pomiędzy typami, co pozwala na zwiększenie elastyczności i lepszej kontroli typów w czasie kompilacji. Załó my, e do naszego oryginalnego przykładu chcemy dodać obsługę kwadratów. W hierarchii klas mo emy odwzorować fakt, e kwadrat jest specjalnym rodzajem prostokąta (zakładając, e oba są niezmienne): ENCUU 5SWCTG GZVGPFU 4GEVCPING ] 5SWCTG FQWDNG UKFG ] UWRGT UKFG UKFG _ FQWDNG UKFG ] TGVWTP NGPIVJ OQ G D[è TÎYPKG YKFVJ _ _ Przedstawiona hierarchia klas nie jest jedynym rozwiązaniem naszego problemu. Hierar- chia ta powstała po podjęciu kilku decyzji, o których warto wspomnieć. Klasy w hierar- chii, poza 5SWCTG, udostępniają swoje pola, nie oferując metod dostępowych. W przy- padku klas publicznych jest to nie do zaakceptowania, ale nam zale ało na zwięzłości kodu (temat 19.). Klasy te są niezmienne. Czasami nie jest to najlepsze, jednak naj- częściej właśnie takie rozwiązanie jest właściwe (temat 13.). Poniewa język Java nie zawiera konstrukcji WPKQP, mo na uwa ać, e nie ma niebez- pieczeństwa utworzenia unii z dyskryminatorem. Mo liwe jest jednak napisanie kodu, który będzie posiadał te same wady. Je eli kiedykolwiek będziesz chciał napisać klasę z polem znacznikowym, nale y pomyśleć o eliminacji pola znacznikowego przez mo- dyfikację hierarchii klas. Innym zastosowaniem konstrukcji WPKQP w języku C, całkowicie niezwiązanym z uniami z dyskryminatorem, jest mo liwość oglądania wewnętrznej reprezentacji danych poprzez umyślne omijanie systemu typów. Metoda ta demonstrowana jest przez poni szy fragment kodu w języku C, który drukuje wewnętrzną postać liczby HNQCV w postaci szesnastkowej: WPKQP ] HNQCV H KPV DKVU
  • 20. 94 Efektywne programowanie w języku Java _ UNGCG UNGCGH G
  • 21. 7OKGUEGPKG FCP[EJ Y LGFP[O RÎN WPKK
  • 22. RTKPVH ZP UNGCGDKVU
  • 23. K QFE[VCPKG FTWIKGIQ
  • 24. Choć mo e być to u yteczne, szczególnie dla programistów systemowych, takie nieprze- nośne zastosowanie nie ma odpowiednika w języku Java. Działanie takie nie mo e być dopuszczalne w języku, który gwarantuje bezpieczeństwo typów i nieomal izoluje programistów od wewnętrznej reprezentacji danych. Pakiet LCXCNCPI zawiera metody pozwalające przekształcić liczby zmiennoprzecin- kowe na ich bitową reprezentację, ale działanie tych metod jest bardzo dokładnie zde- finiowane w celu zapewnienia ich przenośności. Poni szy fragment kodu jest luźnym odpowiednikiem przedstawionego kodu w języku C, ale gwarantuje uzyskanie iden- tycznych wyników bez względu na platformę, na której jest uruchomiony: 5[UVGOQWVRTKPVNP +PVGIGTVQ*GZ5VTKPI (NQCVHNQCV6Q+PV$KVU GH Temat 21. Zastępowanie konstrukcji enum za pomocą klas Konstrukcja GPWO równie nie została przeniesiona do języka Java. Konstrukcja ta słu y do definiowania typu wyliczeniowego — typu, składającego się ze stałego zbioru wartości. Niestety, konstrukcja ta nie jest zbyt zaawansowana. Definiuje ona tylko zbiór nazwanych stałych typu KPVGIGT, nie zapewniając adnego mechanizmu kontroli typów. W języku C mo na wykonać następujące wyra enia: V[RGFGH GPWO ](7,+ 2+22+0 )4#00;A5/+6*_ CRRNGAV
  • 26. V[RGFGH GPWO ]0#8'. 6'/2.' $.11_ QTCPIGAV
  • 29. /KGUCPKG LCD GM RQOCTC ECOK
  • 30. ale takie jest nieprawidłowe: QTCPIGAV Z (7,+ 2+22+06'/2.' Konstrukcja GPWO nie zawiera przestrzeni nazw dla tworzących ją stałych. Dlatego poni - sza deklaracja, zawierająca u ytą ju nazwę, pozostaje w konflikcie z deklaracją typu QTCPIGAV: V[RGFGH GPWO ]$.11 59'#6 6'#45_ HNWKFAV Typy definiowane za pomocą konstrukcji GPWO są niepewne. Dodanie stałych do takiego typu bez ponownej kompilacji klientów powoduje nieprzewidywalne działanie, nie- zale nie od tego, jak dokładnie są sprawdzane istniejące wartości stałych. Poszcze- gólne zespoły nie mogą niezale nie dodawać stałych do tych typów, poniewa nowe typy wyliczeniowe bardzo często są ze sobą w konflikcie. Konstrukcja GPWO nie zapew- nia adnego mechanizmu, ułatwiającego zamianę stałych wyliczanych na ciągi znaków lub przeglądanie stałych w typie.
  • 31. Rozdział 4. ♦ Odpowiedniki konstrukcji języka C 95 Niestety, najczęściej spotykany sposób emulowania typu wyliczeniowego w języku Java posiada wszystkie wady konstrukcji GPWO z języka C: URQUÎD GOWNCELK GOWP C RQOQEæ KPV RTQDNGOCV[EP[ RWDNKE ENCUU 2NC[KPI%CTF ] RWDNKE UVCVKE HKPCN KPV 57+6A%.7$5 RWDNKE UVCVKE HKPCN KPV 57+6A+#/105 RWDNKE UVCVKE HKPCN KPV 57+6A*'#465 RWDNKE UVCVKE HKPCN KPV 57+6A52#'5 _ Mo esz się równie spotkać z odmianą tego wzorca, wykorzystującą stałe typu 5VTKPI. Wariant taki nigdy nie powinien być u ywany. Choć pozwala na bezpośrednie dru- kowanie nazw stałych, mo e powodować obni enie wydajności, poniewa korzysta z porównywania ciągów. Dodatkowo niedoświadczeni u ytkownicy mogą wbudować stałe w kod zamiast korzystania z odpowiednich nazw pól. Je eli taka stała posiada błąd (literówkę), to błąd ten nie będzie wykryty w czasie kompilacji i będzie powodował powstanie błędów wykonania. Na szczęście język Java pozwala na utworzenie innej metody emulacji typu GPWO, która nie posiada wszystkich wad u ycia poprzedniej metody z wartościami KPV lub 5VTKPI, a ponadto ma kilka dodatkowych zalet. Jest ona nazywana bezpiecznym typem wyli- czeniowym. Typ ten nie jest niestety zbyt dobrze znany. Pomysł jest prosty — nale y zdefiniować klasę, reprezentującą pojedynczy element typu wyliczeniowego, nie defi- niując publicznego konstruktora. Zamiast tego nale y udostępnić publiczne pola sta- tyczne typu HKPCN, po jednym dla ka dej ze stałych typu wyliczeniowego. Wzorzec ten w najprostszej postaci wygląda następująco: DGRKGEP[ V[R Y[NKEGPKQY[ RWDNKE ENCUU 5WKV ] RTKXCVG HKPCN 5VTKPI PCOG RTKXCVG 5WKV 5VTKPI PCOG ] VJKUPCOG PCOG _ RWDNKE 5VTKPI VQ5VTKPI ] TGVWTP PCOG _ RWDNKE UVCVKE HKPCN 5WKV %.7$5 PGY 5WKV ENWDU RWDNKE UVCVKE HKPCN 5WKV +#/105 PGY 5WKV FKCOQPFU RWDNKE UVCVKE HKPCN 5WKV *'#465 PGY 5WKV JGCTVU RWDNKE UVCVKE HKPCN 5WKV 52#'5 PGY 5WKV URCFGU _ Poniewa klienci nie mogą utworzyć obiektów tej klasy ani jej rozszerzać, nie mogą istnieć inne obiekty tego typu poza udostępnianymi przez pola statyczne. Choć klasa nie jest zadeklarowana jako HKPCN, nie mo na po niej dziedziczyć — konstruktor klasy pochodnej musi wywołać konstruktor klasy bazowej, a on jest niedostępny. Jak mo na się domyślić na podstawie nazwy, ten wzorzec pozwala na sprawdzanie typów w czasie kompilacji. Je eli zadeklarujesz metodę z parametrem typu 5WKV, masz pewność, e ka da referencja ró na od PWNN będzie prawidłowym obiektem, repre- zentującym jedną ze stałych. Wszystkie próby przekazania obiektu o niewłaściwym typie zostaną wykryte w czasie kompilacji, podobnie jak próby przypisania wyra enia
  • 32. 96 Efektywne programowanie w języku Java jednego typu wyliczeniowego do zmiennej innego typu. Mo na tworzyć wiele typów wyliczeniowych z identycznie nazywającymi się stałymi, poniewa ka da klasa posiada swoją przestrzeń nazw. Do takiej reprezentacji typu wyliczeniowego mo na dodawać kolejne stałe i nie powo- duje to konieczności rekompilacji klientów, poniewa publiczne statyczne pola, zawiera- jące referencje do stałych, izolują klientów od klasy, realizującej typ wyliczeniowy. Same stałe nie są wkompilowywane w kod klienta, tak jak często zdarza się to w przypadku realizacji konstrukcji GPWO za pomocą rozwiązania, korzystającego z pól KPV lub 5VTKPI. Poniewa przedstawiona realizacja typu wyliczeniowego jest zwykłą klasą, mo e ona przedefiniować metodę VQ5VTKPI, co pozwoli na zmianę wartości zmiennych na postać nadającą się do wydrukowania. Je eli jest to potrzebne, mo na równie zwracać komu- nikaty w odpowiednim języku. Zwróć uwagę, e ciągi znaków są wykorzystywane jedy- nie przez metodę VQ5VTKPI. Nie są u ywane do porównywania obiektów, poniewa odziedziczona po klasie 1DLGEV metoda GSWCNU porównuje referencje do obiektów. Mo na równie dodać do klasy implementującej typ wyliczeniowy dowolne metody, jakie mogą być potrzebne. W naszej klasie 5WKV mo e przydać się metoda zwracająca kolor lub rysunek, skojarzony z odpowiednią stałą. Klasa była początkowo prostą reali- zacją typu wyliczeniowego i z czasem zaczęła się zamieniać w bogatą w funkcję abs- trakcję opisywanego obiektu. Poniewa do klasy implementującej typ wyliczeniowy mo na dodawać dowolne metody, mo e ona implementować interfejsy. Na przykład załó my, e chcemy, aby nasza klasa 5WKV implementowała interfejs %QORCTCDNG, co pozwoli klasom sortować karty według koloru. Przedstawimy teraz modyfikację oryginalnego wzorca, która imple- mentuje ten interfejs. Zmienna statyczna PGZV1TFKPCN u ywana jest do przypisywania numeru kolejnego dla ka dego z tworzonych obiektów. Numery te są u ywane przez metodę EQORCTG6Q do porządkowania obiektów. 6[R Y[NKEGPKQY[ PWOGTQYCP[ RWDNKE ENCUU 5WKV KORNGOGPVU %QORCTCDNG ] RTKXCVG HKPCN 5VTKPI PCOG 0WOGT MQNGLP[ VYQTQPGIQ MQNQTW RTKXCVG UVCVKE KPV PGZV1TFKPCN 2T[RKUCPKG PWOGTW MQNGLPGIQ FQ MQNQTW RTKXCVG HKPCN KPV QTFKPCN PGZV1TFKPCN RTKXCVG 5WKV 5VTKPI PCOG ] VJKUPCOG PCOG _ RWDNKE 5VTKPI VQ5VTKPI ] TGVWTP PCOG _ RWDNKE KPV EQORCTG6Q 1DLGEV Q ] TGVWTP QTFKPCN 5WKVQQTFKPCN _ RWDNKE UVCVKE HKPCN 5WKV %.7$5 PGY 5WKV ENWDU RWDNKE UVCVKE HKPCN 5WKV +#/105 PGY 5WKV FKCOQPFU RWDNKE UVCVKE HKPCN 5WKV *'#465 PGY 5WKV JGCTVU RWDNKE UVCVKE HKPCN 5WKV 52#'5 PGY 5WKV URCFGU _
  • 33. Rozdział 4. ♦ Odpowiedniki konstrukcji języka C 97 Poniewa stałe typu wyliczeniowego są obiektami, mo na umieszczać je w kolekcjach. Załó my na przykład, e chcemy w klasie 5WKV udostępnić niezmienną listę kolorów w standardowym porządku. Wystarczy dodać do klasy deklarację dwóch klas pól. RTKXCVG UVCVKE HKPCN 5WKV=? 24+8#6'A8#.7'5 ] %.7$5 +#/105 *'#465 52#'5 _ RWDNKE UVCVKE HKPCN .KUV 8#.7'5 %QNNGEVKQPUWPOQFKHKCDNG.KUV #TTC[UCU.KUV 24+8#6'A8#.7'5 W przeciwieństwie do najprostszej postaci typu wyliczeniowego klasy w wersji korzy- stającej z numerów kolejnych mogą być serializowane (rozdział 9.) z zachowaniem szczególnej ostro ności. Nie wystarczy dodać do deklaracji klasy klauzuli KORNGOGPVU 5GTKCNKCDNG. Wymagane jest równie utworzenie metody TGCF4GUQNXG (temat 57.). RTKXCVG 1DLGEV TGCF4GUQNXG VJTQYU 1DLGEV5VTGCO'ZEGRVKQP ] TGVWTP 24+8#6'A8#.7'5=QTFKPCN? OKCPC PC RQUVCè MCPQPKEPæ _ Metoda ta, wywołana automatycznie przez system serializacji, zabezpiecza przed powie- laniem istniejących stałych, powstałych w procesie deserializacji. Zapewnia ona, e będzie istniał tylko jeden obiekt dla ka dej stałej typu wyliczeniowego, co pozwala uniknąć konieczności przedefiniowywania metody 1DLGEVGSWCNU. Bez tej gwarancji metoda 1DLGEVGSWCNU będzie zwracała nieprawidłowe wyniki, je eli będzie porównywała dwie równe stałe, ale o ró nych kolejnych numerach. Zwróć uwagę, e metoda TGCF4G UQNXG korzysta z tablicy 24+8#6'A8#.7'5, więc musisz zadeklarować tę tablicę, nawet je eli nie chcesz udostępniać kolekcji 8#.7'5. Nale y równie zwrócić uwagę, e pole PCOG nie jest wykorzystywane przez metodę TGCF4GUQNXG, więc jest ono nietrwałe i takie powinno pozostać. Wynikowa klasa jest jednak krucha — konstruktor dla dowolnej nowej wartości musi występować po wszystkich istniejących wartościach, dzięki czemu zapewniamy, e wszystkie serializowane wcześniej obiekty nie zmienią swoich wartości w trakcie dese- rializacji. Dzieje się tak, poniewa postać serializowana stałych (temat 55.) opiera się jedynie na ich kolejnych numerach. Je eli stała, będąca składnikiem typu wyliczenio- wego, zmieni swój numer kolejny, stała o tym numerze poddana serializacji zmieni swoją wartość podczas procesu deserializacji. Mo e istnieć jedna lub więcej operacji skojarzonych z ka dą ze stałych, które są wyko- rzystywane jedynie wewnątrz pakietu, zawierającego klasę realizującą typ wyliczeniowy. Operacje takie najlepiej implementować jako metody prywatne w ramach pakietu. Ka da stała typu wyliczeniowego zawiera ukrytą kolekcję operacji, pozwalających reagować odpowiednio dla odpowiednich stałych. Je eli klasa implementująca typ wyliczeniowy posiada metody, których działanie znacznie się ró ni w zale ności od wartości stałej, powinieneś skorzystać z osobnych klas pry- watnych lub anonimowych klas, zagnie d onych dla ka dej ze stałych. Pozwala to ka dej ze stałych posiadać własną implementację danej metody i automatycznie wywoływać odpowiednią implementację. Alternatywą jest tworzenie wieloście kowych rozgałęzień, które wybierają odpowiednią metodę w zale ności od stałej, na rzecz której wywołu- jemy tę metodę. Jest to rozwiązanie niechlujne, podatne na błędy i często wydajność tego rozwiązania jest ni sza od rozwiązania, korzystającego z automatycznego wybie- rania metod przez maszynę wirtualną.
  • 34. 98 Efektywne programowanie w języku Java Obie techniki opisane w poprzednim akapicie są zilustrowane jeszcze jedną klasą, reali- zującą typ wyliczeniowy. Klasa ta, 1RGTCVKQP, reprezentuje działania wykonywane przez prosty kalkulator czterodziałaniowy. Poza pakietem, w którym zdefiniowana jest ta klasa, mo na skorzystać ze stałych klasy 1RGTCVKQP do wywołania metod klasy 1DLGEV (VQ5VTKPI, JCUJ%QFG, GSWCNU itd.). Wewnątrz pakietu mo na dodatkowo wykonywać operacje matematyczne związane ze stałymi. Przypuszczalnie pakiet mo e eksportować obiekt kalkulatora udostępniający jedną lub więcej metod, które jako parametrów ocze- kują stałych klasy 1RGTCVKQP. Zwróć uwagę, e sama klasa 1RGTCVKQP jest klasą abstrak- cyjną, zawierającą jedną prywatną w ramach pakietu metodę abstrakcyjną — GXCN, która wykonuje odpowiednią operację matematyczną. Dla ka dej stałej zdefiniowana jest wewnętrzna klasa anonimowa, więc ka da stała mo e zdefiniować własną wersję metody GXCN. 6[R Y[NKEGPKQY[ QRGTCELCOK UMQLCTQP[OK G UVC [OK RWDNKE CDUVTCEV ENCUU 1RGTCVKQP ] RTKXCVG HKPCN 5VTKPI PCOG 1RGTCVKQP 5VTKPI PCOG ] VJKUPCOG PCOG _ RWDNKE 5VTKPI VQ5VTKPI ] TGVWTP VJKUPCOG _ 9[MQPCL QRGTCELú OCVGOCV[EPæ FNC DKG æEGIQ MQPVGMUVW CDUVTCEV FQWDNG GXCN FQWDNG Z FQWDNG [ RWDNKE UVCVKE HKPCN 1RGTCVKQP 2.75 PGY 1RGTCVKQP ] FQWDNG GXCN FQWDNG Z FQWDNG [ ] TGVWTP Z [ _ _ RWDNKE UVCVKE HKPCN 1RGTCVKQP /+075 PGY 1RGTCVKQP ] FQWDNG GXCN FQWDNG Z FQWDNG [ ] TGVWTP Z [ _ _ RWDNKE UVCVKE HKPCN 1RGTCVKQP 6+/'5 PGY 1RGTCVKQP
  • 35. ] FQWDNG GXCN FQWDNG Z FQWDNG [ ] TGVWTP Z
  • 36. [ _ _ RWDNKE UVCVKE HKPCN 1RGTCVKQP +8+'A$; PGY 1RGTCVKQP ] FQWDNG GXCN FQWDNG Z FQWDNG [ ] TGVWTP Z [ _ _ _ Przedstawiony typ wyliczeniowy ma wydajność porównywalną do wydajności klasy korzystającej ze stałych wyliczeniowych typu KPV. Dwa ró ne obiekty klasy repre- zentującej typ wyliczeniowy nigdy nie reprezentują tej samej wartości, więc porówna- nie referencji, które jest bardzo szybkie, wystarczy do sprawdzenia równości logicznej. Klienci klasy mogą nawet u yć operatora zamiast metody GSWCNU — wynik będzie identyczny, a operator mo e nawet działać szybciej. Je eli klasa typu wyliczeniowego jest przydatna, mo e być klasą najwy szego poziomu — je eli jest związana z inną klasą najwy szego poziomu, powinna być statyczną klasą zagnie d oną tej klasy (temat 18.). Na przykład klasa LCXCOCVJ$KIGEKOCN zawiera zbiór stałych wyliczeniowych typu KPV, określających tryby zaokrąglania
  • 37. Rozdział 4. ♦ Odpowiedniki konstrukcji języka C 99 części dziesiętnych. Te tryby zaokrąglania stanowią u yteczny model abstrakcji, który nie jest zasadniczo przywiązany do klasy $KIGEKOCN — byłoby lepiej utworzyć osobną klasę LCXCOCVJ4QWPFKPI/QFGU. Udostępnienie takiej klasy wszystkim programistom korzystającym z trybów zaokrągleń pozwoliłoby na zwiększenie spójności między ró nymi API. Podstawowa implementacja wzorca bezpiecznego typu wyliczeniowego, zilustrowana za pomocą dwóch implementacji klasy 5WKV, jest zamknięta. U ytkownicy nie mogą dodawać nowych elementów typu wyliczeniowego, poniewa klasa nie udostępnia im konstruktora. Powoduje to, e klasa zachowuje się tak, jakby została zdefiniowana jako HKPCN. Najczęściej jest to najlepsze rozwiązanie, ale istnieją przypadki, w których chcemy utworzyć rozszerzalną klasę typu wyliczeniowego. Mo e być to potrzebne na przykład do reprezentowania formatów kodowania rysunków, gdy chcesz, aby inni pro- gramiści mogli umo liwiać obsługę nowych formatów. Aby umo liwić rozszerzanie typu wyliczeniowego, wystarczy udostępnić zabezpie- czony konstruktor. U ytkownicy będą mogli dzięki temu dziedziczyć po istniejącej klasie, dodając w podklasach własne stałe. Nie musisz się obawiać, e stałe typu wyli- czeniowego spowodują konflikt, tak jak było to w przypadku typu wyliczeniowego, korzystającego ze stałych KPV. Rozszerzalny wariant wzorca bezpiecznego typu wyli- czeniowego korzysta z przestrzeni nazw pakietu do tworzenia „magicznie admini- strowanych” przestrzeni nazw dla rozszerzalnych wyliczeń. Ró ne zespoły mogą nie- zale nie rozszerzać wyliczenia i nie pozostaną one nigdy w konflikcie. Dodanie elementu do rozszerzalnego typu wyliczeniowego nie gwarantuje jeszcze, e nowe elementy będą w pełni obsługiwane. Metody operujące na elementach typu wyli- czeniowego muszą przewidywać ewentualność przekazania elementu nieznanego pro- gramiście. Wielokrotne rozgałęzienia są dyskusyjne w przypadku zamkniętego typu wyliczeniowego, a w przypadku typu rozszerzalnego są nie do przyjęcia, poniewa nie mogą samoczynnie dodawać nowej gałęzi dla typu, dodanego przez programistę rozszerzającego klasę. Jedynym sposobem radzenia sobie z tym problemem jest wyposa enie klasy bezpiecz- nego typu wyliczeniowego we wszystkie metody niezbędne do opisania zachowania się stałych tej klasy. Metody niezbyt u yteczne dla klientów powinny być zadeklaro- wane jako RTQVGEVGF w celu ich ukrycia, natomiast klasy pochodne mogą je przedefi- niować. Je eli metoda taka nie ma rozsądnego działania domyślnego, oprócz RTQVGEVGF powinna być równie zadeklarowana jako CDUVTCEV. Dla rozszerzalnych klas bezpiecznego typu wyliczeniowego dobrze jest przedefinio- wać metody GSWCNU i JCUJ%QFG jako metody finalne, wywołujące odpowiednie metody z klasy 1DLGEV. Zapewni to, e adna podklasa przypadkowo nie przedefiniuje tych metod, co zagwarantuje, e wszystkie równe obiekty są równie identyczne (CGSWCNU D tylko wtedy, gdy CD): /GVQF[ CDGRKGECLæEG RTGF RTGU CPKCPKGO RWDNKE HKPCN DQQNGCP GSWCNU 1DLGEV VJCV ] TGVWTP UWRGTGSWCNU VJCV _
  • 38. 100 Efektywne programowanie w języku Java RWDNKE HKPCN KPV JCUJ%QFG ] TGVWTP UWRGTJCUJ%QFG _ Trzeba pamiętać, e wariant rozszerzalny nie jest zgodny z wariantem implementują- cym interfejs %QORCTCDNG — je eli będziesz próbował je ze sobą połączyć, porządko- wanie elementów w podklasach będzie działało w porządku inicjalizacji podklas, co mo e się zmieniać w ró nych programach i w ró nych wywołaniach. Rozszerzalny wariant wzorca bezpiecznego typu wyliczeniowego jest zgodny z warian- tem implementującym interfejs 5GTKCNKCDNG, ale łączenie tych wariantów wymaga nieco uwagi. Ka da podklasa musi przypisywać własne numery kolejne i napisać wła- sną metodę TGCF4GUQNXG. Zasadniczo ka da klasa jest odpowiedzialna za serializację i deserializację swoich obiektów. Przedstawiamy teraz kolejną wersję klasy 1RGTCVKQP, która jest rozszerzalna i mo e być serializowana. 5GTKCNKQYCNP[ TQUGTCNP[ DGRKGEP[ V[R Y[NKEGPKQY[ RWDNKE CDUVTCEV ENCUU 1RGTCVKQP KORNGOGPVU 5GTKCNKCDNG ] RTKXCVG HKPCN VTCPUKGPV 5VTKPI PCOG RTQVGEVGF 1RGTCVKQP 5VTKPI PCOG ] VJKUPCOG PCOG _ RWDNKE UVCVKE 1RGTCVKQP 2.75 PGY 1RGTCVKQP ] RTQVGEVGF FQWDNG GXCN FQWDNG Z FQWDNG [ ] TGVWTP Z [ _ _ RWDNKE UVCVKE 1RGTCVKQP /+075 PGY 1RGTCVKQP ] RTQVGEVGF FQWDNG GXCN FQWDNG Z FQWDNG [ ] TGVWTP Z[ _ _ RWDNKE UVCVKE 1RGTCVKQP 6+/'5 PGY 1RGTCVKQP
  • 39. ] RTQVGEVGF FQWDNG GXCN FQWDNG Z FQWDNG [ ] TGVWTP Z
  • 40. [ _ _ RWDNKE UVCVKE 1RGTCVKQP +8+' PGY 1RGTCVKQP ] RTQVGEVGF FQWDNG GXCN FQWDNG Z FQWDNG [ ] TGVWTP Z[ _ _ 9[MQPCL QRGTCELú OCVGOCV[EPæ FNC DKG æEGIQ MQPVGMUVW RTQVGEVGF CDUVTCEV FQWDNG GXCN FQWDNG Z FQWDNG [ RWDNKE 5VTKPI VQ5VTKPI ] TGVWTP VJKUPCOG _ CDNQMQYCPKG OQ NKYQ EK RTGFGHKPKQY[YCPKC 1DLGEVGSWCNU RTG MNCU[ RQEJQFPG RWDNKE HKPCN DQQNGCP GSWCNU 1DLGEV VJCV ] TGVWTP UWRGTGSWCNU VJCV _ RWDNKE HKPCN KPV JCUJ%QFG ] TGVWTP UWRGTJCUJ%QFG _ RQPK UG FGMNCTCELG Uæ PKGDúFPG FNC UGTKCNKCELK RTKXCVG UVCVKE KPV PGZV1TFKPCN RTKXCVG HKPCN KPV QTFKPCN PGZV1TFKPCN RTKXCVG UVCVKE HKPCN 1RGTCVKQP=? 8#.7'5 ] 2.75 /+075 6+/'5 +8+' _ 1DLGEV TGCF4GUQNXG VJTQYU 1DLGEV5VTGCO'ZEGRVKQP ] TGVWTP 8#.7'5=QTFKPCN? OKCPC PC RQUVCè MCPQPKEPæ _ _
  • 41. Rozdział 4. ♦ Odpowiedniki konstrukcji języka C 101 Przedstawimy równie podklasę klasy 1RGTCVKQP, która dodaje operacje logarytmowa- nia i podnoszenia do potęgi. Ta klasa pochodna mo e być zdefiniowana poza pakietem zawierającym klasę bazową. Powinna być ona publiczna i umo liwiać dziedziczenie. Mo liwe jest utworzenie wielu niezale nych podklas, współistniejących bez adnych konfliktów. 2QFMNCUC UGTKCNKQYCNPGIQ TQUGTCNPGIQ DGRKGEPGIQ V[RW Y[NKEGPKQYGIQ CDUVTCEV ENCUU 'ZVGPFGF1RGTCVKQP GZVGPFU 1RGTCVKQP ] 'ZVGPFGF1RGTCVKQP 5VTKPI PCOG ] UWRGT PCOG _ RWDNKE UVCVKE 1RGTCVKQP .1) PGY 'ZVGPFGF1RGTCVKQP NQI ] RTQVGEVGF FQWDNG GXCN FQWDNG Z FQWDNG [ ] TGVWTP /CVJNQI [ /CVJNQI Z _ _ RWDNKE UVCVKE 1RGTCVKQP ':2 PGY 'ZVGPFGF1RGTCVKQP GZR ] RTQVGEVGF FQWDNG GXCN FQWDNG Z FQWDNG [ ] TGVWTP /CVJRQY Z [ _ _ RQPK UG FGMNCTCELG Uæ PKGDúFPG FNC UGTKCNKCELK RTKXCVG UVCVKE KPV PGZV1TFKPCN RTKXCVG HKPCN KPV QTFKPCN PGZV1TFKPCN RTKXCVG UVCVKE HKPCN 1RGTCVKQP=? 8#.7'5 ] .1) ':2 _ 1DLGEV TGCF4GUQNXG VJTQYU 1DLGEV5VTGCO'ZEGRVKQP ] TGVWTP 8#.7'5=QTFKPCN? OKCPC PC RQUVCè MCPQPKEPæ _ _ Zwróć uwagę, e metoda TGCF4GUQNXG w przedstawionej klasie nie jest prywatna, a tylko prywatna w ramach pakietu. Jest to niezbędne, poniewa obiekty 1RGTCVKQP i 'ZVGP FGF1RGTCVKQP są właściwie obiektami podklas anonimowych, więc prywatna metoda TGCF4GUQNXG nie mo e zostać zastosowana (temat 57.). Wzorzec bezpiecznego typu wyliczeniowego posiada jednak nieco więcej wad w porów- naniu do typu wyliczeniowego, korzystającego z wartości KPV. Prawdopodobnie jedyną powa ną niedogodnością jest niewygodne łączenie bezpiecznych stałych wyliczeniowych w zbiory. W przypadku typu wyliczeniowego, korzystającego z wartości KPV, jest to zwykle realizowane przez nadanie stałym wyliczeniowym wartości będących potęgami dwójki i reprezentowanie zbioru jako bitowej sumy logicznej odpowiednich stałych: 1FOKCPC V[RW Y[NKEGPKQYGIQ MQT[UVCLæEGIQ DKVQY[EJ YCTVQ EK NKED KPV RWDNKE UVCVKE HKPCN KPV 57+6A%.7$5 RWDNKE UVCVKE HKPCN KPV 57+6A+#/105 RWDNKE UVCVKE HKPCN KPV 57+6A*'#465 RWDNKE UVCVKE HKPCN KPV 57+6A52#'5 RWDNKE UVCVKE HKPCN KPV 57+6A$.#%- 57+6A%.7$5 ^ 57+6A52#'5 Reprezentowanie w ten sposób zbiorów stałych typu wyliczeniowego jest zwięzłe i nie- zmiernie szybkie. W przypadku zbiorów stałych bezpiecznego typu wyliczeniowego mo esz skorzystać z implementacji zbioru z biblioteki %QNNGEVKQPU, ale nie jest to tak zwięzłe i szybkie.
  • 42. 102 Efektywne programowanie w języku Java 5GV DNCEM5WKVU PGY *CUJ5GV DNCEM5WKVUCFF 5WKV%.7$5 DNCEM57+65CFF 57+652#'5 Choć zbiory stałych prawdopodobnie nie mogą być zrealizowane ani tak zwięźle, ani tak szybko, jak zbiory stałych wyliczeniowych typu KPV, mo liwe jest zmniejszenie tej ró nicy przez utworzenie specjalnej implementacji klasy 5GV, która akceptuje jedynie elementy jednego typu i wewnętrznie reprezentuje zbiór jako wektor bitów. Taki zbiór najlepiej zdefiniować w tym samym pakiecie, co klasa reprezentująca przechowywane elementy, co umo liwia dostęp do pól lub metod prywatnych w ramach pakietu. Roz- sądne jest utworzenie publicznych konstruktorów, które jako parametry akceptują krótkie sekwencje elementów, dzięki czemu mo liwe jest tworzenie następujących wyra eń: JCPFKUECTF PGY 5WKV5GV 5WKV%.7$5 5WKV52#'5 Mniejszą niedogodnością bezpiecznego typu wyliczeniowego, w porównaniu do typu korzystającego z typu KPV, jest to, e bezpieczny typ wyliczeniowy nie mo e być wyko- rzystany w instrukcji UYKVEJ, poniewa nie są to wartości całkowite. Zamiast tego nale y skorzystać z instrukcji KH: KH UWKV 5WKV%.7$5 ] _ GNUG KH UWKV 5WKV+#/105 ] _ GNUG KH UWKV 5WKV*'#465 ] _ GNUG KH UWKV 5WKV52#'5 ] _ GNUG ] VJTQY PGY 0WNN2QKPVGT'ZEGRVKQP 2WUV[ MQNQT UWKV PWNN _ Instrukcja KH mo e nie wykonywać się tak szybko jako UYKVEJ, ale ró nica nie powinna być zauwa alna. Tworzenie wielokrotnych rozgałęzień w przypadku bezpiecznego typu wyliczeniowego powinno być rzadkie, poniewa rozgałęzianie kodu nale y zastę- pować automatycznym wyborem metod przez maszynę wirtualną, tak jak w przyto- czonej klasie 1RGTCVKQP. Kolejny niewielki problem wią e się ze spadkiem wydajności, poniewa potrzeba czasu i miejsca w pamięci na załadowanie klasy typu wyliczeniowego i utworzenie obiek- tów stałych. Problem ten nie powinien być zauwa alny w praktyce, poza niektórymi urządzeniami o ograniczonych zasobach, jak na przykład telefony komórkowe czy tostery. Podsumujmy. Przewagi bezpiecznego typu wyliczeniowego nad typem korzystającym z wartości KPV są bezapelacyjne i adna z wad nie mo e być przyczyną zaprzestania korzystania z niego, chyba e jest on głównie u ywany jako element zbioru lub w środo- wisku o ograniczonych zasobach. Dlatego bezpieczny typ wyliczeniowy powinien być jako pierwszy brany pod uwagę, jeśli konieczne jest zastosowania typu wylicze- niowego. API korzystające z bezpiecznego typu wyliczeniowego jest du o łatwiejsze w u yciu dla programistów ni to, które korzysta z typu KPV. Jedynym powodem, dla którego bezpieczny typ wyliczeniowy nie jest intensywniej wykorzystywany w bibliote- kach platformy Java, jest fakt, e wzorzec ten nie był jeszcze znany w czasie tworzenia
  • 43. Rozdział 4. ♦ Odpowiedniki konstrukcji języka C 103 większości klas tego API. Na koniec nale y przypomnieć, e stosowanie typu wyli- czeniowego powinna być dosyć rzadkie, poniewa w większości zastosowań tego typu z powodzeniem mo na skorzystać z dziedziczenia (temat 20.). Temat 22. Zastępowanie wskaźników do funkcji za pomocą klas i interfejsów Język C pozwala na stosowanie wskaźników do funkcji, które umo liwiają zapamięty- wanie i przesyłanie odwołań do określonych funkcji. Wskaźniki do funkcji są najczę- ściej wykorzystywane w celu umo liwienia funkcji wywołującej modyfikacji swojego działania poprzez przekazanie wskaźnika do drugiej funkcji, czasami nazywanej funkcją wywołania zwrotnego. Na przykład, funkcja SUQTV ze standardowej biblioteki języka C wymaga jako parametru wskaźnika do funkcji, której zadaniem jest porównywanie ele- mentów. Funkcja porównująca wymaga podania dwóch parametrów — wskaźników do elementów. Zwraca ona ujemną liczbę całkowitą, je eli element wskazywany przez pierwszy element jest mniejszy od drugiego, zero, gdy elementy są równe i dodatnią liczbę całkowitą, je eli pierwszy element jest większy od drugiego. Mo na uzyskać ró ny porządek sortowania, przekazując inną funkcję porównującą. Jest to przykład wzorca Strategy (strategia) [Gamma95, str. 315] — funkcja porównująca określa strategię sortowania elementów. Wskaźniki do funkcji nie znalazły się w języku Java, poniewa korzystając z referencji do obiektów, mo na uzyskać takie samo działanie. Wywołując metodę obiektu, zwykle wykonuje się operacje na tym obiekcie. Mo na równie zdefiniować obiekt, którego metody wykonują operacje na innym obiekcie, przekazanym jawnie do metody. Obiekt klasy udostępniającej tylko jedną taką metodę jest, efektywnie, wskaźnikiem do tej metody. Obiekty takie są zwane obiektami funkcjonalnymi. Przyjrzyjmy się takiej właśnie klasie: ENCUU 5VTKPI.GPIVJ%QORCTCVQT ] RWDNKE KPV EQORCTG 5VTKPI U 5VTKPI U ] TGVWTP UNGPIVJ UNGPIVJ _ _ Klasa ta udostępnia jedną metodę, która oczekuje dwóch ciągów znaków jako parame- trów. Zwraca ona liczbę ujemną w przypadku, gdy pierwszy ciąg jest krótszy od dru- giego, zero, gdy ciągi są równe i liczbę dodatnią, gdy pierwszy ciąg jest dłu szy od drugiego. Metoda ta jest komparatorem, porównującym długości ciągów. Referencja do obiektu 5VTKPI.GPIVJ%QORCTCVQT słu y jako „wskaźnik do funkcji”, umo liwiając wywołanie metody dla dwóch podanych ciągów. Bezstanowość klasy 5VTKPI.GPIVJ%QORCTCVQT jest typowa dla klas strategii — klasa ta nie posiada pól, przez co wszystkie jej obiekty są funkcjonalnie identyczne. Aby uniknąć tworzenia niepotrzebnych obiektów, mo emy utworzyć tę klasę jako klasę typu singleton (temat 4., temat 2.).
  • 44. 104 Efektywne programowanie w języku Java ENCUU 5VTKPI.GPIVJ%QORCTCVQT ] RTKXCVG 5VTKPI.GPIVJ%QORCTCVQT ]_ RWDNKE UVCVKE HKPCN 5VTKPI.GPIVJ%QORCTCVQT +056#0%' PGY 5VTKPI.GPIVJ%QORCTCVQT RWDNKE KPV EQORCTG 5VTKPI U 5VTKPI U ] TGVWTP UNGPIVJ UNGPIVJ _ _ Aby przekazać obiekt 5VTKPI.GPIVJ%QORCTCVQT do metody, potrzebujemy odpowied- niego typu dla parametrów. Skorzystanie z typu 5VTKPI.GPIVJ%QORCTCVQT nie będzie odpowiednie, poniewa klienci nie będą mogli przekazywać innych strategii porów- nywania. Mo na natomiast zdefiniować interfejs %QORCTCVQT i zmienić klasę 5VTKPI .GPIVJ%QORCTCVQT, aby implementowała ten interfejs. Inaczej mówiąc, definiujemy interfejs strategii, implementowany przez konkretne klasy strategii: +PVGTHGLU UVTCVGIKK RWDNKE KPVGTHGCEG %QORCTCVQT ] RWDNKE KPV EQORCTG 1DLGEV Q 1DLGEV Q _ Ta definicja interfejsu %QORCTCVQT znajduje się w pakiecie LCXCWVKN, ale równie dobrze mo esz ją utworzyć samemu. W przypadku obiektów innych ni ciągi mo liwe jest, e ich metody EQORCTG będą oczekiwały parametrów typu 1DLGEV, a nie 5VTKPI. Dlatego w celu prawidłowej implementacji interfejsu %QORCTCVQT przytoczona wcześniej klasa 5VTKPI.GPIVJ%QORCTCVQT musi być nieco zmodyfikowana. W celu wywołania metody NGPIVJ parametry typu 1DLGEV muszą być rzutowane na 5VTKPI. Klasy strategii są często definiowane jako klasy anonimowe (temat 18.). Poni sze wyra- enie powoduje posortowanie tablicy ciągów według ich długości. #TTC[UUQTV UVTKPI#TTC[ PGY %QORCTCVQT ] RWDNKE KPV EQORCTG 1DLGEV Q 1DLGEV Q ] 5VTKPI U 5VTKPIQ 5VTKPI U 5VTKPIQ TGVWTP UNGPIVJ UNGPIVJ _ _ Poniewa interfejsy strategii słu ą jako typy dla wszystkich obiektów strategii, w celu udostępnienia strategii jej klasa nie musi być publiczna. Zamiast tego „klasa główna” mo e udostępniać publiczne statyczne pole (lub statyczną metodę factory) typu określa- nego przez interfejs strategii, a klasa strategii mo e być prywatną klasą składową klasy głównej. W poni szym przykładzie pokazujemy zastosowanie statycznej klasy zagnie - d onej, tworzącej klasę strategii do implementacji drugiego interfejsu, 5GTKCNKCDNG. 7FQUVúRPKCPKG UVTCVGIKK ENCUU *QUV ] YKúMUQ è MNCU[ RQOKPKúVC RTKXCVG UVCVKE ENCUU 5VT.GP%OR KORNGOGPVU %QORCTCVQT 5GTKCNKCDNG ]
  • 45. Rozdział 4. ♦ Odpowiedniki konstrukcji języka C 105 RWDNKE KPV EQORCTG 1DLGEV Q 1DLGEV Q ] 5VTKPI U 5VTKPIQ 5VTKPI U 5VTKPIQ TGVWTP UNGPIVJ UNGPIVJ _ _ YTCECP[ MQORCTCVQT OQ PC UGTKCNKQYCè RWDNKE UVCVKE HKPCN %QORCTCVQT 564+0)A.'0)6*A%1/2#4#614 PGY 5VT.GP%OR _ Klasa *QUV korzysta z tego wzorca do udostępnienia za pomocą pola 564+0)A.'0)6*A %1/2#4#614 komparatora porównującego długości ciągów. Podsumujmy. Podstawowym zastosowaniem wskaźników do funkcji jest utworzenie wzorca 5VTCVGIKC. W języku Java wzorzec ten mo na utworzyć, deklarując interfejs reprezentujący strategię i klasę implementującą interfejs dla konkretnej strategii. Gdy strategia jest zastosowana tylko raz, jej klasa deklarowana jest najczęściej jako klasa anonimowa. Gdy strategia jest udostępniana, jej klasa jest zwykle prywatną statyczną klasą zagnie d oną i jest udostępniana poprzez publiczne statyczne pole HKPCN, którego typ jest zgodny z interfejsem strategii.