Java, podobnie jak i inne języki programowania, zawiera w sobie szereg różnorodnych typów danych pozwalających stworzyć zmienne przechowujące w sobie reprezentację wszystkich podstawowych wartości mogących być potrzebnymi w ramach rozwiązywanych zagadnień. Można wyróżnić tzw. typy proste, typy złożone i typ łańcuchowy. Ten ostatni jednak może być także uznany jako typ złożony, ale z uwagi na jego charakter wydzielamy go jako osobny rodzaj.

Typy proste

Liczby całkowite

Typami prostymi liczbowymi nazywamy każdy rodzaj wartości dający się zapisać jako liczba1W tej definicji jest pewna pułapka, bowiem każdy typ wartości w systemach komputerowych jest zapisywany jako liczba. Dopiero interpretacja tej liczby pozwala traktować go jako coś odmiennego. Nie sięgamy jednak po tak wnikliwą analizę zapisu typu..

Można wyróżnić cztery typy danych dla liczb całkowitych, są to:

Nazwa
Typu
Zajętość
pamięci
ZakresWartość
domyślna
byte1 bajt-128 ÷ 1270
short2 bajty-32768 ÷ 327670
int4 bajty-2 147 483 648 ÷ 2 147 483 647
lub
-231 ÷ 231 -1
0
long8 bajtów-263 ÷ 263 -10L
Zestawienie prostych typów liczb całkowitych

Najczęściej używanym typem jest int, z zasady mieszczą się w nim te wartości, które są najczęściej używane, a sam typ nie jest za bardzo pamięciożerny, sama Java traktuje tego typu wartości z reguły jako int. Wartości typu long powinny być oznaczone przyrostkiem l lub L, inaczej jeśli będą się mieścić w zakresie to zostaną przez system uznane za int. Nie jest to duży problem w przypadku pojedynczych zmiennych i przechowywanych w nich małych wartości. Problemem może być czas konwersji wartości przy bardzo częstych odwoływaniach się do tych zmiennych. O konwersji będzie mowa trochę później. Istnieją także inne typy liczb całkowitych (np. BigInteger), wykorzystywane np. w operacjach finansowych, ale stanowią one już odrębny temat i nie zostaną tutaj omówione.

Liczby zmiennoprzecinkowe

Nie wszystkie wartości są całkowite, a w zasadzie tylko ich część da się określić jako całkowita. Dość często więc będziemy mieli do czynienia ze zmiennymi zawierającymi wartości rzeczywiste, czyli „z przecinkiem”. W takim przypadku mamy do czynienia z:

Nazwa
Typu
Zajętość
pamięci
PrecyzjaWartość
domyślna
float4 bajtyok. 6÷7 liczb po przecinku0.0f
double8 bajtówok. 15 liczb po przecinku0.0d
Zestawienie prostych typów liczb zmiennoprzecinkowych

Jak widać takie liczby nie cechują się zakresem, a precyzją z jaką odwzorowują rzeczywistą wartość. Wiąże się z tym ryzyko niedokładności odwzorowania, które będzie omówione w temacie dotyczącym pętli. Domyślną precyzją w języku Java jest precyzja reprezentowana poprzez typ double. Należy pamiętać, że wartości tych typów oznaczamy przyrostkiem F lub w przypadku typu float, oraz D lub d w przypadku double. Pominięcie przyrostka zostanie potraktowane przez Javę jako podanie zmiennej typu double. Istnieją także inne typy liczb zmiennoprzecinkowych (np. BigDecimal), wykorzystywane np. w operacjach finansowych, ale stanowią one już odrębny temat i nie zostaną tutaj omówione.

Typ znakowy

Takim typem jest char (ang: znak), który przechowuje w sobie reprezentację wartości interpretowaną jako znak w kodowaniu Unicode. Ten typ jest istotny do operowania interakcją z użytkownikiem, sterowania pętlami, sterowania wyświetlaniem itp. Wartością domyślną przy deklaracji zmiennej typu znakowego, a bez inicjalizacji wartością jest '\u0000′ (znak Unicode o wartości 0 – szesnastkowo 0x0000). Generalnie ujmując tę kwestię znaki mają wartości wynikające z tablicy ASCII2W linku zaprezentowana jest 7-bitowa tablica ASCII odwzorowania alfabetu i znaków sterujących., bądź w przypadku notacji rozszerzonej w tablicy Unicode3W linku zaprezentowany jest fragment tablicy Unicode zawierający znaki specjalne..

