Liigu peamise sisu juurde

Muutujad

Sissejuhatus

Muutuja on nimega varustatud koht arvuti mälus, kuhu programm saab oma käitamisaja jooksul andmeid salvestada. Javas kasutatakse muutujaid väärtuste hoidmiseks, lugemiseks ja muutmiseks programmi töö käigus.

Java on tüübikindel programmeerimiskeel, mis tähendab, et iga muutuja tüüp peab olema määratud ning sellest tuleb kogu aeg kinni pidada.

Igal muutujal peab olema nimi, tüüp ja väärtus.

Deklaratsioon ja initsialiseerimine

Muutuja kasutamiseks Javas tuleb see esmalt deklareerida ning enne kasutamist ka initsialiseerida:

  • Deklaratsioon määrab muutuja tüübi ja nime
  • Initsialiseerimine määrab muutujale algväärtuse

Kõige levinum viis muutuja loomiseks on muutuja ühel real deklareerimine ja initsialiseerimine. Javas käib muutujate loomine järgneva mustri järgi: TYPE VARIABLE_NAME = VALUE;
Näiteks:

int x = 1;
String name = "Ago";

Ehk esimese rea puhul on muutuja tüübiks int ehk täisarv, nimeks x ning väärtuseks 1.
Teise rea puhul on muutuja tüübiks String ehk sõne, nimeks name ning väärtuseks Ago.

Samuti on võimalik muutujat deklareerida ka ilma sellele väärtust andmata. Sellisel juhul kehtivad kindlad reeglid.

Lokaalsed muutujad

Lokaalsed muutujad ehk meetodisisesed muutujad ei saa vaikimisi väärtust.
Näiteks:

int x;
System.out.println(x); // Error

Kui proovida kasutada initsialiseerimata muutujat, tekib kompileerimisviga:

java: variable x might not have been initialized

Isendi- ja staatilised muutujad

Klassitasemel deklareeritud muutujad saavad endale vaikimisi väärtuse, isegi kui neid ei initsialiseerita käsitsi.
Näiteks:

public class Main {

int x; // default value is 0
boolean b; // default value is false
String s; // default value is null

public static void main(String[] args) {
Main a = new Main();
System.out.println(a.x); // prints 0
System.out.println(a.b); // prints false
System.out.println(a.s); // prints null
}

}

Tüübikindlus

Kuna Java on staatiliselt tüübitud (ehk tüübikindel) keel, siis igale muutujale määratakse kompileerimise ajal tüüp ning antud muutujale saab omistada ainult sellele tüübile sobivaid väärtusi. Mitteühilduvate tüüpide tõttu tekiks kompileerimisviga.
Näiteks:

int x = 1;
x = "Ago"; // Error

Antud näite põhjal tekiks järgmine kompileerimisviga:

java: incompatible types: java.lang.String cannot be converted to int

Tüübikindlus aitab vältida loogikavigu, parandada koodi loetavust ning tuvastada vigu enne programmi käivitamist.

Muutuja skoop

Samuti mängib Javas olulist rolli ka see, kus muutuja deklareeriti. Muutuja skoop määrab, millises programmi osas on muutuja nähtav ja kasutatav.
Skoope saab jaotada kolmeks: lokaalne-, isendi- ja staatiline muutuja.

Lokaalne muutuja

Lokaalne muutuja kehtib ainult meetodis või koodiplokis, kus see deklareeritud on.
Näiteks:

if (true) {
int x = 5;
System.out.println(x); // 5
}
System.out.println(x); // Error

Viimase x väljakutse kohal programm ei oska muutujat tuvastada ning tekib järgnev kompileerimisviga:

java: cannot find symbol
symbol: variable x
location: class Main

Isendimuutuja

Isendimuutujad on deklareeritud klassitasemel ning on seotud konkreetse objekti isendiga.
Näiteks:

class Student {
String name; // instance variable
}

public class Main {
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student();

s1.name = "Ago";
s2.name = "Taavi";

System.out.println(s1.name); // Ago
System.out.println(s2.name); // Taavi
}
}

Antud näite puhul, igal Student-objektil on määratud unikaalne nimi ehk hoiab erinevaid väärtusi. Ühes objektis tehtud muudatused ei mõjuta teisi objekte.

Staatiline muutuja

