Zmienne

Bez występu tym razem są dwa typy zmiennych w Javie.

 

 

  • Primitives (typy proste) Oto kilka przykładowych  typów prostych: char, boolean, byte, short, int, long, double, float.  Gdy typ prosty jest zadeklarowany jego typ nigdy się nie zmienia ale jego wartość zazwyczaj tak.
  • Reference variables (typ referencyjny) Typ referencyjny jest używany jako adres do konkretnego obiektu. Typ referencyjny jest zadeklarowany do konkretnego  typu i ten typ nie może być później zmieniony.  Zmienna referencyjna może referować się do każdego obiektu z zadeklarowanym typem albo podtypem. Później omówię polimorfizm.

Przejdź do deklaracji typów prostych.

Deklarowanie typów prostych

Zmienne typów prostych mogą być deklarowane jako statyczne klasy, instancje zmiennych, parametry metody czy jako zmienne lokalne. Możesz zadeklarować jedną bądź więcej typów prostych tego samego typu w jednej linijce kodu.

byte b;
int x,y,z;
boolean myPrmitive,myLogic;

W poprzednich wersjach egzaminu trzeba było znać dokładny zakres wszystkich typów prostych. W tej wersji egzaminu nie trzeba znać takich szczegółów.  Jednak wciąż trzeba wiedzieć i znać kluczowe różnice w typach prostych liczb całkowitych. Pamiętać trzeba też o kolejności od najmniejszego zakresu do największej : byte, short, int, long.

Trzeba także wiedzieć o tym ,że typ double ma większy zakres niż float i są to typy liczbowe, które przechowują wartości dziesiętne.

Musisz także znać koncepcje bitów w typach liczbowych. Każde z tych  sześciu typów liczbowych składa się z konkretnego numeru 8- bitowego i jest on oznaczony, co znaczy ,że przechowuje pozytywne i negatywne wartości. Bit najbardziej na lewo jest używany do określenia pozytywnego bieguna i negatywnego. Jedynka określa wartość negatywną (ujemną) ,a 0 pozytywną (dodatnią). Reszta bitów służy do określenia wartość liczbowej przy notacji binarnej.

public class-06

Tabelka poniżej pokazuje zakres wartości typów, jak i ich rozmiar. Ilustracja powyżej pokazuje ,że byte posiada 256 wartości (sumując zakres dodatni i ujemny). Negatywny zakres zawsze jest mniejszy o jeden, ponieważ negatywny zakres nie przechowuje zera. Zero należy do części pozytywnej.

Używamy formuły –2^bity-1 to określenia zakresu negatywnego ,a do zakresu pozytywnego używamy wzoru  (2^bity-1)-1.

TypBityBajtyMinimalny zakresMaksymalny zakres
Byte81-2^72^7-1
short162-2^152^15-1
int324-2^312^31-1
long648-2^632^63-1
float324  
double648  


Zakres wartości liczb niecałkowitych jest trudny do określenia, ale tego nie musisz wiedzieć.

Dla wartości boolean nie ma zakresu. Zmienna boolean może być tylko prawdziwa bądź fałszywa (true,false). Ich zakres jest zależy od maszyny wirtualnej.

Typ char (znak) zawiera pojedynczy 16-bitowy znak Unicode. Znaki Unicode są reprezentowane przez wartość 16-bitową, która jest nieoznaczona (nie ma +-), co oznacza ,że przechowuje ona 2^16 wartości. Jest to zakres od 0 do 65535.

Deklarowanie zmiennych referencyjnych

Zmienne referencyjne mogą być zadeklarowane jako statyczne, instancje zmiennej, parametry metody i jako lokalne zmienne. Można deklarować więcej niż jedną zmienną referencyjną w jednej linijce kodu pod warunkiem ,że mają taki sam typ.

Object object;

String s2,s1,s3,s0; 
//deklarowanie 4 zmiennych string

Amiga myVariableReferenceToAmiga1200;

Instancje zmiennych

Instancje zmiennych są definiowane wewnątrz klas, ale poza metodami oraz są one inicjowane  wraz z stworzeniem instancji klasy. Instancje zmiennych są polami, które należą do każdego obiektu. Kod poniżej definiuje pola (instancje zmiennych) nazwisko i imię dla obiektu Osoba. Postanowiłem użyć nazw angielskich tym razem.

public class Person 
{
    //definicja pól (instancji zmiennych) dla instancji "Osoby" 
    private String name;
    private String surname;

    //inny kod
}

Zakładając ,że klasa Osoba będzie miała konstruktor parametrowy możemy przyjąć ,że każdy obiekt klasy Osoba będzie znała swoje imię i nazwisko. Pole te będą miały unikatowe wartości dla każdego obiektu.

