Szkolenia programowania we Wrocławiu
Kurs Java Podstawy - rozszerzony

Klasy osłonowe

Ponieważ w Javie typy proste, czyli int, double, float, czy boolean nie są typami obiektowymi, przez co nie można ich na nich wywoływać żadnych metod. Na szczęście istnieją klasy osłonowe, które dają nam sporo możliwości - przykładowo w łatwy sposób zmienić reprezentację liczb w systemie dziesiętnym na dwójkowy, czy szesnastkowy, lub zamienić je na Stringi. Jest to szczególnie przydatne, gdy przykładowo odczytujemy jakieś dane w postaci Stringów od użytkownika, bądź z plików, a chcielibyśmy uzyskać niektóre dane w formacie liczbowym.

Klasy osłonowe to odpowiednio:

  • Boolean - boolean
  • Character - char
  • Integer - int
  • Double - double
  • Float - float
  • Byte - byte
  • Short - short
  • Long - long

Niektóre z metod są statyczne, dzięki czemu dostęp do nich jest ułatwiony i można je wywołać w schematyczny sposób:

NazwaKlasy.nazwaMetody(parametr);
Przykładowo:
Integer.toString(5);

Wykorzystanie klas osłonowych nietrudno sobie wyobrazić. Jeśli chcemy odczytać dane od użytkownika przy pomocy buforowanego strumienia i wiemy, że będą tam dane różnego typu to należy użyć klasy osłonowej, aby zamienić ją z typu String na typ liczbowy należy użyć parsera, czyli metody parseInt(), parseDouble() itp.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Test{
	public static void main(String[] args) throws NumberFormatException, IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("Podaj imie: ");
		String imie = br.readLine();

		System.out.println("Podaj wiek: ");
		int wiek = Integer.parseInt(br.readLine());
	}
}

W przypadku metod typu parse należy pamiętać o zgłaszanym przez nie wyjątku typu NumberFormatException. Jest on zgłaszany w przypadku kiedy użytkownik wprowadzi przykładowo jakieś znaki alfanumeryczne w momencie pytania o wiek. Możemy go oczywiście przechwycić w bloku try catch i poprosić o ponowne wprowadzenie danych, co wydaje się być rozsądnym posunięciem.

Jeszcze ciekawsze możliwości daje nam klasa Character. Najpopularniejsze jej metody to:

-boolean isDigit() - sprawdza, czy podany argument w postaci znaku jest liczbą

-char toLowerCase(char) / toUpperCase(char) - zwracają podany znak odpowiednio w postaci małej, lub wielkiej litery

-boolean isWhiteSpace(char) - sprawdza, czy podany znak jest białym znakiem

Zobaczmy przykładowe działanie:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Test{
	public static void main(String[] args) throws NumberFormatException, IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		System.out.println("Podaj cyfrę od 0 do 9: ");
		String str = br.readLine();
		int liczba = 0;
		if(str.length()==1 && Character.isDigit(str.charAt(0))){
			System.out.println("hurra podałeś cyfrę");
			liczba = Integer.parseInt(str);
		}
		else{
			System.out.println("niestety podałeś nieprawidłowe dane");
		}
	}
}

Początek jest oczywisty, utworzyliśmy obiekt BufferedReader do odczytu strumienia wejścia, następnie wczytujemy linię tekstu, gdzie powinna być cyfra. Jeśli wprowadzony ciąg znaków ma długość różną od 1 to wiadomo, że cyfrą być nie może, następnie przy pomocy metody isDigit() klasy Character sprawdzamy, czy jest to faktycznie cyfra. Dzięki temu bez obaw możemy przypisać tę wartość przy pomocy metody parseInt() klasy Integer zmiennej liczba, ponieważ w przypadku wprowadzenia błędnych danych zostanie wyświetlony odpowiedni komunikat.

Komentarze

YeeeZooo

Nie bardzo rozumiem te wyjątki i try catch bo nie było tego wcześniej a robię lekcje po kolei. Można by to wyjaśnić.

Slawek

W sumie faktycznie się pospieszyłem trochę z napisaniem o tym :) (kiedyś) Będzie poświęcona temu osobna lekcja, jedna z kolejnych ... a kiedy będę miał czas ... hmm

s4ncho

jakby ktoś (tak jak ja) nie wiedział co to jest "biały znak"

