Składnia
Klasa, obiekt, składowe, konstruktory, metody klasy
Zaczniemy od przykładu, w którym zostannie zaprezentowanych kilka podstawowych elementów języka.
W Javie przyjęto konwencje nazewnicze. Stosowanie tych konwencji ułatwia czytanie programów. Przyjmowanie nazw odzierciedlających merytoryczne znaczenie zmiennych, metod, klas jest dobrze widzianą praktyką.
Nazwy zmiennych, nazwy funkcji zaczynają się od małej litery. Jeżeli nazwa składa się z kilku słów, wtedy drugie i następne słowa pisane są z dużej litery. (bokTrojkata, policzDelte(), dopuszcza się używanie polskich znaków w nazwach, czyli poprawne jest bokTrójkata, policzDeltę())
Nazwy klas zaczynają się z dużej litery, jeśli nazwa klasy składa się z kilku słów, wtedy każde słowo pisane jest z dużej litery (ToJestWaznaKlasa).
Nazwy stałych są pisane dużymi literami, jeśli nazwa stałej składa się z kilku słów, wtedy słowa oddzielane są znakami podkreślenia (STALA_MATEMATYCZNA).
P06Proste.java
Warto zwrócić uwagę na:
słowo kluczowe static oraz wartość zmiennej y na wydruku
słowa kluczowe private, protected, public oraz funkcję getZ().
dwa konstruktory
operator + łączący teksty oraz w sposób niewidoczny wykonaną metodę toString()
Zwracanie referencji
słowo kluczowe this
Zmienne - typy podstawowe
Nazwa typu | Rozmiar | Typ Obiektowy |
---|---|---|
boolean | Boolean | |
char | 16 bitów | Character |
byte | 8 bitów | Byte |
short | 16 bitów | Short |
int | 32 bity | Integer |
long | 64 bity | Long |
float | 32 bity | Float |
double | 64 bity | Double |
void | Void |
Zmienną typu podstawowego definiujemy i inicjujemy:
int y;
char x = 's';
float z = 1.5f;
Dla klas opakowujących
Integer y = new Integer(5);
Character x = new Character('s');
Float z = new Float(1.5f)
W wersji 5 Javy wprowadzono automatyczne otaczanie, ten temat będzie omówiony w następnych wykładach.
Klasa i modyfikatory dostępu do klasy
class NazwaKlasy { ciało klasy } dostępna tylko w klasach tego
samego pakietu
public class NazwaKlasy{ciało klasy } dostępna dla klas z innych
pakietów
może być jedna w pliku
Obiekt klasy NazwaKlasy tworzymy
NazwaKlasy a = new NazwaKlasy();
lub
NazwaKlasy a; utworzenie pustej referencji
a = new NazwaKlasy();
Kilka własności
Tylko identyfikatory zmiennych typów podstawowych reprezentują wartości.
Pozostałe identyfikatory są obiektami, applet i aplikacja także.
Identyfikator obiektu jest referencją.
Ciało klasy to
składowe - zmienne podstawowe i obiekty
konstruktory - funkcje o nazwach takich jak klasa, służą do tworzenia obiektów, nie zwracacją wartości
metody - funkcje dowolne
Obszar działania zmiennych wyznaczają nawiasy łańcuchowe.
Kontrola dostępu do składowych klasy i przydział pamięci
Dostęp do składowych klasy i przydział pamięci wyznaczają słowa kluczowe:
private - oznacza, że składowa jest dostępna jedynie dla funkcji z danej klasy,
protected - udostępnia pole wszystkim klasom z tego samego pakietu i klasom dziedziczącym,
public - zezwala na dostęp do pola dla każdej funkcji z dowolnej klasy,
static -jeśli będzie budowanych wiele instancji tej samej klasy, to pola statyczne wszystkich tych obiektów zajmą to samo miejsce w pamięci, nie ma wpływu na dostępność tego pola.
Konstruktory
Konstruktory mają następującą strukturę
NazwaKlasy(argumenty){
ciało konstruktora
}
i mogą być poprzedzone modyfikatorem dostępu, najczęściej konstruktory wykorzystuje się następująco:
NazwaKlasy nazwa_obiektu = new NazwaKlasy(argumenty)
Konstruktor służy do budowania obiektów. Zwykle jest wykorzystywany do nadawania wartości początkowych składowym (polom, zmiennym) klasy. Jeśli nie utworzymy żadnego konstruktora, to zostanie utworzony konstruktor domyślny - bezargumentowy. Utworzenie jakiegokolwiek konstrukora z argumentami uniemożliwia użycie konstruktora domyślnego. Należy, o ile jest to konieczne zdefiniować konstruktor bezargumentowy. Za pomocą operatora new otrzymujemy referencję do utworzonego obiektu z nadanymi wartościami zgodnie z użytym konstruktorem. Wszystkie konstruktory z danej klasy mają taką samą nazwę. Różnią się listą argumentów.
Funkcje - metody
Definicje metody zapisujemy następująco:
[static] [modyfikator_dostępu] TypKlasa nazwaMetody(argumenty){
ciało metody
}
gdzie modyfikator_dostępu to jedno ze słów kluczowych public, protected, private. Znaczenie tych słów oraz słowa kluczowego static w zastosowaniu do funkcji jest następujące:
static - dla funkcji oznacza, że metoda ma być dostępna, nawet jeśli żaden obiekt klasy, w której ta metoda się znajduje nie został utworzony, składowe statyczne mają przydzielone to samo miejsce w pamięci dla wszystkich obiektów klasy, w której zostały zdefuiniowane.
public, protected, private - pozwalają na udostępnianie wszystkim, udostępnianie dla pakietu i klas wywiedzionych, ukrywanie części metod i pól (składowych). Z pól można korzystać jedynie poprzez metody.
Wykonanie metod
Każde odwołanie do metody może być wykonane na rzecz obiektu z klasy z której pochodzi ta metoda. Należy więc utworzyć obiekt, i niech to będzie obiekt klasy TrzyLiczby, czyli
TrzyLiczby a = new TrzyLiczby();
po utworzeniu tego obiektu i na jego rzecz można wykonać metody dodaj() i pomnoz(), sumaXZ()
a.dodaj()
a.pomnoz(5)
a.sumaXZ(b)
Metody statyczne mogą być wykorzystywane, nawet wtedy, gdy nie istnieje obiekt danej klasy. Do tego zagadnienia wrócimy wkrótce.
Metody statyczne, argumenty funkcji, referencje
Prześledźmy poniższy program
P07Proste.java
Funkcje statyczne
Funkcje statyczne mogą być wywołane nawet wtedy, gdy żaden obiekt klasy, w której jest ona zapisana nie został utworzony. Takie metody można wywoływać na rzecz klasy. Wywołanie metody na rzecz klasy ma poniższą postać:
NazwaKlasy.nazwaFunkcji(argumenty)
W przykładzie powyższym klasa ZmienPodstawowa zawiera jedną metodę i jest to metoda statyczna. Obiekt klasy ZmienPodstawowa nie jest tworzony. Można wykonać metodę ZmienPodstawowa na rzecz klasy.
Argumenty funkcji - zmienne podstawowe jako argumenty funkcji
Zmienne podstawowe są przekazywane przez wartość. Obiekty są przekazywane przez referencję. Metoda ZmienPodstawowa zmienia wartość zmiennej r, po wyjściu z metody wartość argumentu aktualnego pozostaje niezmieniona. Powołanie do życia obiektu ZmienPodstawowa nie zmienia sposobu działania. Klasy, które zawierają tylko metody statyczne można traktować jak zestaw podręcznych narzędzi. Jeśli umieścimy w takiej klasie funkcje statyczne, to będzie się można do nich odwoływać bez tworzenia obiektu.
Składowe klasy
Składowe klasy, które nie są poprzedzone modyfikatorem dostępu mają modyfikator domyślny protected. Są dostępne dla metod z tego pliku, w którym są zdefiniowane. Można nadać wartość składowej x z klasy Raz, czyli b.x = 5; jest poprawną instrukcją, chociaż niezbyt elegancką. Zmiany składowych w obiekcie powinny być dokonywane przez metody z klasy tego obiektu.
Argumenty funkcji - obiekty
Metoda zmienO() z klasy ZmienObiekt zmienia składową obiektu klasy Raz, ale może zmienić tylko składową, która nie jest poprzedzona modyfikatorem dostępu private. Prywatne składowe mogą być zmieniane tylko przez metody z klasy, do której przynależą. Metoda setY() może zmienić prywatną składową klasy Raz.
Operatory porównwania
Ten przykład pozwala na prześledzenie korzystania z dokumentacji. Zawarte są w nim przykłady zastosowania kilku metod z klasy Integer.
P08Proste.java
Najważniejsze elementy programu
Metody klasy Integer
Działanie operatorów = == != zastosowanych do obiektów. Większość operatorów w Javie może być stosowana jedynie dla zmiennych typów podstawowych. Wyjątki od tej reguły będą przedstawione w następnych wykładach.
W wersji 5 Javy wprowadzono automatyczne otaczanie zmiennych prostych. Ta zmiana wymaga również komentarza dotyczącego operatorów.
Operatory (poprawnie zastosowane), podobnie jak funkcje zwracają wartości. Pobierają jeden lub więcej argumentów i zwracają wartość.
Prawie wszystko co wiadomo o operatorach z C można przenieść do Javy.
Należy zapamiętać, że jeżeli operatory mogą działać na obiektach, to działają zwykle na referencjach.
Przyjrzyjmy się budowie klasy Integer
Pola statyczne klasy Integer
MAX_VALUE | typ int, maksymalna wartość typu całkowitego |
---|---|
MIN_VALUE | typ int, minimalna wartość typu całkowitego |
typ Class | reprezentuje typ podstawowy |
Zwyczajowo, w nazwach stałych, przyjmuje się duże litery i jako rozdzielenie elementów w tych nazwach stosuje się podkreślenia
Konstruktory klasy Integer
Integer(int value) | tworzy obiekt, nadaje wartość value |
---|---|
Integer(String s) | tworzy obiekt, nadaje wartość otrzymaną przez zamianę tekstu na wartość całkowitą |
Wybrane metody
int | parseInt(String s, int radix) | s potraktowane jak liczba układu radix zamieniona typ int |
---|---|---|
static int | parseInt(String s) | s potraktowane jak liczba układu dziesiętnego zamienione na int |
static Integer | valueOf(String s) | tworzy nowy obiekt klasy Integer, inicjuje go zamieniając s potraktowane jak liczba dziesiętna na typ int |
int | intValue() | zwraca wartość typu int z klasy, na rzecz której została wywołana |
boolean | equals(Object obj) | porównuje obiekt obj z obiektem, na rzecz którego została wywołana |
String | toString() | zwraca łańcuch reprezentujący klasę, na rzecz której została wywołana |
Korzystanie z dokumentacji, dokumentacja pakietu java.lang
Dokumentacja pakietu ma poniższą postać.
Operatory, literały, instrukcje sterujące, pętle, skoki, przełączniki
Operatory
Przykład poniższy ilustruje działanie operatorów przypisania i porównywania zastosowanego do referencji oraz wybrane własności automatycznego otaczania.
P09Proste.java
Operatory działają na typach podstawowych. Operatory, o ile mogą być zastosowane do obiektów oznaczają działania na referencjach. Do operatorów mogących działać na obiektach należą
= == != | przypisanie, czy równe?, czy różne |
---|
Operator przypisania zastosowany do obiektów powoduje przypisanie referencji, nie jest to klonowanie.
Porównanie obiektów typów własnych i otaczających dla zmiennych prostych za pomocą operatora == != porównuje referencje. Chcąc porównać wartości składowej należy nadpisać metodę equals() z klasy Object.
Dla obiektów klas otaczających zbudowanych z wykorzystaniem automatycznego otaczania można wykorzystać operatory == != tak jak dla zmiennych prostych. Jeśli jeden z porównywanych obiektów jest zbudowany tradycyjnie (za pomocą operatora new), to będą porównywane referencje.
Tylko poniższe operatory działają na obiektach. Operatory te mogą być zastosowane do łańcuchów tekstowych. Pozwalają na łączenie tekstów. Jest to jedynyny operator przeciążony dostępny w Javie. Java nie zawiera żadnych mechanizmów pozwalających na przeciążanie operatorów.
+ += | dadaj, powiększ o |
---|
Zbierzemy wszystkie dostępne operatory.
Operatory arytmetyczne
- + | zmiana znaku |
---|---|
* / %/ | mnożenie, dzielenie, reszta z dzielenia |
- + | dodawanie, odejmowanie |
Operatory zwiększania i zmniejszania
++ -- | zwiększanie, zmniejszanie o jeden |
---|
Operatory te dają efekty uboczne w postaci zmiany operandów, mogą wystąpić podobnie jak w C w wersji przedrostkowej oraz w wersji przyroskowej.
Operatory relacji
< <= >= > | mniejsze, mniejsze lub równe, większe lub równe ,większe |
---|---|
== != | równe , różne |
Wyrażenia relacyjne przyjmują wartości : false true
Operatory logiczne, mogą działać jedynie na zmiennych logicznych ( w przeciwieństwie do C i C++)
! | zaprzeczenie |
---|---|
|| | alternatywa |
&& | koniunkcja |
Wyrażenia logiczne mogą nie być liczone do końca - jeśli wynik obliczeń jest znany po policzeniu części wyrażenia, dalsze obliczenia nie są kontynuowane.
Operatory bitowe - pozwalają manipulować bitami argumentów całkowitych i mogą być używane wyłącznie z podstawowym typem całkowitym. Jest to zastosowanie algebry logicznej na parach odpowiadających sobie bitów w przypadku operatorów dwuargumentowych. Działają na pojedynczych bitach w przypadku operatorów jednoargumentowych.
& | koniunkcja bitowa |
---|---|
| | alternatywa bitowa |
~ | zaprzeczenie bitowe - operator uzupełnienia |
<< | przesunięcie bitowe w lewo - zera na najmłodszych bitach |
>> | przesunięcie bitowe w prawo - zera (+) lub jedynki (-) na najstarszych bitach |
>>> | przesunięcie bitowe w prawo - zera na najstarszych bitach |
^ | alternatywa wykluczająca |
Pozostałe operatory
wyrażenie_logiczne ? wyrażenie_1 : wyrażenia | trójargumentowy operator if-else |
---|---|
, | operator przecinkowy - może wystąpić tylko w pętli for |
(typ) | operator rzutowania |
Priorytety
Mnemonik | Typ operatora | Operatory |
---|---|---|
Jadą | Jednoargumentowe | + - ++ -- |
Andrzej i Paweł | Arytmetyczne i przesunięcia | * / % + - << >> |
rowerem | Relacyjne | > < >= <= == != |
ledwie biedni | Logiczne i bitowe | && || & | ^ |
wlokąc | Warunkowy | ?: |
pedałami | Przypisania | = += *= .... |
Stałe - literały
Całkowity int 12 +13 -35 0x7f 0X7f 0177
Całkowity long 12L 123l
Rzeczywisty float 13.3f 1e-5f
Rzeczywisty double 34.2d
Rzutowanie w Javie jest bezpieczne (dla typów podstawowych) z wyjątkiem rzutowania zawężającego, które może się łączyć z utratą dokładności. Przy rzutowaniu zawężającym kompilator wymusza jawne stosowanie operatora rzutowania. Rzutowanie rozszerzające jest dokonywane automatycznie. Typ logiczny nie podlega rzutowaniu. Rzutowanie obiektów będzie omówione później.
Instrukcja warunkowa
Instrukcja warunkowa ma postać:
if ( wyrażenie_logiczne ) instrukcja_a
lub
if ( wyrażenie_logiczne ) instrukcja_a else instrukcja_p
warto zwrócić uwagę, żę w nawiasach może wystąpić wyłącznie wyrażenie logiczne.
Pętla for
for(inicjalizacja ; wyrażenie_logiczne ; krok )instrukcja_p
Pętla for-each
W wersji 5 Javy została wprowadzona pętla typu for-each pozwalająca na przeglądanie kolekcji i tablic.
for(typ zmienna: kolekcja)instrukcja_p
Pętla do...while
do instrukcja_p while(wyrażenie_logiczne)
Pętla while
while(wyrażenie_logiczne) instrukcja_p
Instrukcja skoku
W Javie nie ma instrukcji skoku. Są za to instrukcje break i continue połączone z etykietą; dają one takie możliwości przerwania iteracji, jak ciesząca się złą sławą instrukcja goto - jest to słowo kluczowe Javy ale nieużywane. Etykieta ma postać
moja_etykieta:
i może być stosowana wyłącznie, bezpośrednio przed jedną z instrukcji pętli. Instrukcja break ma jedną z dwóch postaci break; i przerywa najciaśniej obejmującą ją instrukcję pętli, lub break moja_etykieta przerywa pętlę oznaczoną moja_etykietą, może to spowodować przerwanie wielu zagnieżdżonych pętli
Instrukcja continue ma jedną z dwóch postaci continue; zaprzestaje wykonywania bieżącego obrotu pętli i przechodzi do wykonania następnego kroku najciaśniej obejmującej ją pętli, lub continue moja_etykieta; przerywa wykonywanie bieżącego obrotu pętli i przechodzi do następnego obrotu pętli oznaczonej moja_etykietą.
Wyliczenia
W wersji 5 Javy wprowadzono, znane z innych języków, wyliczenia. Szczegółowe informacje o wyliczeniach będą przedstawione w późniejszych wykładach. Teraz przyjrzyjmy się jej podstawowej postaci.
enum KlasaWyliczenia {stała_1, stała_2, ... , stała_n}
Można zdefiniować zmienną wyliczenia i nadać jej wartość (wyłącznie wymienioną w liście stałych klasy wyliczenia).
KlasaWyliczenia zmiennaWyliczenia;
zmiennaWyliczenia = KlasaWyliczenia.stała_1;
Podstawowe wykorzystanie zmiennych wyliczeniowych będzie pokazane w najbliższym przykładzie,
Instrukcja switch
switch(wyrażenie_całkowite){
case wartość_całkowita_1 : ciąg_instrukcji_1
case wartość_całkowita_2 : ciąg_instrukcji_2
default : ciąg_instrukcji_default
case wartość_całkowita_3 : ciąg_instrukcji_3
case wartość_całkowita_4 : ciąg_instrukcji_4
}
Instrukcja switch działa dokładnie tak, jak w języku C. Jeśli ma być wykonany tylko jeden ciąg instrukcji, to konieczne jest użycie instrukcji break.
Podstawowe wykorzystanie instrukcji switch będzie przedstawione w najbliższym przykładzie.
Ograniczenie instrukcji switch do przełączników w postaci wyrażeń całkowitych obowiązywało do wersji poniżej 6 Javy. W wersji 7 wprowadzono przełączniki postaci obiektów klasy String
Wykorzystanie instrukcji switch jest przedstawione w poniższym przykładzie. Przedstawia on działanie instrukcji switch w kolejnych wersjach Javy (do 5, do 7, od 7)
P091Proste.java
Warto zwrócić uwagę na możliwość używania polskich liter w zazwach zmiennych i nazwach stałych.
Pierwsza instrukcja switch jest znana od pierwszych wersji Javy. Instrukcja switch wymagała przełącznika całkowitego, dokładniej, takiego który mógł być bezpośrednio rzutowany na typ całkowity.
W drugiej instrukcji switch jest zastosowana klasa enum. Pojawiła się ona w wersji 5 Javy. W etykietach case występują stałe zapisane w enum. Nie są to obiekty klasy String. Stałe z enum są wyprowdzane za pomocą metody toString() z klasy Enum, po której dziedziczy klasa enum.
W ostatniej, trzeciej instrukcji switch jako przełącznikiem jest obiekt klasy String. Porównanie tekstów pobranych z obiektu klasy String (nie referencji) jest podstawą wyboru.