W typie znakowym można wyróżnić kilka znaków szczególnych, stosowanych np. w prostym formatowaniu przy wyświetlaniu komunikatów na konsolę. Znaki takie aby były potraktowane jako sterujące muszą być poprzedzone tzw. znakiem ucieczki „\”, są to:

  • \t – (ang: tab) tabulacja [kod ASCII 9],
  • \n – (ang: next line) przejście do nowej linii [kod ASCII 10],
  • \r – (ang: control/carriage return) – powrót na początek linii (powrót karetki)[kod ASCII 13],
  • \” – użyj znaku cudzysłowu (cudzysłów jest używany do obramowania tekstu)[kod ASCII 34],
  • \’ – użyj znaku apostrofu (apostrofy używane są do typów znakowych)[kod ASCII 44],
  • \\ – użyj znaku backslash[kod ASCII 92].

Należy pamiętać, że pomimo tego, że w typie znakowym przyporządkowujemy mu wartości będące znakami, to jak zostało napisane znaki mają wartość. Typ jest, podobnie do typów całkowitych, typem wyliczeniowym, czyli wartości ułożone są w odpowiedniej kolejności względem siebie.

Typ logiczny

Ostatnim typem prostym jest typ przechowujący dwie wartości:

  • true – prawda,
  • false – fałsz

Zajętość tego typu to 1 bajt, a używany jest najczęściej jako znacznik logiczny wystąpienia jakiegoś zdarzenia, np. porównania ze sobą wartości dwu liczb, gdzie wynikiem takiego porównania jest np. prawda (są równe) lub fałsz (nie są równe). Często ten typ wykorzystywany jest w pętlach i warunkach. Wartością domyślną, przy deklaracji zmiennej bez przypisania wartości jest: false.

Typy złożone

Typami złożonymi są takie rodzaje wartości których nie da się zapisać za pomocą typów prostych. Należą do nich wspomniane już takie typy jak BigInteger czy BigDecimal. Do typów złożonych mogą należeć także typy rekordowe (nie chodzi tu o rekord sportowy ;-), a o złożenie różnych typów prostych w jedną spójną strukturę). W języku Java nie ma takich tworów jak Struct lub Union znanych z języka C/C++, wszystkie takie hermetyzacje odbywają się w ujęciu obiektowym, które zostanie omówione nieco później.

Typ łańcuchowy

Typem łańcuchowym, jest typ złożony (patrz wyżej) z łańcucha znaków, czyli tzw. łańcuch znakowy. Jest to obiektowy typ String. W zmiennych tego typu przechowywane są wszystkie wieloznakowe wartości służące do np. wypisywania komunikatów, czy przetwarzania tekstu np. „Ala ma kota”. Wartością domyślną przy powołaniu do życia zmiennej typu znakowego, a bez przypisania jej wartości, jest null (zmienna wskaźnikowa wskazująca na… brak wskazania).

Dosyć ciekawą informacją jest wykorzystanie zapisu Unicode w ramach wartości łańcuchowej bądź znakowej w celu uzyskania znaku nie będącego dostępnym na naszej klawiaturze, a zakodowanego w tablicy Unicode. Przykładem może tu być taki łańcuch: „S\u00ED Se\u00F1or„, a mający w rezultacie wynikową wartość: „Sí Señor„. Prawda, że przydatne?!

Zmienne

Zmienne noszą przyznane im przez programistę nazwy, przyporządkowany jest do nich typ, oraz w sytuacjach szczególnych oznaczone są jako wartościowo nie modyfikowalne tzw. stałe. Przechowują one przetwarzane w programie wartości i są znaczącym uproszczeniem dla programisty, gdy nie musi on samodzielnie rezerwować pamięci i składować w niej reprezentacji liczbowej używanych wartości. Część deklaratywna zmiennych wygląda następująco:

        int a;
        byte b;
        float f;
        boolean g;
        String Imie;

Część deklaratywno-inicjalizująca wygląda tak:

        byte b=67;
        char c='z';
        int i=6+c;
        int j=17;
        int o, t, m=83, rKwadrat=81;
        float f=98.67f;
        boolean g=true;
        String Imie="Ala";

Przypisywanie wartości już zadeklarowanych zmiennych może wyglądać tak:

        b=97;
        c=65;
        i=c;
        f=100f;
        g=false;
        Imie = "Hanna";

Błędem jest próba podwójnej inicjalizacji zmiennej (przykład poniżej) i środowisko programistyczne na to nie pozwoli. Zmienną definiuje się tylko raz, wielokrotnie można za to zmieniać jej wartość.

        int a=6;
        String Imie="Ala";
        int a=9;
        String imie="Aleksander";

