11 marca 2008

SCJP - Deklaracje metod

Deklaracje metod, czyli streszczenie sekcji "Nonaccess Member Modifiers" – kontynuacja działań zapowiedzianych w artykule "Przygotowania do SCJP czas zacząć".

Modyfikatory widoczności w kontekście metod opisałem w artykule "SCJP - Modyfikatory widoczności w deklaracji metod i zmiennych", zatem znaczenie słów kluczowych private, public i protected w tym kontekście mamy już wyjaśnione. Pozostało jeszcze jednak kilka modyfikatorów których możemy użyć w deklaracji metod, są to: final, abstract, synchronized, native, strictfp oraz static.

Metoda abstrakcyjna, tj. zadeklarowana jako abstract to metoda nie posiadająca implementacji. Jeśli klasa zawiera choć jedną metodę abstrakcyjną to sama także musi być zadeklarowana jako abstract – więcej na ten temat w artykule "SCJP - Modyfikatory dla deklaracji klas". Jeśli metoda jest zadeklarowana jako abstract to jednocześnie może być zadeklarowana tylko jako public lub protected, modyfikator abstract nie może być użyty w parze z żadnym innym modyfikatorem. Przy okazji uświadommy sobie jak to jest z metodami i klasami abstrakcyjnymi w świetle dziedziczenia. Załóżmy, że klasa A jest klasą abstrakcyjną i zawiera abstrakcyjne metody a() i b(). Jeśli klasa B dziedziczy z klasy A, to są dwie możliwości: albo klasa B również jest abstrakcyjna i wtedy może implementować dowolną, obie albo żadną z metod a() i b(), albo klasa B nie jest abstrakcyjna i wtedy musi implementować zarówno a() i b(). Ogólna zasada jest taka, że jeśli klasa nie abstrakcyjna dziedziczy z klasy abstrakcyjnej to musi implementować wszystkie abstrakcyjne metody odziedziczone z tej nadklasy.

Modyfikator final oznacza, że metoda nie będzie mogła być przedefiniowana w podklasie. Generalnie, modyfikator final jest po to właśnie, aby zagwarantować sobie, że cokolwiek zostało raz zdefiniowane i oznaczone jako final nigdy nie będzie się mogło zmienić. Zmiana w kontekście metody oznacza właśnie przedefiniowanie w podklasie. Ale w kontekście deklaracji metod modyfikator final pojawia się raz jeszcze. Otóż modyfikatorem tym możemy także oznaczyć parametr formalny metody i ma to ten skutek, że do zmiennej lokalnej określonej tym parametrem nie będzie można przypisać żadnej wartości. Nawiasem mówiąc, final jest jedynym modyfikatorem, jakim można oznaczyć zmienne lokalne, a więc i parametry metod. I jeszcze przypomnienie - tak jak już napisałem powyżej, modyfikator final nie może wystąpić razem z modyfikatorem abstract.

Metodę statyczną, nazywaną także metodą klasową, deklarujemy używając słówka kluczowego static. Jak już napisałem, modyfikator static nie może wystąpić w parze z modyfikatorem abstract.

Słówko kluczowe synchronized wskazuje, że oznaczona nim metoda może być wykonywana w danym czasie co najwyżej przez jeden wątek. Mówiąc precyzyjniej, metoda taka działa jak monitor (pojęcie z programowania współbieżnego, nie chodzi o monitor w sensie ekranu). Jeśli metoda jest statyczna to monitor ten synchronizuje się na obiekcie klasy a jeśli nie to na obiekcie, dla którego metoda została wywołana. Naturalnie, słówko kluczowe synchronized nie może wystąpić w parze ze słówkiem abstract.

