JAVA exPress > Archive > Issue 1 (2008-08-18) > Kubek Kawy - czyli alternatywny kurs Javy, cz. I

Kubek Kawy - czyli alternatywny kurs Javy, cz. I

Java - rodzaj kawy produkowany na wyspie Jawa. Słowo to jest też slangowym określeniem kawy w Stanach Zjednoczonych. W Indonezji zwrot Kopi Java nie oznacza kawy jako takiej, a rodzaj mocnej, czarnej i bardzo słodkiej kawy podawanej z mielonymi ziarnami.

Kawa została sprowadzona na Jawę przez Duńczyków w XVIIw. Pierwotnie była to kawa gatunku Arabica, ale po pladze w 1880 roku została zastąpiona najpierw odmianą Liberica, a potem Robusta. Obecnie określenia Java używa się tylko w stosunku do niektórych odmian produkowanych na wyspie.

Wstęp

Cześć właśnie dorwałeś się do alternatywnego kursu języka Java. Ja nazywam się... nie inaczej. W internecie spotkasz mnie pod xwką Koziołek. Osobiście możesz mnie spotkać na imprezach organizowanych przez warszawski JUG

Poniższy kurs jest wynikiem długiej praktyki z językiem Java i różnymi materiałami edukacyjnymi dotyczącymi tegoż języka. Przez ten czas zebrało mi się wiele pomysłów oraz myślałem czego brakuje mi w tradycyjnych kursach. Na ich podstawie powstał ten oto kurs. Żeby ułatwić nam pracę na początek omówię jak organizujemy pracę.

Wychodzę z założenia, że nigdy nie programowałeś lub bardzo mało programowałeś. Jeżeli jesteś bardziej doświadczonym programistą lub znasz już jakiś język programowania w stopniu eksperckim to z góry przepraszam za uproszczenia. W pierwszej części kursu przybliżę Ci czym jest Java, jakie są podstawowe koncepcje i pojęcia z nią związane. Opowiem o maszynie wirtualnej i przybliżę pojęcia takie jak klasa, obiekt, interfejs. Zaprezentuję też narzędzia pozwalające na łatwą i przyjemną pracę i naukę. W drugiej części poznamy podstawowe elementy składni języka. Będzie to najnudniejsza i najbardziej najbardziej sztampowa część kursu. Niestety nie da się tego pominąć. W kolejnych częściach zajmiemy się już poważnymi sprawami. Poznasz zasady przekazywania i wysyłania danych w programach, sposób zarządzania interfejsem użytkownika czy też zasady zdroworozsądkowego programowania.

Od początku będę też odsyłał Cię do innych źródeł. Ma to na celu wyrobienie w Tobie umiejętności poszukiwania wiedzy. Jeżeli chcesz złączyć swoją przyszłość z programowaniem to bardzo ważne jest abyś potrafił szybko i sprawnie wyszukiwać rozwiązania problemów. Nie oszukujmy się większość z nich już dawno rozwiązano, a czas poświęcony na znalezienie tego rozwiązania jest zazwyczaj krótszy niż wymyślanie koła od nowa. Tu muszę podkreślić, że samo wymyślanie koła od nowa nie zawsze jest złe, w końcu nasze koło może być bardziej okrągłe.

Czego nie znajdziesz w tym kursie. Nie będę odwoływał się do innych języków programowania. Nie będę męczył cię przydługimi listingami kodu. Nie będę używał techniczno komputerowego bełkotu w ilościach większych niż jest to potrzebne.

Skoro już ustaliliśmy co i jak czas wziąć się do pracy.

Część 1: Kubek Javy. Otwieramy puszkę z kawą.

Tak jak kawa (zazwyczaj w wersji żużel – kawa pół na pół z wodą) jest paliwem programistów tak język java stał się jednym z najważniejszych składników współczesnego świata komputerów. Czym jest java? Jest to zorientowany obiektowo, kompilowany i uruchamiany na maszynie wirtualnej javy (JVM) język programowania. Trochę skomplikowane? Rozpracujmy tą definicję krok po kroku.

