« poprzedni punkt 

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);

  }

}

RysUwidoczni 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 "".

Rys 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.

Rys 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).


« poprzedni punkt