4. JAVA – typy danych


JAVA jest językiem ściśle typowanym, czyli w Javie typy danych są bardzo istotne, a co za tym idzie, każda zmienna już na początku musi mieć określony typ np.:

String name = "Ala"; //deklarujemy zmienną tekstową typu String
int liczba = 10; //deklarujemy zmienną liczbową typu int

gdzie String i int to typ zmiennej
name i liczba to nazwy zmiennych
Ala oraz 10 to przypisane wartości

Tworzenie zmiennych nazywamy również deklaracją lub inicjalizacją.

Dzięki typowaniu JVM wie, ile musi zarezerwować pamięci dla danej wartości.

Przykład:

Stwórzmy nowy plik(klasę) o nazwie „DataTypes” w folderze „com.cku.basics” – instrukcja w poprzednim temacie JAVA – zmienne (pierwszy przykład)

package com.cku.basics;

public class DataTypes {
    public static void main(String[] args) {
        //deklarujemy zmienną typu liczbowego int
        // o nazwie liczba1 i wartości 10
        int liczba1 = 10;

        //wyświetlamy wartość zmiennej
        System.out.println("Zmienna liczba1 ma wartość " + liczba1);
    }
}

/*
otrzymany wynik w konsoli:

Zmienna liczba1 ma wartość 10
*/

W powyższym przykładzie podczas wyświetlania został zastosowany operator „+” – za jego pomocą „doklejamy” kolejne rzeczy do wyświetlenia.

TYPY PROSTE

Całkowite:

byte1 bajtLiczby z zakresu -128 to 127
short2 bajtyLiczby z zakresu -32,768 to 32,767
int4 bajtyLiczby z zakresu -2,147,483,648 to 2,147,483,647
long8 bajtówLiczby z zakresu -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 (posiadają przyrostek L)
Tabela typów prostych

Przykład:

package com.cku.basics;

public class DataTypes {
    public static void main(String[] args) {
        //deklarujemy zmienną typu liczbowego byte (zakres: -128 to 127)
        byte liczba_byte = 10;

        //deklarujemy zmienną typu liczbowego short (zakres: -32,768 to 32,767)
        short liczba_short = 15000;

        //deklarujemy zmienną typu liczbowego int (zakres: -2,147,483,648 to 2,147,483,647)
        int liczba_int = -1500000000;

        //deklarujemy zmienną typu liczbowego long (zakres: -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807)
        long liczba_long = 9223372036854775807L;
    }
}

Uwaga: deklarując typ „long” należy na końcu liczby dopisać literę „L”

Zmiennoprzecinkowe (rzeczywiste):

float4 bajtyLiczby do 6-7 liczb po przecinku (posiadają przyrostek F, lub f)
double8 bajtówLiczby do 15 cyfr po przecinku (posiadają przyrostek D, lub d)
Tabela typów zmiennoprzecinkowych

Przykład (rozszerzamy poprzedni):

package com.cku.basics;

public class DataTypes {
    public static void main(String[] args) {
        /*
       tutaj kod z poprzedniego przykładu
        */

        //deklarujemy zmienną typu float: Liczby do 6-7 liczb po przecinku (posiadają przyrostek F, lub f)
        float liczba_float = 2.123456F;

        //deklarujemy zmienną typu double: Liczby do 15 cyfr po przecinku (posiadają przyrostek D, lub d)
        double liczba_double = 10.12345678910D;
    }
}

Typ logiczny – boolean

Typ boolean umożliwia zapisanie wartości logicznej true lub false. Jest to typ interpretowany jako prawda/fałsz.

Przykład (rozszerzamy poprzedni):

package com.cku.basics;

public class DataTypes {
    public static void main(String[] args) {
        /*
       tutaj kod z poprzedniego przykładu
        */

        //deklarujemy zmienną typu boolean: true lub false
        boolean wartosc_logiczna = true;
    }
}

Typ znakowy – char

Typ char pozwala na zadeklarowanie pojedynczego znaku Unicode, do zapisu liter, czy wyrazów stosujemy typ złożony String, o którym trochę później.

Przykład (rozszerzamy poprzedni):

package com.cku.basics;

public class DataTypes {
    public static void main(String[] args) {
        /*
         tutaj kod z poprzedniego przykładu
        */

        //deklarujemy zmienną typu char: pojedynczy znak Unicode
        char wartosc_char = '\u0041'; //litera A
    }
}

Typ wyliczeniowy- enum

Jest to typ, którym określamy zakres wartości jaki może przyjąć zmienna. Ograniczamy ilość wariantów dla danej zmiennej np. stan danego procesu może być tylko on lub off, mamy określoną ilość rozmiarów ubrań itd.

Typ ten deklarowany jest odmiennie niż do tej pory. Deklarujemy go przed „public static void main…”

Przykład (rozszerzamy poprzedni):

package com.cku.basics;

public class DataTypes {

    enum Stan {on, off};

    public static void main(String[] args) {
        /*
         tutaj kod z poprzedniego przykładu
        */

        //najpierw podajemy nazwę naszej "listy", czyli Stan
        //wymyślamy nazwę zmiennej, której przypiszemy jedną z wartości - u nas "stan"
        //określamy. którą wartość ma przyjąć zmienna - Stan.on
        Stan stan = Stan.on;
    }
}

Typ specjalny – var

Od Javy 10 wprowadzono typ „var”, który pozwala skrócić deklaracje zmiennych lokalnych i pozwala kompilatorowi na „domyślenie się” jaki typ przyjmie zmienna. NIE NADUŻYWAMY tego typu.

Wyobraźmy sobie, że mamy funkcję która przyjmuje 2 argumenty typu int i dodaje je do siebie – kompilator będzie wiedział, że wynik dodawania 2 int’ów to int.

