3. Praktyczne przykłady
Omawianie skomplikowanego tematu obiektów i referencji warto zakończyć kilkoma
przykładami o nieco bardziej praktycznym charakterze, pokazującymi jednocześnie,
że słowo kluczowe null bardzo w programowaniu się przydaje, a referencja
do pustego łańcucha znakowego jest czymś innym niż zmienna typu String, która
nie wskazuje na żaden obiekt.
Przy okazji poznamy wstępnie pewne możliwości interakcji z programem: wprowadzanie danych w dialogu wejściowym oraz pokazywania
komunikatów w dialogu komunikatów, a także sposób uzyskiwania ze znakowej
(napisowej) reprezentacji liczby całkowitej - jej binarnej (wewnętrznej)
wartości, na której można wykonywać operacje arytmetyczne.
Zapis w programie:
String s = JOptionPane.showInputDialog("Komunikat");
spowoduje otwarcie okienka dialogowego z komunikatem "Komunikat", w którym
będzie można wprowadzić jakiś tekst. Po kliknięciu w przycisk Ok wprowadzony
łańcuch znakowy będzie dostępny za pomocą zmiennej s. Zamknięcie dialogu (np.
przyciskiem Cancel) spowoduje, że zmienna s będzie miała wartośc null.
Zapis:
JOptionPane.showMessageDialog(null, "Komunikat");
pokaże okno dialogowe z komunikatem "Komunikat" (w tym zapisie null
mówi m.in. o tym, że okno dialogowe ma być wycentrowany w obszarze pulpitu graficznego
interfejsu systemu operacyjnego; zamiast null można podać referencję do obiektu-okna
- innego od pulpitu)
Aby korzystać z tych możliwości trzeba w pierwszym wierszu programu wpisać:
import javax.swing.JOptionPane; (dzięki temu będzie można użyć nazwy JOptionPane,
która jest nazwą klasy).
Co konkretnie oznaczają te zapisy (oraz "import") dowiemy się w następnych wykładach, a szczegóły
stosowania dialogów poznamy (niestety dopiero) w drugim semestrze.
Teraz istotne jest tylko to, że (może jeszcze nie bardzo wiedząc o co chodzi)
będziemy mogli komunikować się w (w miarę) wygodnej formie z naszymi programami.
Pierwszy przykładowy program jest kolejną wariacją na temat "Hello world" czy "Dzień dobry".
import javax.swing.JOptionPane;
public class GreetMsg {
public static void main(String[] args) {
String name = JOptionPane.showInputDialog("Podaj swoje imię");
if (name == null) name = "";
JOptionPane.showMessageDialog( null, "Witaj " + name + "!");
System.exit(0);
}
}
Uwidoczni on dialog wejściowy, w którym będziemy mogli wprowadzić tekst.
Gdy po wpisaniu tekstu klikniemy "Ok", to zmienna name będzie wskazywać na
napis, który wprowadziliśmy w dialogu. Jeśli natomiast zamkniemy dialog,
albo klikniemy "Cancel", to wynikiem odwołania JOptionPane.showInputDialog(...)
będzie null i tę właśnie wartość będzie miala zmienna name (oc oznacza, że
nie wskazuje na żaden łańcuch znakowy).
W takim przypadku przypiszemy jej referencję do pustego łańcucha znakowego "".
Następnie odwołanie JOptionPane.showMessageDialog(..) pokaże komunikat z powitaniem (z podanym imieniem lub bez).
Ciekawe, co by się stało, gdyby usunąć z programu instrukcję if (...) i pozwolić
na to, by przy zamknięciu dialogu przez Cancel zmienna name miala wartośc
null.
No, cóż dostalibyśmy niezbyt grzeczny komunikat "Witaj null!" ( konkatenacja przekształca wartość null na napis null).
Ale problem nie w grzeczności.
Gdybyśmy dodali na końcu programu instrukcję wyprowadzającą na konsolę długość
łańcucha znakowego, wskazywanego przez name (tę długość możemy uzyskać pytając
o nią obiektu za pomocą polecenia length()):
System.out.println("długość: " + name.length());
to w przypadku usunięcia instrukcji if powstałby błąd wykonania, gdy zmienna name miałaby wartość null.
Istotnie pytalibyśmy wtedy niestniejącego obiektu o długość napisu w nim zawartego.
Pozostawiając if - gwarantujemy, że name będzie wskazywac zawsze na jakiś
obiekt. Gdy nie podano żadnego tektsu w dialogu lub wybrano Cancel - będzie
to pusty łańcuch znakowy. O długości 0. W uzupełnionym programie uzyskamy wtedy na konsoli komunikat: długość 0.
Pusty łańcuch znakowy (nie zawierający żadnego znaku) jest takim samym
obiektem jak każdy inny łańcuch znakowy. Należy odróżniać pusty łańcuch znakowy
(o długości 0) od wartości null. Zmienna typu String, która ma wartość null
nie wskazuje na żaden obiekt. Wtedy nie możemy jej używać do posyłania poleceń
do obiektu. Zmienna ta może jednak wskazywać na obiekt - pusty łańcuch znakowy
i wtedy możemy wobec niego stosować metody (polecenia) zdefiniowane w klasie
String.
Drugi program przykładowy łączy wprowadzane w kolejno (w pętli) pojawiających
się dialogach teksty w taki sposób, by pokazać je w dialogu jako komunikat
składający się z wielu wierszy (każdy wprowadzony tekst = jeden wiersz komunikatu).
Wprowadzanie kończy się i wynikowy komunikat zostaje uwidoczniony tylko wtedy,
gdy użytkownik zamknął (np. przez Cancel) dialog wejściowy. Program nie
pozwala dołączyć do zbioru tekstów pokazywanytych w dialogu wynikowym pustego
łańcucha znakowego. Jeżeli użytkownik nic nie wpisał w dialogu wejściowym
(inp.equals("") zwraca true), to program przypomina o konieczności wprowadzenia
tekstu (lub zrezygnowania z wprowadzania przez Cancel). Na rysunku obok pokazano
wynik działania programu po wprowadzeniu w kolejnych dialogach kilku nazw
zwierząt.
import javax.swing.JOptionPane;
public class ShowStrings {
public static void main(String[] args) {
String out = "";
String inp = null;
while ( (inp = JOptionPane.showInputDialog( "Wpisz coś" )) != null) {
if (inp.equals(""))
JOptionPane.showMessageDialog( null,
"Podaj dane lub zamknij dialog"
);
else out = out + '\n' + inp;
}
if (out.equals("")) out = "Nie wprowadzono żadnych danych";
JOptionPane.showMessageDialog(null, out);
System.exit(0);
}
}
Warte podkreślenia:
- w warunku while wykorzystano fakt, że przypisanie jest wyrażeniam o
wartości lewej strony; przy tym jednak trzeba było uwzględnić niski priorytet
operatora = i dlatego przypisanie jest ujęte w nawiasy
- kolejne wiersze wynikowego komunikatu uzyskiwane są przez przyłączenie znaku '\n' (przejście do nowego wiersza)
- porównanie zawartości łańcuchów znakowych - zawsze za pomocą equals
W obu programach zastosowano na końcu odwołanie System.exit(0). Powoduje
ono zakończenie działania programu (z podanym kodem wynikowym - w tym przypadku
0).
Normalnie program w Javie kończy swoje działanie, gdy zostaną wykonane wszystkie
instrukcje w metodzie main. Nie jest to jednak prawdą, jeśli w programie
korzystamy z elementów graficznego interfejsu użytkownika (powody tego zostaną
wyjaśnione później). Ponieważ dialogi pokazywane przez showXXXDialog są elementami
GUI, to trzeba było jawnie zakończyć działanie programu przez System.exit(...).
A jak wprowadzić do programu liczby?
Gdy w polu tekstowym okna dialogowego wpiszemy jakąś liczbę, to będzie ona
w programie dostępna jako napis (łancuch znakowy, String). Oczywiście nie
możemy na takim napisie wykonywać operacji arytmetycznych. Do tego potrzebne
jest przekształcenie znakowej (napisowej) reprezentacji liczby do postaci
binarnej (takiej, w jakiej liczby są zapisywane w pamięci komputera).
Do przekształcania napisów na liczby całkowite można wykorzystać następujące odwołanie:
liczba = Integer.parseInt(napis);
gdzie:
liczba - jest dowolną zmienną typu int,
napis - jest wyrażeniem typu String.
Oczywiście, nie każdy napis reprezentuje liczbę całkowitą. Jeśli np. w napisie
znajdzie się znak litery lub kropka dziesiętna, to przy próbie przekształcenia
napisu na liczbę całkowitą wystąpi błąd. W Javie taki błąd sygnalizowany
jest za pomoca wyjątku, który nazywa się NumberFormatException.
Dopóki (w ostatnim wykładzie) nie poznamy mechanizmu obsługi błędów (wyjątków)
musimy się liczyć z tym, że w takim przypadku wykonanie programu zostanie
przerwane.
Przykład: program sumujący dwie wprowadzone w dialogach liczby.
import javax.swing.*;
public class ParseInt {
public static void main(String[] args) {
String s1 = JOptionPane.showInputDialog("Podaj pierwszą liczbę");
String s2 = null;
if (s1 != null) {
s2 = JOptionPane.showInputDialog("Podaj drugą liczbę");
if (s2 != null) {
int l1 = Integer.parseInt(s1);
int l2 = Integer.parseInt(s2);
JOptionPane.showMessageDialog(null, "Suma: " + (l1 + l2));
}
}
System.exit(1);
}
}
Proszę wypróbować powyższy program przy różnych danych wejściowych, m.in.
takich które nie stanowią napisów reprezentujących liczby całkowite (w tym
- przy pustym łańcuchu znakowym, który zostanie wprowadzony, gdy wybierzemy
w dialogu Ok, nie wpisując nic do jego pola tekstowego).
|