Co o instancji zmiennych (polach) musisz wiedzieć na egzaminie.

  • Mogą one użyć 4 poziomu dostępu (3 modyfikatorów dostępu)
  • Mogą być oznaczone jako final.
  • Mogą być oznaczone jako transient.
  • Nie mogą być oznaczone jako abstract.
  • Nie mogą być oznaczone jako synchronized.
  • Nie mogą być oznaczone jako strictfp.
  • Nie mogą być oznaczone jako native.
  • Nie mogą być oznaczone jako staticponieważ stają się one zmiennymi klas.

Poniżej prosta ilustracja wykazująca, które modyfikatory są używane w metodach ,a które w zmiennych.

public class-07

Zmienne lokalne

Zmienne lokalne są to zmienne zadeklarowane wewnątrz metody. To oznacza ,że zmienna jest nie tylko inicjowania wewnątrz metody ,ale też deklarowana wewnątrz metody. Jej życie  rozpoczyna się w trakcie wykonywania metody ,a zostaje zniszczona wtedy, gdy metoda została zakończona. Lokalne zmienne są zawsze na stosie nie na stercie. Nie ma też czegoś takiego jak obiekt na stosie, czy lokalny obiekt w rzeczywistości jest lokalnie zadeklarowana  zmienna referencyjna.

Lokalne zmienne nie mogą używać różnych modyfikatorów (wyjątkiem jest final).  Nie ma zmiennej lokalnej, która  używałaby modyfikatorów jak np. public transient, volatile, czy static.  

Trzeba też wiedzieć ,że zanim zmienna lokalne zostanie użyta musi mieć przypisaną wartość ,ale o tym później.

public class FinalCountDown 
{
    public void countDown()
    {
        int count = 15;
    }
}

Zazwyczaj inicjuje się  zmienną w tej samej linijce co się ją  zadeklarowało. Można to zrobić później ,ale pamiętać trzeba ,że zanim użyjemy danej zmiennej musi być ona zainicjowana. Kompilator jest wrażliwy na takie  nieprzypisane wartości. W przeciwieństwie do zmiennych wewnątrz klas zmienne lokalne nie otrzymują gotowych domyślnych wartości. W klasach tak jest, ponieważ każda z nich posiada przynajmniej jeden konstruktor, który inicjuje wszystkie zmienne wewnątrz klasy.

image

Lokalna zmienna nie może być referowana poza metodą gdzie została stworzona. Jest to logiczne, ponieważ zmienna ta istnieje i żyje tylko w metodzie. Nie mamy prawa uzyskać do niej dostępu poza tym blokiem kodu.

public class FinalCountDown 
{
    public void countDown()
    {
        int count = 15;
        System.out.print(count);
    }

    public void resetTimer(int r)
    {
        count = r;
    }
}

Ten kod wywoła błąd.

image

Czy jest możliwe zadeklarowanie lokalnej zmiennej, której nazwa jest taka sama jak nazwa  już istniejącej instancji zmiennej?  Odpowiedź brzmi tak. Mówi się na to “shadowing”.

public class FinalCountDown 
{
    int count = 9;
    //deklaracja instancji zmiennej "count"  

    public void countDown()
    {
        int count = 15;

        //deklaracja zmiennej lokalnej "count"     
        System.out.print(count);
    }
}

Wygląda to ciekawie, ale po co  to robić.

Zastosowanie “shadowing” ma swój sens w metodach, w których celem jest przypisanie wartości z parametru do instancji zmiennej. .Obie zmienne mają takie same nazwy więc  proces przypisania jest dużo łatwiejszy.

Jak rozwiązać konflikt nazw skoro obie zmienne nazywają się tak samo? Kiedy wiadomo, o którą nam zmienną chodzi.

public class FinalCountDown 
{
    int count = 30;
    
    public void setCount(int count)
    {
        count = count;
        //co tutaj się dzieje? 
    }
    
}

Podobne nazwy mają ułatwić przypisanie ,ale jak powiedzieć kompilatorowi ,że chodzi mi o instancje zmiennej ,a nie o parametr w jednym momencie.
Istnieje słowo kluczowe“this”, które referuje się do obecnego obiektu stworzonego na podstawie tej klasy. Używając go już wiadomo kiedy jest użyte pole ,a kiedy  zmienna lokalna.

public class FinalCountDown 
{
    int count = 30;
    
    public void setCount(int count)
    {
        this.count = count;
        //this.count odnosi się do  
        //instancji tej klasy – obiektu  
        //w której jest ta zmienna  
        //Po prawej "count" jest parametrem metody     
    }
}

Deklarowanie tablic

W Javie tablice są obiektami, które potrafią przechowywać wiele zmiennych tego samego typu ,albo zmienne, które są podklasami tego samego typu. Tablice mogą przechowywać typy referencyjne i typy proste.

Tablica jednak przechowuje swoje wartości jako obiekt na stercie, nawet jeśli tablica przechowuje typy proste. Czyli nie ma czegoś takiego jak prosta tablica (primitive array).