Java jest zorientowana obiektowo. Oznacza to, że w języku tym posługujemy się pojęciami takimi jak obiekt, klasa, interfejs. Java nie jest językiem wpełni obiektowym ponieważ istnieje w niej grupa typów prostych (pierwotnych), które nie są obiektami. Zaraz opowiem co to są obiekty.

Java jest kompilowana to znaczy, że zanim uruchomimy nasz program jego kod jest poddawany specjalnemu procesowi, który tłumaczy nasze wypociny na coś zrozumiałego dla komputera. Szczegółów co to jest kompilator poszukaj sobie w Googlu.

Java uruchamiana jest na Maszynie Virtualnnej Javy (JVM od ang. Java Virtual Machine). Jest to najważniejsza i najbardziej rozpoznawalna cecha javy. Maszyna wirtualna to specjalny program, który znajduje się pomiędzy naszym kodem, a systemem operacyjnym. Jej zadaniem jest ujednolicenie interfejsu tak aby nasz kod mógł zostać napisany raz i uruchamiany na każdym komputerze niezależnie od jego architektury. Jest to bardzo skomplikowane pojęcie, ale spróbuję je uprościć w następujący sposób.

Zapewne spotkałeś się z uniwersalnymi czytnikami kart pamięci na USB. Te małe urządzenia pozwalają na przeglądanie zawartości karty nie zależnie jakiego jest typu. Złączka karty jest „magicznie” zamieniana na zwykłe USB. Jeżeli teraz nasz kod jest tym portem USB, a systemy operacyjne są reprezentowane przez różne typy kart to JVM jest naszym czytnikiem, który pozwala nam na stworzenie kodu raz i nie martwienie się jakiego typu jest karta, którą chcemy przeczytać. Mam nadzieję, że łapiesz o co chodzi.

Obiecałem napisać coś o obiektach no to do dzieła.

Esencja aromatu