public int add(int l1. int l2){
    var result = l1 + l2;
    return result;
}

Literały i znaki specjalne

Literał to sposób zapisu danych. Te same wartości mogą być zapisane np. jako liczba dziesiętna, szesnastkowa lub w systemie ósemkowym. Literałami są też przyrostki, które dodajemy na końcu liczb np. typu double, czy float.

Literałami są też znaki specjalne wykorzystywane w programowaniu:

New line (znak nowej linii)\n
Horizontal tab (tabulacja pionowa)\t
Backspace\b
Carriage return (powrót karetki)\r
From feed (znak nowej strony)\f
Single quote (apostrof)\’
Double quote (cudzysłów)\”
Backslash (lewy ukośnik)\\
znaki specjalne

znak specjalny „nowej linii” już używaliśmy w temacie 2. JAVA – pierwszy program, wyświetlanie danych, komentarze

TYPY ZŁOŻONE

W Javie istnieją różne klasy osłonowe(nie mówimy tu o klasach w obiektówce), są to zbiory pewnych metod/funkcji już określonych i wykonujących konkretne operacje.Można zapoznać się z listą dostępnych w Java klas w dokumentacji.

Wymienione wyżej typy proste tj. byte, short, int, long, float, double, char, boolean mają swoje odpowiedniki w postaci klas: Byte, Short, Integer, Long, Float, Double, Char, Boolean, które określamy mianem typów złożonych.

Poznany wcześniej typ String jest klasą osłonową, czyli typem złożonym, dzięki któremu możemy np. wykonywać różne operacje na ciągach. Klasa Integer umożliwia nam wykonywanie zaawansowanych operacji na liczbach.

Najczęściej będziemy wykorzystywali dwa typy złożone – String oraz Integer. Szczegółowo zostaną opisane w następnych tematach.

RZUTOWANIE/KONWERSJA

Tworząc program niejednokrotnie natrafimy na sytuację, w której konieczna będzie zmiana typu zmiennej.  Takie operacje mogą spowodować nieoczekiwane błędy, straty itp., jest to bardzo niebezpieczny temat np. podczas pisania programów księgowych. Wyobraźmy sobie sytuację, że piszemy skrypt obsługujący operacje na koncie bankowym i nagle okazuje się, że liczby po rzutowaniu tracą swoją część – jest to oczywiście niedopuszczalne. Zatem zwracajmy baczną uwagę przy zmianie typu.

Typ zmiennej zmieniamy podając w nawiasach zwykłych nazwę pożądanego typu przed nazwą zmiennej: int a = (int) b.

Zmiana typu zmiennej, która nie powoduje utraty danych nazywa się konwersją niejawną i nie wymaga bezpośredniej ingerencji programisty – kompilator sam zmieni taki typ. Przeanalizujmy sytuację, w której zmienną int przypiszemy do zmiennej double:

//konwersja typu int na double
int a = 12;
System.out.println("Liczba a typu int: " + a);
double b = a;
System.out.println("Liczba b typu double: " + b);

/*
Wynik w konsoli:

Liczba a typu int: 12
Liczba b typu double: 12.0
*/

Możemy zauważyć, że nie straciliśmy żadnej części z naszej liczby, dodał się tylko przecinek – automatycznie. Kompilator sam zmienił liczbę.

Inna sytuacja występuje, gdy chcemy np. zmienić liczbę typu double na int. Dla przykładu mamy liczbę typu double c=1.2 i chcemy by była int – stracimy wtedy to co jest po przecinku. Kompilator nie pozwoli nam na to automatycznie, musimy świadomie zapisać taką zmianę i to właśnie nazywa się rzutowaniem typów (casting).

Dla przykładu spróbujmy dokonać konwersji niejawnej typu double na int:

//konwersja double na int
double c = 1.2;
System.out.println("Liczba c typu double: " + c);
int d = c;
System.out.println("Liczba d typu double: " + d);
/*
Wynik w konsoli:

java: incompatible types: possible lossy conversion from double to int
*/

Możemy zauważyć błąd, kompilator ostrzega nas przed utratą danych. Zróbmy więc to jak należy – dokonajmy jawnego rzutowania, przekażmy kompilatorowi informację, że jesteśmy świadomi zagrożeń:

//rzutowanie double na int
double c = 1.2;
System.out.println("Liczba c typu double: " + c);
//int d = c; //taki zapis spowoduje błąd, próbowaliśmy dokonać konwersji stratnej
int d = (int)c;
System.out.println("Liczba d typu double: " + d);

/*
Wynik w konsoli:

Liczba c typu double: 1.2
Liczba d typu double: 1
*/

W powyższym przykładzie widzimy, że straciliśmy część po przecinku.

Konwersji niejawnej możemy dokonać z „mniejszego” typu na „większy” – bez utraty danych, ale należy uważać na 3 przypadki:

  • konwertując int na float
  • konwertując long na float
  • konwertując long na double

Zadania:

  1. Napisz skrypt, który wyświetli w oknie przeglądarki tekst:
    I’m the best!
    oraz tekst:
    This is a bad command : del c:\\*.*
    Każdy napis w osobnej linii.
  2. Zdefiniuj stałą URL, przypisz do niej adres internetowy i wyświetl ją.
  3. Dokonaj konwersji i rzutowania pomiędzy różnymi typami danych, które poznałeś/aś. W komentarzach w pliku zapisz wnioski. Zwróć uwagę na konwersję typu char do int, jak można rozwiązać zaistniały „problem”. (tabela kodów ASCII)

Sprawdź się:

  1. Jakie znasz typy proste w Java?
  2. Jakie znasz typy złożone w Java?
  3. Co oznacza rzutowanie typów?
  4. Co należy zrobić, aby nie stracić wartości po przecinku podczas dzielenia?