Do egzaminu o tablicach musisz wiedzieć:

  • Jak stworzyć referencje zmiennej do tablicy, czyli zadeklarować tablicę.
  • Jak stworzyć obiekt tablicy.
  • Jak przypisać wartości do elementów tablic, czyli jak ją zainicjować.


Do deklaracji tablicy trzeba najpierw określić  typ przechowywanych elementów później trzeba dodać nawiasy kwadratowe.

int[] numbers; 

//nawiasy kwadratowe przed nazwą 
//rekomendowany styl deklaracji tablicy 
int number [];

// nawiasy kwadratowe po nazwie 
//mało czytelne ,ale poprawne 
//deklaracja tablicy z elementami referencyjnymi 
StringBuilder[] sBuilder;

StringBuilder sBuilder2[];


Można też zadeklarować tablice wielowymiarowe. Każdy następny nawias kwadratowy dodaje wymiar w w tablicy.

String[] [] [] threeTab;
String[] twoTab[];

Pierwsza zmienna jest tablicą trójwymiarową ,a druga jest tablicą dwuwymiarową. Jak widzisz kompilator nie miał problemu, gdy umieściłem kolejny nawias kwadratowy poza nazwą zmiennej ,ale nie należy tak robić.

Untitled5

Na egzaminie różne podchwytliwe pytania mogą się trafić. Trzeba pamiętać ,że wielkość tablicy jest ustalana dopiero w czasie inicjacji tablicy ,a nie jej deklaracji.

Co oznacza ,że poniższy kod jest błędny.

image

Ten kod się nie skompiluje maszyna wirtualna Java alokuje miejsce w czasie tworzenia instancji obiektu tablicy. W czasie deklaracji tablicy mamy do czynienia tylko ze zmienną, która będzie się referować do tego obiektu.

Zmienne Finale

Deklarując zmienne ze słowem final tworzysz zmienną, której wartość może być zadeklarowana tylko raz i nie może być później  zmieniona.

Z typami prostymi sprawa jest prosta przypisujemy do zmiennej final wartość 10 i ta wartość nie może być później zmieniona ,ale jak sprawa wygląda z typami referencyjnymi.

Zmienna referencyjna oznaczona jako final nie może referować się do innego obiektu. Informacje na temat obiektu mogą ulec zmianie ,ale sama referencja nie może być zmieniona. Modyfikacja stanu obiektu jest dozwolona ,ale zmiana referencji już nie.

Czyli nie ma finalnych obiektów, ale są finalne referencje.

Określiłem już jak modyfikator final  oddziałowuje na metody, klasach i zmiennych.

public class-08

Zmienne Transient

Jeśli oznaczysz zmienną jako “transient” mówisz maszynie wirtualnej Java ,aby zignorowała daną zmienną, kiedy wykonuje się serializacja  obiektu, który zawiera tą zmienną.

Serializacja to przydatny mechanizm w językach obiektowych pozwala  na zapisanie stanów obiektów np. do pliku.

Serializacja została dodana do egzaminu SCJP wraz z wersją 5 , co oznacza ,że będę musiał ją również omówić.

Zmienne Volatile

Modyfikator volatile mówi maszynie wirtualnej java ,że wątek, który chce uzyskać dostęp do tej zmiennej musi zawsze tworzyć własną kopię tej zmiennej wraz z kopią bazową w pamięci.

Brzmi skomplikowanie. Na szczęście do egzaminu musisz tylko wiedzieć ,że te słowo istnieje i odwołuje się tylko do zmiennych.

No cóż, myśl o kilku wątkach, które korzystają z tej samej zmiennej jest trochę straszne ,ale jest to istotne zagadnienie dla zaawansowanych programistów.

Słowo kluczowe synchronize ma jednak większy sens w zastosowaniu wątkowym niż volatile.

Statyczne zmienne i metody

Modyfikator static tworzy zmienne i metody, które istnieją niezależnie od instancji klasy. Wszystkie elementy statyczne istnieją przed utworzeniem instancji klasy i zawsze istnieje tylko jedna kopia statycznego elementu bez względu na ilość instancji klasy w programie.

Statyczne elementy wymagają swojego oddzielnego wpisu. Na razie powiem jakie elementy mogą być oznaczone jako statyczne.

  • Metody
  • Zmienne
  • Klasa zagnieżdżona w innej klasie
  • inicjowanie bloków 

Co nie może być oznaczone słowem kluczowym:  static

  • Konstruktory (w C# jest  konstruktor statyczny ,więc sens takiego zastosowania  byłby ,ale w 99% procentach przypadków konstruktor tworzy instancje obiektu więc ich brak w Javie jest nawet słuszny)
  • Klasy (chyba że jest to klasa zagnieżdżona)
  • Interfejsy
  • Metody lokalne wewnątrz klas
  • Lokalne zmienne

Co dalej:

Deklaracja typów wyliczeniowych.