Modyfikator native oznacza, że metoda została zaimplementowana w sposób charakterystyczny dla danej platformy, czyli najpewniej przy użyciu innego języka programowania, np. C czy C++. Autorzy Książki twierdzą, że na potrzeby egzaminu SCJP nie trzeba wiedzieć, jak implementować tego typu metody, wystarczy znajomość hasłowa. Trzeba zatem wiedzieć, że deklarując metodę jako native kończymy jej deklarację średnikiem, zupełnie tak jakbyśmy deklarowali metodę abstrakcyjną. Jakże mogłoby być inaczej, w końcu nie będziemy przecież podawać implementacji w języku C. Naturalnie, metoda oznaczona modyfikatorem native nie może być jednocześnie abstract, ale uwaga! Nie może być także strictfp, choć tą informację znalazłem w specyfikacji języka, w Książce jej nie widziałem. Jest natomiast w Książce podkreślone dla lepszego uświadomienia, że modyfikator native może być użyty tylko i wyłącznie w deklaracji metody. W deklaracji klasy czy zmiennej nie! Tylko metody!

O strictfp już pisałem, ale przypomnę. Modyfikator strictfp oznacza, że wszystkie operacje zmiennoprzecinkowe w danej metodzie będą zgodne ze standardem IEEE 754, tj. wirtualna maszyna Javy wykona instrukcje zmiennoprzecinkowe w sposób zgodny z tym standardem. Modyfikator ten może być zastosowany przy deklaracji metody oraz klasy, ale nigdy przy deklaracji zmiennej. Jeśli klasa jest zadeklarowana jako strictfp to oznacza to tyle, że wszystkie jej metody oraz klasy zagnieżdżone również są strictfp. Także zmienne zadeklarowane w klasie są inicjalizowane zgodnie z arytmetyką strictfp (choć same zmienne nie mogą być strictfp). Modyfikator strictfp nie może być użyty razem z modyfikatorem abstract ani native.

I jeszcze jedna rzecz dotycząca deklaracji metod – metody ze zmienną liczbą parametrów (ang. var-args). Począwszy od Javy 5 możemy zadeklarować, że metoda akceptuje dowolną liczbę argumentów pewnego ustalonego typu, przy czym dopuszczone są wszystkie typy, zarówno prymitywne jak i obiektowe. Możemy więc zadeklarować ‘fun(int… x)’ co będzie oznaczało, że metoda akceptuje dowolną liczbę argumentów typu ‘int’. Sładnia jest właśnie taka, że po nazwie typu umieszczamy 3 kropeczki, po czym podajemy nazwę zmiennej, która de facto będzie tablicą. Metoda może akceptować także inne parametry, czyli poprawną jest deklaracja ‘fun(char a, long… x)’. Ważne jest, że metoda może zawierać tylko jeden parametr tego rodzaju i że musi on być zadeklarowany na końcu listy parametrów. Poniższy kod ilustruje to zagadnienie.

public class AnyClass {
void testFun() {
fun("any", 1, 2, 3, 4);
}

void fun(String str, Integer... ints) {
System.out.println(str + ints.length);

for (Integer x : ints) {
System.out.println(x);
}
}
}

4 komentarze:

Przemek pisze...

Hej,
ja troszeczke sie doczepie do stwierdzenia:
"Jeśli metoda jest zadeklarowana jako abstract to jednocześnie może być zadeklarowana tylko jako public lub protected, modyfikator abstract nie może być użyty w parze z żadnym innym modyfikatorem."

Ile mamy tych "żadnych innych modyfikatorów"? Zdanie powyższe sugeruje że conajmniej dwa ale ja bym powiedział że dokładnie jeden (private).

Prawdopodobnie chodziło Ci o jeszcze czwarty poziom dostepu - "default", - ale uwaga to jest poziom a nie modyfikator.

W Javie mamy trzy modyfikatory dostepu (public, private, protected) które tworzą cztery pozimy dostepu (jw + default).
Miło się czyta serię o SCJP.

Mariusz Lipiński pisze...

Hej,

dzięki za uwagę. Masz rację, że jeśli chodzi o modyfikatory dostepu to jest ich tylko trzy, ale ja miałem na myśli wszystkie modyfikatory, w tym np. strictfp. Być może powinieniem to jakoś wyraźnie zaznaczyć.

Pozdr. Mariusz Lipiński

Anonimowy pisze...

A czy klasa abstrakcyjna przypadkiem nie może mieć modyfikatora strictfp? np class strictfp abstract StrictAbstract{}

Mariusz Lipiński pisze...

Rzeczywiście,

może, z tym że:

abstract strictfp class StrictAbstract {}

a nie

class strictfp abstract StrictAbstract{}