Należy zauważyć, że środowisko „oburzyło się” jedynie w przypadku zduplikowanej definicji zmiennej a. Ten przykład pokazuje więc, że środowisko rozpoznaje wielkość liter i należy o tym pamiętać, bo może to stanowić źródło potencjalnych błędów i problemów w działaniu programów. Nazwami zmiennych muszą być wobec tego unikalne ciągi znakowe zawierające małe lub duże litery, oraz cyfry (z tym, że cyfra nie może rozpoczynać takiego ciągu!). Dobrym zwyczajem jest używanie jednego standardu w tworzeniu nazw zmiennych tj. uporządkowanie modelu ich nazywania w tzw. notacji. Wyróżnić można przynajmniej kilka notacji zapisu nazw zmiennych i są to np. notacja węgierska (ang: Hungarian notation)4W tej notacji nazwy zmiennych rozpoczynają się od litery określającej typ zmiennej w celu łatwego rozróżnienia w trakcie programowania, tak na przykład:
int iWartosc, iDlugosc, iWiek;
, notacja wielbłądzia (ang: camelCase notation)5Notacja rozpoczynająca się z małej litery i złożona ze słów określających rolę takiej zmiennej w sposób taki, że każde nowe słowo w nazwie jest akcentowane dużą literą, tak na przykład:
int wiekDrzewa;
float objetoscBryly;
, notacja Pascal’owa (ang: PascalCase notation)6Nazwy zmiennych w tej notacji są tworzone podobnie do poprzedniej tylko od razu akcentowane dużymi literami, np.:
int RozmiarOknaPanelu
, itp.

Pewnie dało się już także zauważyć, że jeśli deklarujemy kilka zmiennych tego samego typu, to możemy dokonać tego w jednej linii kodu rozdzielając kolejne zmienne znakiem przecinka.

Należy także zauważyć, że zmienne mogą być oznaczone jako stałe, co powoduje, że przez całe życie zmiennej w programie niedozwoloną jest próba zmiany jej wartości. Stałe deklaruje się z użyciem słowa kluczowego final w następujący sposób:

final float Pi = 3.14159f; 

To co jest istotne, to użycie słowa kluczowego (dezyderaty) final, a nie jak mogłyby się spodziewać osoby znające inne języki programowania słowa kluczowego const. To ostatnie jest określane przez język Java jako słowo kluczowe, jednakże pomimo zarezerwowania terminu, nie jest ta forma w żaden sposób używana. Nadmienić także trzeba, że stałej nie trzeba od razu inicjalizować wartością jak w powyższym przykładzie, można taką zmienną zadeklarować jak poniżej:

final float Pi;


Pi = 3.14159f; 

Jak widać, środowisko programistyczne przyjmuje rozdzielenie części deklaratywnej od inicjalizacyjnej dla zmiennych określonych dezyderatą stałej. Jednakże poprawnym będzie tylko pierwsze przypisanie wartości do tak utworzonej stałej. Próba kolejnego przypisania wartości kończy się już wygenerowaniem błędu.

Konkludując, można pokusić się o zapisanie w całości naszego kodu programu, definiując i inicjalizując kilka zmiennych wartościami, a następnie spróbować je wyświetlić z wykorzystaniem strumienia wyjściowego na konsolę (ekran). Program taki może wyglądać jak poniżej:

package nowyprojekt1;
public class NowyProjekt {

    public static void main(String[] args) {
       
        String imie="Ala";
        int wiek=21, wzrost=176;
        final int y;
        y=56;
        final String plec="Kobieta";

        System.out.println(plec+", studentka "+imie+" mająca lat "+wiek+" z uwagi na wzrost "+wzrost+"cm zaklasyfikowała się do grupy osób wysokich.");
        
    }    
}

Wynikiem działania ww. kodu będzie efekt zamieszczony na poniższym obrazie.

Przy powyższej okazji można było zapoznać się ze sposobem konkatenacji (złączania) łańcuchów tekstowych oraz sposobem wyświetlania komunikatu w oknie konsoli za pomocą metody println() strumienia Out, będącego częścią klasy System. Techniki te będą dogłębniej omówione już wkrótce.

Zadanie do samodzielnego opracowania: Zapoznać się ze typami zmiennych. Przećwiczyć deklarowanie i inicjalizację różnych typów danych. Spróbować zmieniać wartości powołanych do życia zmiennych poprzez nadawanie im nowych wartości i wyświetlanie tych wartości w oknie konsoli.