Staatiline muutuja kuulub klassile, mitte objektile. Seda deklareeritakse koos static märksõnaga.
Näiteks:

class Student {
static int studentCount = 0; // static variable

Student() {
studentCount++;
}
}

public class Main {
public static void main(String[] args) {
Student s1 = new Student();
Student s2 = new Student();

System.out.println(Student.studentCount); // 2
}
}

Antud näite puhul luuakse muutuja studentCount ühe korra, kõik Student-tüüpi objektid kasutavad ja muudavad sama muutujat. Muutujale pääsetakse ligi läbi klassi, mitte objekti.

Teisisõnu tekib globaalne muutuja, mis on jagatud kõikide seda tüüpi objektide vahel.

final-keyword ehk muutumatu muutuja

Kui on soov luua muutuja, mille väärtust peale initsialiseerimist muuta ei saa, siis on võimalik muutuja deklaratsioonile juurde lisada final-märksõna. final tähistab, et antud muutuja väärtust ei saa peale initsialiseerimist muuta.
Näiteks:

final int x = 100;
x = 200; // Error

Uue väärtuse omistamisel tekiks järgnev kompileerimisviga:

java: cannot assign a value to final variable x

final-märksõna kasutatakse tavaliselt konstantide loomiseks koos static-märksõnaga.

Nimereeglid

Java puhul järgitakse järgnevaid reegleid muutujate nimetamisel:

  • Nimi võib alata tähe, alakriipsu (_) või dollarimärgiga ($), kuid viimast kaht pole soovitatud kasutada.
  • Nimi ei tohi alata numbriga ning ei tohiks olla mõni Java märksõna

Samuti tuleks järgida järgnevaid tavasid:

  • Muutujate nimetamisel kasutatakse camel case stiili ehk nimi algab väikese tähega. Kui muutuja nimi koosneb mitmest sõnast siis need kirjutatakse kokku ning iga uus sõna algab suure tähega.
  • Muutuja nimi võiks olla lühike kuid tähendusrikas. Antud muutuja põhimõte peaks nimetusest välja tulema.
  • Ühetähelisi muutujaid võiks vältida, kui neid parasjagu ei kasutata tsüklites (ajutiste muutujate puhul on selline nimetus sobiv).
  • Staatilised final muutujad nimetatakse läbivalt suurte tähtedega ning iga sõna on alakriipsuga (_) eraldatud.

Näited:

// Correct examples - camelCase, meaningful names
int age;
double averageScore;
String studentName;
boolean isActive;

// Technically correct but should be avoided

int _count; // Commonly used for assigning class variables via arguments.
// We have `this` keyword for said use-case.
// this.count = count is better than _count = count

int $sum; // Reserved for compiler use.

// Bad naming examples
int a;
int x1;
double data;
String temp;

// static final constants
static final int MAX_SIZE = 100;
static final String DEFAULT_ROLE = "USER";

// These will throw an error
int 1number;
int class;
int public;

Ühetähelised muutujad on lubatud tsüklites, kuna need on ajutised:

for (int i = 0; i < 10; i++) {
// ...
}

var

Antud peatükis käime var märksõna lühidalt läbi, kuid selle kohta tuleb hiljem täpsem artikkel, kuna antud märksõnal on oma kindlad nüansid.
Alates Java versioon 10-st on võimalik kasutada ka var märksõna, mis võimaldab muutuja tüübi automaatset tuletamist kompilaatori poolt.
Näiteks:

var number = 10;    // Type - int
var text = "Java"; // Type - String

var puhul on oluline teada, et ta ei ole omaette tüüp, ta on lihtsalt märksõna, mis annab kompilaatorile mõista et muutuja tüüp tuleb tuletada kompileerimise ajal algväärtuse põhjal. Kompilaator määrab muutujale konkreetse ja muutumatu tüübi. Oluline on teada, et see ei muuda antud muutuja tüüpi dünaamiliseks ehk tüüp ei muutu programmi käivitamise ajal. Muutuja käitub tavapäraselt edasi, näiteks:

var x = 5;  // Type - int
x = 10; // OK
x = "test"; // Error

Seega var võimaldab koodi loetavamaks muuta, kuid ta ei muuda Javat dünaamiliselt tüübitud keeleks. var-i täpsemad reeglid on välja toodud eraldi peatükis.