[ Pobierz całość w formacie PDF ]
stać ze zmiennej , gdyż została ona zdefiniowana w bloku zewnętrznym, do którego
ma dostęp blok wewnętrzny.
Wewnątrz bloku deklaracja zmiennej może pojawić się w dowolnym wierszu, ale jest
poprawna dopiero po nim. Z tego powodu zadeklarowanie zmiennej na poczÄ…tku metody
powoduje, że jest ona dostępna dla całego kodu tej metody. Deklaracja zmiennej na
końcu bloku nie ma sensu, ponieważ żaden fragment kodu nie będzie miał do niej do-
stępu. Poniższy fragment kodu nie jest poprawny, gdyż zmienna nie może zostać
użyta przed jej zadeklarowaniem.
Ten fragment zawiera błąd!
Ojej! Nie można użyć zmiennej count zanim nie zostanie zadeklarowana!
Warto pamiętać o innej bardzo istotnej kwestii: zmienne są tworzone w momencie
wejścia w ich zasięg i niszczone przy wychodzeniu z danego zasięgu. Oznacza to, że
zmienna nie będzie przechowywała swojej wartości, gdy znajdzie się poza zasięgiem.
Właśnie z tego powodu zmienne metody nie zachowują swoich wartości między ko-
lejnymi wywołaniami metody. Podobna sytuacja dotyczy bloków zmienna utraci
swoją wartość, gdy wyjdziemy z bloku. Innymi słowy, czas życia zmiennej jest ściśle
związany z jej zasięgiem.
Jeśli deklaracja zmiennej zawiera inicjalizację, zmienna ta zostanie ponownie zainicjali-
zowana przy każdym wejściu do bloku, do którego jest przypisana. Rozważmy nastę-
pujÄ…cy program.
Przykład czasu życia zmiennej.
y jest inicjalizowane przy każdej iteracji pętli
76 Część I f& Język Java
zawsze zostanie wyświetlone 1
Wykonanie programu spowoduje wyświetlenie następującego wyniku.
Jak łatwo zauważyć, przy każdej nowej iteracji pętli zmienna jest ponownie ini-
cjalizowana wartością 1. Choć pózniej zostaje jej przypisana wartość 100, jest ona
tracona w kolejnej iteracji.
Ostatnia uwaga: choć bloki mogą być zagnieżdżane, nie można zadeklarować zmiennej
o takiej samej nazwie jak zmienna z bloku zewnętrznego. Poniższego programu nie
uda się skompilować.
Ten program siÄ™ nie skompiluje.
tworzy nowy zasięg
Błąd kompilacji -- zmienna bar jest już zadeklarowana!
Konwersja typów i rzutowanie
Jeśli ktoś wcześniej pisał programy komputerowe, zapewne wie, że często zachodzi
potrzeba przypisania wartości jednego typu do zmiennej innego typu. Jeśli oba typy
są ze sobą zgodne, Java dokona automatycznej konwersji. Na przykład zawsze można
przypisać wartość typu do zmiennej . Niestety, nie wszystkie typy są ze sobą
zgodne i z tego powodu niejawna konwersja nie zawsze jest dozwolona. Na przykład
Java nie wykona automatycznej konwersji z typu do typu . Na szczęście
nadal można dokonać takiej konwersji, ale trzeba to zrobić jawnie, używając tak zwanego
rzutowania typów. Przyjrzyjmy się teraz konwersji automatycznej oraz rzutowaniu.
Automatyczna konwersja typów
Gdy jeden typ danych jest przypisywany do zmiennej innego typu, automatyczna kon-
wersja typu zostanie wykonana, jeśli zostaną spełnione oba poniższe warunki:
Rozdział 3. f& Typy danych, zmienne i tablice 77
oba typy danych sÄ… zgodne,
typ docelowy jest pojemniejszy (w sensie zakresu) od typu zródłowego.
Po spełnieniu obu warunków dochodzi do tak zwanej konwersji rozszerzającej. Na
przykład typ jest na tyle pojemny, że zawsze potrafi pomieścić wszystkie wartości
typu , więc Java nie wymaga jawnego rzutowania.
W przypadku konwersji rozszerzającej, typy numeryczne (typy całkowite i zmiennoprze-
cinkowe) sÄ… ze sobÄ… zgodne. Z drugiej strony, typy numeryczne nie sÄ… zgodne z typami
i . Dodatkowo, typy i nie są zgodne między sobą.
Wspomniano już wcześniej, że Java dokonuje automatycznej konwersji literałów całko-
witych do zmiennych typu , oraz .
Rzutowanie dla typów niezgodnych
Choć konwersja automatyczna jest pomocna, nie pokrywa wszelkich możliwych sy-
tuacji. Na przykład zachodzi potrzeba konwersji z typu do typu . Nie dojdzie
w tej sytuacji do konwersji automatycznej, ponieważ typ jest mniejszy od typu
. Teki rodzaj konwersji jest często nazywany konwersją zawężającą, gdyż doko-
nuje jawnego ograniczenia wartości zródłowej do zakresu docelowego typu.
Aby dokonać konwersji między dwoma niezgodnymi typami, trzeba użyć rzutowania.
Rzutowanie to po prostu jawna konwersja typu. Jego ogólna postać jest następująca.
Element określa typ, do którego ma zostać skonwertowana .
Poniższy fragment kodu dokonuje konwersji z typu do typu . Jeśli wartość
w zmiennej jest większa od dopuszczalnego zakresu typu , zostanie wykonana
operacja modulo (reszta z dzielenia liczby przez zakres nowego typu) ograniczajÄ…ca
tę wartość do zakresu .
...
Inny rodzaj konwersji wystąpi, gdy liczba zmiennoprzecinkowa będzie konwertowana
do typu całkowitego wystąpi wtedy tak zwane obcięcie. Liczby całkowite nie mają
części ułamkowej. Z tego powodu przy opisanej konwersji tracona jest informacja na
temat ułamka. Jeśli na przykład przypiszemy wartość 1,23 do typu całkowitego, uzyska-
my wartość 1. Ułamek 0,23 zostanie obcięty. Oczywiście, jeśli ogólna wartość będzie
za duża, aby zmieścić się w docelowym typie, zostanie dodatkowo wykonana redukcja
modulo dla zakresu docelowego typu.
Poniższy program przedstawia kilka konwersji wymagających rzutowania.
Przykłady rzutowania.
78 Część I f& Język Java
Wynik działania programu jest następujący.
Przyjrzyjmy się poszczególnym konwersjom. Gdy wartość 257 jest rzutowana do typu
, wynikiem jest reszta z dzielenia 257 przez 256 (zakres typu ), czyli wartość 1.
Gdy zmienną d konwertujemy do typu , tracimy część ułamkową. Gdy zmienną
d konwertujemy do typu , tracimy część ułamkową oraz dodatkowo dochodzi do
redukcji modulo 256, co powoduje uzyskanie wartości 67.
Automatyczne rozszerzanie typów
w wyrażeniach
[ Pobierz całość w formacie PDF ]