"„białe znaki” (ang. white space), czyli spacje, tabulatory i znaki nowej linii (..)"
źródło: http://pl.wikipedia.org/wiki/Whitespace

Patryk

"-char toLowerCase(char) / tpUpperCase(char) – zwracają podany znak odpowiednio w postaci małej, lub wielkiej litery"
Czy tu nie zaszła literówka w tpUpperCase(char)? Gdyby literki 'o' i 'p', były trochę bardziej od siebie oddalone na klawiaturze, to bym nic nie mówił, ale w tym przypadku musiałem. Proszę o sprostowanie mojego toku myślenia.

andrew

Witam.
Po przeczytaniu fragmentu" "Wykorzystanie klas osłonowych nietrudno sobie wyobrazić. Jeśli chcemy odczytać dane od użytkownika przy pomocy buforowanego strumienia i wiemy, że będą tam dane różnego typu to należy użyć klasy osłonowej, aby zamienić ją z typu String na typ liczbowy należy użyć parsera, czyli metody parseInt(), parseDouble() itp." doszedłem do wniosku , że mamy tu do czynienia z konwersją Stringa na liczbe. Czyli podając w programie wiek w postaci np. "EA" powinienem otrzymać "6965". Niestety program wyrzuca błąd (jak niżej).
Druga rzecz to wyjątek : NumberFormatException
wpisujemy go tu public static void main(String[] args) throws NumberFormatException...
ale co to nam daje, skoro wpisując np. "xxx" przy pytaniu o wiek wyrzuca mi błąd:

at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)

Pomijając wyjątek w metodzie otrzymujemy to samo. Jak dla mnie sens ma tylko zastosowanie bloku "try catch ".

Slawek

A w jakim systemie liczbowym "EA" jest równe 6965, bo ja takiego nie znam. Zwykła metoda parseInt służy do tego, że wprowadzając dane w postaci Stringa "12345" po sparsowaniu otrzymujemy inta 12345. Jest też metoda parseInt(String, int), gdzie drugi parametr określa rodzaj kodowania - binarne 2, ósemkowe 8, dziesiętne 10, hexadecymalne 16.
Przykład
Integer.parseInt("EA", 16) = 14*16+10 = 234
co do wyjątku - w tej lekcji to bez znaczenia, bo to tylko przykład, w normalnej aplikacji jak najbardziej warto go obsłużyć, chociaż jeszcze lepiej zadbać o to, aby aplikacja była tzw idioto odporna.

miszczu

Warto wspomnieć, żeby nie porównywać tych obiektów w ten sposób:

Integer intA = 1000;
Integer intB = 1000;
System.out.println(intA == intB);

Powyższy kod wypisze na ekran false, gdyż porównujemy ze sobą
dwa różne obiekty, a nie ich wartość (1000). Jeśli chcemy porównać
liczby używamy na tych obiektach metody equals:

intA.equals(intB) // zwraca true dla powyższego przypadku.

Można się przejechać czasami, bo operator == zwraca prawidłowe
wartości dla małych liczb :)

WBAR

A nie można zamiast tak komplikować z tymi wyjatkami może na początku użyć klasy java.util.Scanner ?

WBAR



miszczu:

Warto wspomnieć, żeby nie porównywać tych obiektów w ten sposób:
Integer intA = 1000;
Integer intB = 1000;
System.out.println(intA == intB);
Powyższy kod wypisze na ekran false, gdyż porównujemy ze sobą
dwa różne obiekty, a nie ich wartość (1000). Jeśli chcemy porównać
liczby używamy na tych obiektach metody equals:
intA.equals(intB) // zwraca true dla powyższego przypadku.
Można się przejechać czasami, bo operator == zwraca prawidłowe
wartości dla małych liczb

A dlaczego ? bo "małe liczby" < 256 są trzymane w wirtualnej maszynie jako stałe statyczne więc:

int a = 5;
int b = 5;

a == b zwróci TRUE
Sławek Ludwiczak

akurat:
int a = 1000;
int b = 1000;
a==b też zwróci true. False jest zwracane w przypadku typu obiektowego Integer, gdzie następuje autoboxing typu prostego do obiektowego i wtedy faktycznie jest tak jak piszesz. W Javie 5 i 6 było to dla wartości