No właśnie czas przyswoić sobie trzy podstawowe pojęcia związane z językiem java. Są to Klasa, Obiekt i Interfejs. Nie będę bawił się w rozwlekłe opisywanie co i jak. Czas skorzystać ze źródeł. W swoim czasie popełniłem „klasyczny” kurs javy na 4programmers.net ( http://4programmers.net/Java/Podstawy_javy)

Klasa

Abstrakcyjny byt określający zbiór Obiektów o takich samych właściwościach.

Klasa definiuje zestaw Metod i Pól dla swoich Obiektów. Przykładem klasy może być samochód. Może on podejmować różne działania np. jechać i ma pewne właściwości np. kolor. Jest jednak abstrakcyjny, mówiąc inaczej "nienamacalny". Jeżeli mówimy o klasie Samochód to oznacza, że mówimy o jakimś samochodzie.

Ogólny wzór definicji klasy w Javie wygląda w następujący sposób:

          [modyfikator dostępu] [abstract] class NazwaKlasy{
            // definicja pól i metod
          }
        

Nasz wzorcowy samochód:

          public class Samochod{
            public Color kolor = new Color(255,255,255);
            // pole kolor określa kolor samochodu

            public void jedzie(){
              //kod odpowiedzialny za jazdę samochodu
            }
          }
        

Klasa może implementować Interfejs. Oznacza to, że klasa ma wszystkie metody, zachowania, definiowane przez interfejs. Klasa musi implementować wszystkie metody interfejsu. Tu jednak rodzi się pytanie co zrobić, jeżeli nie chcemy implementować wszystkich metod? Można oczywiście zaimplementować je w taki sposób by zwracały wartości null. Jednak nie jest to dobre rozwiązanie. Można powiedzieć nawet więcej, jest to najgorsze z możliwych rozwiązań, ponieważ ukrywa fakt braku implementacji metod. Znacznie lepszym rozwiązaniem jest uczynienie danej klasy abstrakcyjną.

Klasa abstrakcyjna zawiera w sobie zwykłe metody, czyli takie które mają jawną implementację, oraz metody abstrakcyjne. Metoda abstrakcyjna nie ma implementacji. Poniżej przykład klasy abstrakcyjnej:

          public abstract class KlasaAbstrakcyjna {
            public int pole;
            public abstract void metodaAbstrakcyjna();
            public void metodaZwykła(){
              //Kod metody
            }
          }
        

Po co to wszystko? Dochodzimy do bardzo ważnego elementu programowania obiektowego jakim jest dziedziczenie. Załóżmy, że chcemy stworzyć klika klas odpowiadających różnym markom i typom samochodów. Interesuje nas to że samochody jeżdżą i mogą mieć doczepioną naczepę. Najbardziej prawidłowe podejście powinno wyglądać w następujący sposób:

- Definiujemy interfejs Samochód. Posiada on metody które odpowiadają działaniom wszystkich samochodów np.

- jedź

- załóż naczepę

- Tworzymy klasę abstrakcyjną, która implementuje interfejs Samochód w taki sposób, że metoda jedź jest wspólna dla wszystkich samochodów, a metoda załóż naczepę abstrakcyjna.

- Tworzymy poszczególne klasy samochodów. Dziedziczą, rozszerzają, one klasę AbstrakcyjnySamochód i implementują zakładanie naczepy w zależności od potrzeb.

Nasze samochody to:

- Ferrari

- Star

Kod takiego programu powinien wyglądać mniej więcej w taki sposób:

          // plik Samochód
          public interface Samochód {
            public void jedź();
            public void załóżNaczepę();
          }

          //plik AbstrakcyjnySamochód
          public abstract class AbstrakcyjnySamochód implements Samochód {
            public void jedź() {
              //kod odpowiedzialny za poruszanie się samochodu
            }
            public abstract void załóżNaczepę();
          }

          //plik Ferrari
          public class Ferrari extends AbstrakcyjnySamochód {
            public void załóżNaczepę() {
              //nic nie robimy. Ferrari nie może mieć naczepy
            }
          }

          //plik Star
          public class Star extends AbstrakcyjnySamochód {
            public void załóżNaczepę() {
              //Czynności związane z zakładaniem naczepy
            }
          }
        

Kilka uwag o dziedziczeniu i interfejsach w javie:
- Można dziedziczyć tylko po jednej klasie
- Klasa może implementować kilka interfejsów, ale trzeba uważać na konflikty nazw
- Interfejs może dziedziczyć po innym interfejsie
- Wszystkie obiekty dziedziczą po klasie Object

Obiekt

Byt fizyczny stanowiący instancję klasy.

Obiekt jest fizyczną "manifestacją" Klasy. Oznacza to, że ma własne miejsce w pamięci komputera i możemy nim manipulować. Jeżeli mówimy o obiekcie samochód będącym instancją Klasy Samochód to oznacza, że mówimy o konkretnym samochodzie.

Obiekt definiujemy jako Zmienną.

Zmienna

Byt fizyczny o którym mówimy że ma wartość

Przez pojęcie zmiennej w Javie rozumiemy referencję, wskazanie, do określonego miejsca w pamięci komputera. Zmienne reprezentują dane i pozwalają za swoim pośrednictwem nimi manipulować.

Stała

Rodzaj zmiennej, której wartość nie podlega modyfikacji

Stała to zmienna, która po nadaniu jej wartości nie może być już zmieniona. Zazwyczaj tej konstrukcji używa się do definiowania np. ustawień. Chcąc uzyskać taki efekt należy użyć słowa kluczowego final.

Metoda

Działanie, które mogą podjąć Obiekty danej Klasy

Metoda określa Działanie. Dlatego najczęściej stosuje się do jej nazwania czasowniki. samochód.jedzie() - jedzie() to metoda, działanie. Metody wywołujemy za pomocą znaku . po nazwie zmiennej.

Pole

Właściwość Obiektu danej Klasy

Samochód może mieć kolor. Pole Klasy rozumiemy właściwość lub relację MA. Pole jest zmienną która należy do klasy.

Interfejs

Dobrze zdefiniowany zestaw czynności - metod, które może wykonać obiekt danej klasy.

Interfejs jest jednym z najtrudniejszych do zrozumienia pojęć OOP. Jednocześnie jest stosunkowo prostym pojęciem, jeżeli posłużymy się przykładem. Załóżmy że Samochód Jest Interfejsem. Oznacza to że możemy korzystać z jego Metod i Stałych. Jednocześnie możemy zdefiniować kilka różnych klas implementujących interfejs Samochód. Wszystkie one będą miały dobrze zdefiniowane metody interfejsu. Oznacza to, że jeżeli wiemy, że dany obiekt implementuje interfejs samochód to możemy "w ciemno" używać metod tego interfejsu. Nie interesuje nas jak one działają, a jedynie ich parametry wywołania i to co otrzymamy w wyniku ich działania.

W życiu codziennym spotykamy się z interfejsami, które zapewniają funkcjonalności, a jednocześnie nie musimy znać zasad ich działania. Przykład to pilot od telewizora. Jest interfejsem pozwalającym na włączania, zmianę kanałów i wyłączanie urządzenia.

W języku Java definicja jest następująca:

          [modyfikator dostępu] interface NazwaInterfejsu{
            // definicja stałych i metod
          }
        

W naszym przykładzie z samochodem:

          public interface Samochod{
            public final Color kolor = new Color(0,0,0);
            // pole będące stałą. Produkujemy Fordy T ;)

            public void jedzie();
          }
        

Modyfikatory dostępu

Od początku zarówno w definicji klasy jak i interfejsu, metody i pola znajduje się tajemniczy zapis [modyfikator dostępu].

Modyfikator dostępu określa w jaki sposób inne obiekty mogą otrzymać dostęp do danego pola, metody, definicji klasy czy interfejsu. W języku Java wyróżniamy cztery modyfikatory dostępu: publiczny, prywatny, chroniony i domyślny.

Modyfikator publiczny

Określany jest słowem kluczowym public. Oznacza iż do danej metody, pola, definicji klasy i interfejsu ma dostęp każdy obiekt w uniwersum javy (JU). Dostęp ten nie jest uzależniony o tego w jakim pakiecie znajduje się udostępniana własność i czy to jest ten sam pakiet co pakiet obiektu z którego pochodzi żądanie.

Modyfikator prywatny

Jest przeciwieństwem modyfikatora publicznego. Pola, metody, klasy i interfejsy oznaczone słowem private są całkowicie niewidoczne poza definicją swojego właściciela. Przykładowa klasa zawierająca zarówno pola, metody, klasy i interfejsy prywatne:

          class PrywatnaKlasa {
            private int polePrywatne;

            private void metodaPrywatna(){}
            private interface prywatnyInterfejs{}
            private class prywatnaKlasa implements prywatnyInterfejs{}
          }
        

Żaden obiekt w JU nie będzie wstanie odwołać się do zawartości PrywatnaKlasa. Bardzo istotnym faktem jest to, że klasa znajdująca się na najwyższym poziomie, czyli PrywatnaKlasa nie może być prywatna.

Modyfikator chroniony

Modyfikator chroniony oznaczamy słowem kluczowym protected. Elementy oznaczone w ten sposób są widoczne tylko dla innych obiektów znajdujących się poniżej w tej samej hierarchii klas. Innymi słowy dziedziczące po klasie zawierającej elementy chronione. Oczywiście są też widoczne dla innych elementów znajdujących się w tym samym pakiecie i pod pakietach.

Modyfikator domyślny

Nie jest oznaczony żadnym słowem kluczowym. Nie zrozumienie jak działa modyfikator domyślny jest źródłem popularnych błędów związanych z próbą wykorzystania oznaczonych w ten sposób pól i metod. Modyfikator domyślny można zdefiniować w następujący sposób, jeżeli dostęp do pola, metody, klasy lub interfejsu jest oznaczony jako domyślny to mogą go otrzymać tylko te obiekty, które znajdują się w tym samym pakiecie. Oznacza to, że klasy dziedziczące po klasie zawierającej elementy z dostępem domyślnym nie będą mogły użyć tego elementu chyba, że znajdują się w tym samym pakiecie. Ten sam pakiet oznacza literalnie ten sam katalog w strukturze pakietów. Nie może to być np. podkatalog o innej strukturze pakietów nie wspominając.

Inne modyfikatory

Poza modyfikatorami dostępu funkcje i pola obiektów mogą być opisane za pomocą innych modyfikatorów.

Modyfikator final

Pole obiektu oznaczone jako final po inicjacji nie może być modyfikowane. Oznacza to, że inicjacji pola można dokonać tylko na dwa sposoby. Poprzez jawne inicjowanie w definicji klasy:

          class Klasa{
            final Object pole = new Object();
          }
        

lub w konstruktorze:

          class Klasa{
            final Object pole;

            public Klasa(){
              pole = new Object();
            }

            public Klasa(Object obj){
              pole = obj;
            }
          }
        

Wartość pola po zainicjowaniu nie może być już zmieniana. Jeżeli pole wskazuje na jakiś obiekt, to dalej można używać metod ustawiających tego obiektu i bezpośrednich odwołań do pól do ustawiania wartości pól tego obiektu.

W przypadku metody oznaczenie jej jako final powoduje, że klasy dziedziczące po klasie nie mogą przesłonić metody:

          public class KlasaA {
            final void metoda(){}
          }

          class KlasaB extends KlasaA{
            // Niedozwolone! Nie można przesłonić
            // metody final
            // void metoda(){}
          }
        

Jeżeli klasa jest oznaczona jako final to nie można rozszerzyć tej klasy:

          public final class KlasaA {
          }
          // nie można rozszerzyć klasy oznaczonej jako final
          // class KlasaB extends KlasaA{}
        

Modyfikator static

Modyfikator static oznacza, iż pole obiektu ma taką samą wartość dla wszystkich obiektów danej klasy. Formalnie oznacza to, iż wszystkie obiekty danej klasy odwołują się do tego samego miejsca w pamięci.

Jeżeli metoda jest oznaczona jako statyczna, to może być wywołana bez potrzeby tworzenia obiektu klasy definiującej tą metodę. W tym miejscu należy wspomnieć, iż do zarówno metod, jak i pól oznaczonych jako static dobieramy się w inny sposób, iż do normalnych metod i pól. Chcąc odwołać się do statycznego elementu należy użyć wzorca:

          nazwa_klasy.nazwa_metody/nazwa_pola         

Jeżeli chcemy użyć tradycyjnego odwołania:
- obiekt.metoda();
- obiekt.pole;
to kompilator zwróci ostrzeżenie The static field/method obiekt.pole/obiekt.metoda() should be accessed in a static way.

Program powinien kompilować się bez błędów i ostrzeżeń.

Modyfikator strictfp

Metoda lub klasa oznaczona w ten sposób będzie wykonywana tak, by wszystkie obliczenia były zgodne ze standardem IEEE-754.

Modyfikator native

Zaawansowany modyfikator, którym oznaczane są metody wykonywane przez JNI (Java Native Interface). W praktyce oznacza to, że metody te są implementowane w języku innym niż Java, a JVM wywołując je odwołuje się do mechanizmów pozwalających na komunikację z np C++.

Modyfikator transient

Zaawansowany modyfikator związany z JPA (Java Persistence Api). Pola oznaczone w ten sposób nie są utrwalane.

Modyfikator volatile

Obok modyfikatora transient, jeden z rzadziej wykorzystywanych modyfikatorów. Oznacza, że pole oznaczone w ten sposób może być modyfikowane przez zewnętrzny proces lub inny wątek.
 

Na razie wystarczy tej wiedzy. W kolejnym odcinku omówię składnię i polecenia języka. Kofeina w żyłach się już wypaliła więc miłej nocy.

Nobody has commented it yet.

Only logged in users can write comments

Developers World