Diferență între revizuiri ale paginii „Sintaxa limbajului Java; Structura lexicală a unui program”
(Nu s-au afișat 48 de versiuni intermediare efectuate de același utilizator) | |||
Linia 89: | Linia 89: | ||
|| [[Fișier:referinte.png|Exemplu de variabile tip referință]] | || [[Fișier:referinte.png|Exemplu de variabile tip referință]] | ||
|} | |} | ||
+ | |||
+ | ==== Șiruri de caractere în Java - clasa String ==== | ||
+ | |||
+ | În Java, șirurile de caractere sunt implementate de clasa [http://docs.oracle.com/javase/7/docs/api/java/lang/String.html String]: | ||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | String _nume; | ||
+ | _nume = "George"; | ||
+ | //urmatoarele doua constructii sunt echivalente: | ||
+ | String _prenume = "Vasile"; | ||
+ | String _prenume2 = new String("Vasile"); | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Singurul operator supraîncărcat permis în Java este operatorul + folosit pentru concatenarea șirurilor de caractere. Dacă operatorul + este folosit pentru a concatena un '''String''' cu o valoare primitiva sau de tip referință, atunci aceasta este convertită automat în șir de caractere folosind metoda '''String.valueOf()''' pentru primitive sau '''Object.toString()''' pentru variabile de tip referință. Aceasta din urmă poate fi suprascrisă de alte clase. | ||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | String _nume; | ||
+ | _nume = "George"; | ||
+ | String _prenume = "Vasile"; | ||
+ | String _numeIntreg = _nume + " " + _prenume; | ||
+ | String _title = "I am number " + 7; | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | <div class="regula"><font color="#ff0000">Regulă:</font> Compararea obiectelor de tip '''String''' se face utilizând metoda '''equals'''. Operatorul de egalitate '''==''' compară dacă referințele sunt la același obiect, nu dacă obiectele conțin aceleași date.</div> | ||
+ | |||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | String _prenume = "Vasile"; | ||
+ | String _prenume2 = new String("Vasile"); | ||
+ | |||
+ | if(_prenume2 == _prenume){ | ||
+ | System.out.println("Obiecte egale"); | ||
+ | }else{ | ||
+ | System.out.println("Obiecte diferite"); | ||
+ | } | ||
+ | |||
+ | if(_prenume2.equals(_prenume)){ | ||
+ | System.out.println("Stringuri egale"); | ||
+ | }else{ | ||
+ | System.out.println("stringuri diferite"); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Afișarea unui '''String''' pe ecran se face utilizând metoda "print" sau "prinln" ale câmpului ''out'' de tip '''PrintStream''' din clasa '''System''': | ||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | System.out.println("Hello world!"); | ||
+ | String _someString = "Trust " + "no. " + 1; | ||
+ | System.out.println(_someString); | ||
+ | </syntaxhighlight> | ||
==== Vectori multi-dimensionali ==== | ==== Vectori multi-dimensionali ==== | ||
Linia 115: | Linia 166: | ||
|| [[Fișier:vectori.png|Exemplu de variabile tip referință - vectori]] | || [[Fișier:vectori.png|Exemplu de variabile tip referință - vectori]] | ||
|} | |} | ||
+ | |||
+ | Toți vectorii conțin un câmp numit '''length''' care reține numărul de elemente ale vectorului: | ||
+ | <syntaxhighlight lang="java"> | ||
+ | int[] _array1 = new int[5]; | ||
+ | System.out.println(_array1.length); //se va afisa 5 | ||
+ | int[][] _array2 = new int[5][9]; | ||
+ | System.out.println(_array2.length); //se va afisa 5 | ||
+ | System.out.println(_array2[0].length); //se va afisa 9 | ||
+ | </syntaxhighlight> | ||
== Clasa Java == | == Clasa Java == | ||
Linia 185: | Linia 245: | ||
<div class="conventie"><font color="#0000ff">Convenție:</font> Numele de câmpuri încep cu literă mică.</div> | <div class="conventie"><font color="#0000ff">Convenție:</font> Numele de câmpuri încep cu literă mică.</div> | ||
+ | |||
+ | |||
+ | <div class="conventie"><font color="#0000ff">Convenție:</font> Pentru a deosebi ușor câmpurile de variabilele locale, numele acestora din urmă vor începe cu caracterul "_".</div> | ||
Linia 593: | Linia 656: | ||
{| class="wikitable" | {| class="wikitable" | ||
|- bgcolor="#ddeeff" align="center" | |- bgcolor="#ddeeff" align="center" | ||
− | !'''Modificator''' !! '''Clasa Curenta''' !! ''' | + | !'''Modificator''' !! '''Clasa Curenta''' !! '''Pachet''' !! '''Clasa Derivată''' !! '''În afara pachetului''' |
|- bgcolor="#ddffdd" align="center" | |- bgcolor="#ddffdd" align="center" | ||
− | | public || DA || DA || DA || DA | + | | public || <font color="green">DA</font> || <font color="green">DA</font> || <font color="green">DA</font> || <font color="green">DA</font> |
|- bgcolor="#ddffdd" align="center" | |- bgcolor="#ddffdd" align="center" | ||
− | | protected || DA || DA || DA || NU | + | | protected || <font color="green">DA</font> || <font color="green">DA</font> || <font color="green">DA</font> || <font color="red">NU</font> |
|- bgcolor="#ddffdd" align="center" | |- bgcolor="#ddffdd" align="center" | ||
− | | implicit (fără specificator) || DA || DA || NU || NU | + | | implicit (fără specificator) || <font color="green">DA</font> || <font color="green">DA</font> || <font color="red">NU</font> || <font color="red">NU</font> |
|- bgcolor="#ddffdd" align="center" | |- bgcolor="#ddffdd" align="center" | ||
− | | private || DA || NU || NU || NU | + | | private || <font color="green">DA</font> || <font color="red">NU</font> || <font color="red">NU</font> || <font color="red">NU</font> |
|} | |} | ||
Linia 792: | Linia 855: | ||
==== Modificatorul synchronized ==== | ==== Modificatorul synchronized ==== | ||
+ | |||
+ | O metodă sincronizată nu este accesibilă decât unui singur ''thread'' la un moment dat. Acest cuvânt cheie poate fi utilizat atât ca modificator pentru o metodă, cât și ca bloc de instrucțiuni în interiorul unei metode: | ||
+ | <syntaxhighlight lang="java"> | ||
+ | import java.util.ArrayList; | ||
+ | |||
+ | public class Queue extends ArrayList{ | ||
+ | |||
+ | public Queue(){ | ||
+ | super(); | ||
+ | } | ||
+ | |||
+ | public synchronized void push(Object _obj){ | ||
+ | add(_obj); | ||
+ | } | ||
+ | |||
+ | public Object pop(){ | ||
+ | if(size() != 0){ | ||
+ | synchronized(this){ | ||
+ | return remove(0); | ||
+ | } | ||
+ | }else{ | ||
+ | throw new RuntimeException("Queue empty!"); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Mai multe despre ''thread''-uri în capitolul [[Programare concurentă - fire de execuție (Threads)]]. | ||
==== Modificatorul native ==== | ==== Modificatorul native ==== | ||
+ | |||
+ | Există situații în care anumite funcții de sistem nu pot fi apelate în Java, sau alte cazuri în care din Java trebuie apelate funcții dintr-o bibliotecă (.dll sau .so, etc.). În acest caz, din aplicația Java trebuie apelate funcții compilate în limbajul nativ al mașinii, și nu în limbajul mașinii virtuale. Aceste funcții se numesc native, iar mecanismul prin care se pot apela ele din Java se numește [http://docs.oracle.com/javase/7/docs/technotes/guides/jni/index.html JNI] (Java Native Interface). | ||
+ | |||
+ | Mai multe despre cum se implementează metodele native pe [http://java.sun.com/developer/onlineTraining/Programming/JDCBook/jni.html site-ul Oracle]. | ||
+ | |||
+ | <div class="sfat"><font color="darkgreen">Sfat:</font> Evitați pe cât posibil utilizarea metodelor native deoarece acestea nu sunt portabile.</div> | ||
+ | |||
+ | === Constante de clasă === | ||
+ | |||
+ | Un câmp declarat în același timp ''static'' și ''final'' se numește constantă a clasei. | ||
+ | |||
+ | === Extinderea claselor === | ||
+ | |||
+ | Limbajul Java suportă moștenirea simplă (vezi [[Noțiuni avansate de programare obiect-orientată#Ierarhii de clase|ierarhii de clase]] și [[Noțiuni avansate de programare obiect-orientată#polimorfism|polimorfism]]). Cuvântul cheie care permite extinderea unei clase este '''extends'''. | ||
+ | |||
+ | <div class="regula"><font color="#ff0000">Regulă:</font> O clasă Java extinde exact o singură altă clasă (dacă nu este specificată, aceasta este clasa ''Object'').</div> | ||
+ | |||
+ | Exemplu: | ||
+ | <syntaxhighlight lang="java"> | ||
+ | //--------------------------------------------------- | ||
+ | //file Vehicle.java | ||
+ | public class Vehicle{ //class Vehicle extends Object | ||
+ | |||
+ | protected int cylinders; | ||
+ | protected float maxSpeed; | ||
+ | protected static float maxAcceptedVehicleMass; | ||
+ | protected float vehicleMass; | ||
+ | |||
+ | public void startEngine(){ | ||
+ | //... | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | //--------------------------------------------------- | ||
+ | //file Truck.java | ||
+ | public class Truck extends Vehicle{ //class Truck extends Vehicle | ||
+ | |||
+ | protected float maxCargoWeight; | ||
+ | protected float currentCargoWeight; | ||
+ | |||
+ | public void loadCargo(float _cargo){ | ||
+ | // protected fields maxAcceptedVehicleMass and vehicleMass | ||
+ | // are inherited from Vehicle class | ||
+ | if(currentCargoWeight + _cargo <= maxCargoWeight && | ||
+ | vehicleMass + currentCargoWeight + _cargo <= maxAcceptedVehicleMass){ | ||
+ | currentCargoWeight += _cargo; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === Șabloane (generics) === | ||
+ | |||
+ | Există situații în care o anumită instanță a unei clase lucrează exclusiv cu un anumit tip de date. În acest caz, dacă clasa este definită ca folosind, de exemplu, date de tip '''Object''', atunci trebuie făcuți pași suplimentari, consumatori de timp, pentru a face up-cast de la '''Object''' la tipul de date (clasa) cu care se lucrează. În plus, aceste operații de up-cast sunt verificate doar la runtime, crescând șansa să apară erori de programare ne-detectabile la compilare. Ca exemplu, vom descrie o clasă '''Stack''' care stochează referințe de tip '''Object''': | ||
+ | <syntaxhighlight lang="java"> | ||
+ | public class Stack{ | ||
+ | |||
+ | private Object[] stackArray; | ||
+ | private int stackTop; | ||
+ | |||
+ | public Stack(int _size){ | ||
+ | stackArray = new Object[_size]; | ||
+ | stackTop = 0; | ||
+ | } | ||
+ | |||
+ | public Object pop() throws Exception{ | ||
+ | if(stackTop > 0){ | ||
+ | return stackArray[--stackTop]; | ||
+ | } | ||
+ | |||
+ | throw new Exception("Stack empty"); | ||
+ | } | ||
+ | |||
+ | public void push(Object _obj) throws Exception{ | ||
+ | if(stackTop < stack.length){ | ||
+ | stackArray[stackTop++] = _obj; | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | throw new Exception("Stack full"); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | Și o clasă care folosește o stivă exclusiv pentru obiecte de tip '''String''': | ||
+ | <syntaxhighlight lang="java"> | ||
+ | public class StringStacker{ | ||
+ | |||
+ | public static void main(String[] _args){ | ||
+ | Stack _stack = new Stack(10); | ||
+ | try{ | ||
+ | // String is automatically down-cast to Object | ||
+ | // we could just as well push any kind of reference | ||
+ | // on this stack, by mistake, and reading and trying | ||
+ | // to up-cast it as String will give a runtime ClassCastException | ||
+ | _stack.push("Hello world!"); | ||
+ | _stack.push("Byebye world"); | ||
+ | |||
+ | // Object must be manually up-casted to String | ||
+ | // every time, even if it's obvious that all | ||
+ | // objects on the stack are Strings | ||
+ | String _secondString = (String)_stack.pop(); | ||
+ | String _firstString = (String)_stack.pop(); | ||
+ | |||
+ | System.out.println(_secondString + ", " + _firstString); | ||
+ | }catch(Exception _e){ | ||
+ | System.out.println("Stack error: " + _e.getMessage()); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Această problemă se poate rezolva folosind șabloane. Vom rescrie clasa '''Stack''': | ||
+ | <syntaxhighlight lang="java"> | ||
+ | public class Stack <GenericType>{ | ||
+ | |||
+ | private GenericType[] stackArray; | ||
+ | private int stackTop; | ||
+ | |||
+ | public Stack(int _size){ | ||
+ | stackArray = new GenericType[_size]; | ||
+ | stackTop = 0; | ||
+ | } | ||
+ | |||
+ | public GenericType pop() throws Exception{ | ||
+ | if(stackTop > 0){ | ||
+ | return stackArray[--stackTop]; | ||
+ | } | ||
+ | |||
+ | throw new Exception("Stack empty"); | ||
+ | } | ||
+ | |||
+ | public void push(GenericType _obj) throws Exception{ | ||
+ | if(stackTop < stack.length){ | ||
+ | stackArray[stackTop++] = _obj; | ||
+ | return; | ||
+ | } | ||
+ | |||
+ | throw new Exception("Stack full"); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Și clasa '''StringStacker''': | ||
+ | <syntaxhighlight lang="java"> | ||
+ | public class StringStacker{ | ||
+ | |||
+ | public static void main(String[] _args){ | ||
+ | // at this point, the _stack object is an instance | ||
+ | // of the class Stack, where GenericType has been | ||
+ | // replaced by String | ||
+ | Stack<String> _stack = new Stack<String>(10); | ||
+ | try{ | ||
+ | // now the push method only takes Strings as | ||
+ | // an argument; trying to push an Object will | ||
+ | // fail with a compile time error | ||
+ | _stack.push("Hello world!"); | ||
+ | _stack.push("Byebye world"); | ||
+ | |||
+ | // pop() will now return a String so casting | ||
+ | // is no longer necessary | ||
+ | String _secondString = _stack.pop(); | ||
+ | String _firstString = _stack.pop(); | ||
+ | |||
+ | System.out.println(_secondString + ", " + _firstString); | ||
+ | }catch(Exception _e){ | ||
+ | System.out.println("Stack error: " + _e.getMessage()); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Mai multe despre șabloane în [http://docs.oracle.com/javase/tutorial/java/generics/ tutorial-ul Oracle]. | ||
== Interfața Java == | == Interfața Java == | ||
+ | |||
+ | Interfața Java este o structură echivalentă cu o clasă abstractă în care toate metodele sunt abstracte. Spre deosebire de sistemul de moștenire (extindere), unde o clasă poate moșteni o singură altă clasă (moștenire simplă), o clasă poate implementa oricâte interfețe. | ||
+ | |||
+ | <div class="sfat"><font color="darkgreen">Sfat:</font> Evitați declararea câmpurilor în interfețe. Pot apărea conflicte când există mai multe interfețe care conțin fiecare un câmp cu același nume.</div> | ||
+ | |||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | //--------------------------------------------------- | ||
+ | //file Closeable.java | ||
+ | public interface Closeable{ | ||
+ | public void close(); | ||
+ | } | ||
+ | |||
+ | //--------------------------------------------------- | ||
+ | //file Openable.java | ||
+ | public interface Openable{ | ||
+ | public void open(); | ||
+ | } | ||
+ | |||
+ | //--------------------------------------------------- | ||
+ | //file Stream.java | ||
+ | public class Stream implements Openable, Closeable{ | ||
+ | |||
+ | public void close(){ | ||
+ | //.. something here | ||
+ | } | ||
+ | public void open(){ | ||
+ | //... something here | ||
+ | } | ||
+ | |||
+ | } | ||
+ | //--------------------------------------------------- | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | <div class="regula"><font color="#ff0000">Regulă:</font> Dacă o clasă implementează o interfață, atunci obligatoriu ea trebuie să implementeze toate metodele declarate în interfață, sau clasa să fie abstractă și metodele respective să fie declarate abstracte.</div> | ||
+ | |||
+ | Mai multe despre interfețe în capitolele [[Noțiuni avansate de programare obiect-orientată#Ierarhii de clase|ierarhii de clase]] și [[Noțiuni avansate de programare obiect-orientată#polimorfism|polimorfism]]. | ||
== Construcții repetitive == | == Construcții repetitive == | ||
=== Expresia for === | === Expresia for === | ||
+ | |||
+ | Expresia '''for''' are două forme posibile. Prima este identică cu cea din C: | ||
+ | <syntaxhighlight lang="java"> | ||
+ | for(expresie_initializare; condiție_continuare; expresie_bucla){ | ||
+ | //... | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | * ''expresie_inițializare'' - reprezintă o expresie care se execută o singură dată la intrarea în buclă; | ||
+ | * ''condiție_continuare'' - reprezintă o condiție care se evaluează la începutul fiecărei iterații; ciclul se continuă dacă condiția e adevărată sau dacă ea lipsește; | ||
+ | * ''expresie buclă'' - reprezintă o expresie care se execută necondiționat la sfărșitul fiecărei iterații. | ||
+ | |||
+ | Exemplu pentru un array: | ||
+ | <syntaxhighlight lang="java"> | ||
+ | int[] someArray = getArray(); | ||
+ | |||
+ | for(int i=0; i<someArray.length; i++){ | ||
+ | System.out.println(someArray[i]); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Exemplu pentru o listă: | ||
+ | <syntaxhighlight lang="java"> | ||
+ | Node firstNode = getList(); | ||
+ | |||
+ | for(Node _eachNode = firstNode; _eachNode != null; _eachNode = _eachNode.getNextNode()){ | ||
+ | System.out.println(_eachNode); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Exemplu pentru o buclă infinită: | ||
+ | <syntaxhighlight lang="java"> | ||
+ | for(;;){ | ||
+ | System.out.println("Freedom!"); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Al doilea tip de expresie '''for''' este utilizat pentru vectori în felul următor (identic ca funcționare cu primul exemplu): | ||
+ | <syntaxhighlight lang="java"> | ||
+ | int[] someArray = getArray(); | ||
+ | |||
+ | for (int element : someArray) { | ||
+ | System.out.println(element); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
=== Expresia while === | === Expresia while === | ||
+ | |||
+ | Expresia '''while''' este identică cu cea din C: | ||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | while(conditie_continuare){ | ||
+ | //... something | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | * ''conditie_continuare'' - este o condiție care se evaluează la începutul fiecarei iterații și bucla se încheie dacă aceasta este falsă. | ||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | int a = 20; | ||
+ | int b = 3; | ||
+ | while(a != b){ | ||
+ | a++; | ||
+ | b--; | ||
+ | System.out.println(a * b); | ||
+ | } | ||
+ | </syntaxhighlight> | ||
=== Expresia do - while === | === Expresia do - while === | ||
+ | |||
+ | Expresia '''do - while''' este identică cu cea din C: | ||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | do{ | ||
+ | //... something | ||
+ | }while(conditie_continuare); | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | * ''conditie_continuare'' - este o condiție care se evaluează la sfârșitul fiecarei iterații și bucla se încheie dacă aceasta este falsă. | ||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | int a = 20; | ||
+ | int b = 3; | ||
+ | do{ | ||
+ | a++; | ||
+ | b--; | ||
+ | System.out.println(a * b); | ||
+ | }while(a != b); | ||
+ | </syntaxhighlight> | ||
=== Instrucțiunile break & continue === | === Instrucțiunile break & continue === | ||
+ | |||
+ | Instrucțiunile '''break''' și '''continue''' sunt folosite identic cu cele din C și anume pentru a întrerupe un ciclu repetitiv ('''break''') sau a continua cu următoarea iterație ('''continue'''). | ||
+ | |||
+ | Spre exemplu, pentru a căuta primul număr par mai mare ca 100 într-un vector: | ||
+ | <syntaxhighlight lang="java"> | ||
+ | int search(int[] someArray){ | ||
+ | int result = 0; | ||
+ | |||
+ | for(int element: someArray){ | ||
+ | if(element % 2 != 0){ | ||
+ | continue; | ||
+ | } | ||
+ | if(element > 100){ | ||
+ | result = element; | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | return result; | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | <div class="regula"><font color="#ff0000">Regulă:</font> '''Break''' și '''continue''' acționează asupra celui mai apropiat (inner) '''for''', '''while''' sau '''do-while''' din metoda curentă.</div> | ||
== Construcții condiționale == | == Construcții condiționale == | ||
=== Operatorul condițional (?) === | === Operatorul condițional (?) === | ||
+ | |||
+ | Operator condițional este identic cu cel din C: | ||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | (expresie_de_evaluat ? expresie_adevarat : expresie_fals) | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | * ''expresie_de_evaluat'' - reprezintă o expresie booleană (adevărat sau fals) de care depinde valoarea finală a expresiei condiționale; | ||
+ | * ''expresie_adevarat'' - dacă ''expresie_de_evaluat'' este adevărată, atunci expresia condițională va lua valoarea ''expresie_adevarat''; | ||
+ | * ''expresie_fals'' - dacă ''expresie_de_evaluat'' este falsă, atunci expresia condițională va lua valoarea ''expresie_fals''; | ||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | public class Utils{ | ||
+ | |||
+ | //private constructor means the class can't be instantiated | ||
+ | private Utils(){ | ||
+ | //nothing here | ||
+ | } | ||
+ | |||
+ | public static float max(float a, float b){ | ||
+ | // if a is greater than b, the expression is | ||
+ | // evaluated to a and the value of a is returned | ||
+ | // else the expression is evaluated to b and the | ||
+ | // value of b is returned | ||
+ | return a > b ? a : b; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
=== Expresia if - else === | === Expresia if - else === | ||
+ | |||
+ | Expresia '''if-else''' este expresia condițională standard și este și ea identică cu cea din C: | ||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | if(conditie){ | ||
+ | //instructiuni | ||
+ | }else{ | ||
+ | //instructiuni | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | * ''conditie'' - este o expresie booleană care se evaluează și în funcție de care se execută primul bloc de instrucțiuni (dacă expresia este adevărată) sau al doilea bloc de instrucțiuni (cel de după '''else''', dacă expresia este falsă). | ||
+ | |||
+ | Exemple de blocuri '''if''': | ||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | public class Utils{ | ||
+ | |||
+ | private Utils(){ | ||
+ | // nothing here | ||
+ | } | ||
+ | |||
+ | public static float clamp(float _value, float _lowestValue, float _highestValue){ | ||
+ | float _result = 0; | ||
+ | if(_value < _lowestValue){ | ||
+ | _result = _lowestValue; | ||
+ | }else if(_value > _highestValue){ | ||
+ | _result = _highestValue; | ||
+ | }else{ | ||
+ | _result = _value; | ||
+ | } | ||
+ | |||
+ | return _result; | ||
+ | } | ||
+ | |||
+ | public static float max(float a, float b){ | ||
+ | float _result = 0; | ||
+ | if(a > b){ | ||
+ | result = a; | ||
+ | }else{ | ||
+ | result = b; | ||
+ | } | ||
+ | return result; | ||
+ | } | ||
+ | |||
+ | public static float abs(float a){ | ||
+ | if(a < 0){ | ||
+ | a = -a; | ||
+ | } | ||
+ | |||
+ | return a; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </syntaxhighlight> | ||
=== Expresia switch === | === Expresia switch === | ||
+ | |||
+ | Expresia '''switch''' este identică cu cea din C. Se folosește atunci când în funcție de valoarea unei expresii trebuie executate diferite instrucțiuni: | ||
+ | <syntaxhighlight lang="java"> | ||
+ | switch(expresie){ | ||
+ | case Valoare_1: | ||
+ | // bloc_instructiuni_1 | ||
+ | break; | ||
+ | case Valoare_2: | ||
+ | // bloc_instructiuni_2 | ||
+ | break; | ||
+ | case Valoare_3: | ||
+ | // bloc_instructiuni_3 | ||
+ | break; | ||
+ | default: | ||
+ | // bloc_instructiuni_default | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | * ''expresie'' - reprezintă expresia în funcție de valoarea căreia se sare la blocul de instrucțiuni corespunzător; | ||
+ | * ''Valoare_i'', ''bloc_instructiuni_i'' - dacă expresia ''expresie'' are valoarea ''Valoare_i'', atunci se sare la ''bloc_instrucțiuni_i''; ''Valoare_i'' trebuie să fie constantă. | ||
+ | * '''default''' - este un cuvânt cheie care determină blocul la care se sare (''bloc_instructiuni_default'') în cazul în care valoarea expresiei nu corespunde nici unei valori specificate in blocul '''switch'''. | ||
+ | |||
+ | <div class="regula"><font color="#ff0000">Atenție:</font> Odată saltul făcut la unul din blocurile de instrucțiuni, acestea se vor executa în continuare până la întalnirea cuvântului cheie '''break''' (care face ca execuția programului să se reia de la prima instrucțiune după blocul '''switch''') sau a cuvântului cheie '''return''' care încheie execuția metodei. Dacă se omite instrucțiunea '''break''' atunci programul se va executa în continuare, bloc după bloc, începând cu cel la care s-a sărit. </div> | ||
+ | |||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | public String intToString(int _value){ | ||
+ | String _result = ""; | ||
+ | switch(_value){ | ||
+ | case 0: _result = "zero"; break; | ||
+ | case 1: _result = "one"; break; | ||
+ | case 2: _result = "two"; break; | ||
+ | case 3: _result = "three"; break; | ||
+ | case 4: _result = "four"; break; | ||
+ | case 5: _result = "five"; break; | ||
+ | case 6: _result = "six"; break; | ||
+ | case 7: _result = "seven"; break; | ||
+ | case 8: _result = "eight"; break; | ||
+ | case 9: _result = "nine"; break; | ||
+ | default: _result = "more than nine"; break; | ||
+ | } | ||
+ | |||
+ | return _result; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == Cuvinte cheie pentru tratarea excepțiilor == | ||
+ | |||
+ | O excepție se aruncă folosind cuvântul cheie '''throw'''. O metodă care nu administrează o excepție trebuie să o declare în prototip folosind cuvântul cheie '''throws'''. Un bloc de administrare a excepțiilor este de tip '''try-catch-finally''' sau, din Java 7, '''try-with-resources''': | ||
+ | |||
+ | <syntaxhighlight lang="java"> | ||
+ | public class TestClass{ | ||
+ | |||
+ | private int value; | ||
+ | |||
+ | public static void main(String[] _args){ | ||
+ | try{ | ||
+ | TestClass _obj = new TestClass(10); | ||
+ | _obj.someMethod(); | ||
+ | }catch(Exception _e){ | ||
+ | System.out.println("Exception caught: " + _e.getMessage()); | ||
+ | } | ||
+ | |||
+ | try{ | ||
+ | TestClass _obj = new TestClass(-10); | ||
+ | _obj.someMethod(); | ||
+ | }catch(Exception _e){ | ||
+ | System.out.println("Exception caught: " + _e.getMessage()); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | public TestClass(int _value) throws Exception{ | ||
+ | if(_value < 0){ | ||
+ | throw new Exception("The value must not be negative: " + _value); | ||
+ | } | ||
+ | value = _value; | ||
+ | } | ||
+ | |||
+ | public void someMethod(){ | ||
+ | System.out.println("Running method for value " + value); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | Mai multe despre excepții în capitolul [[tratarea excepțiilor]]. | ||
== Operatori == | == Operatori == | ||
+ | |||
+ | Aceasta este lista de operatori permiși în limbajul Java. Spre deosebire de C++, în Java nu este permisă supraîncarcarea operatorilor. | ||
+ | |||
+ | {| class="wikitable" | ||
+ | |- | ||
+ | ! style="text-align: center" | Precedență | ||
+ | ! style="text-align: center" | Operator | ||
+ | ! style="text-align: center" | Descriere | ||
+ | ! style="text-align: center" | Asociativitate | ||
+ | |- | ||
+ | ! rowspan=3| 1 | ||
+ | | style="border-bottom-style: none; border-top-style: none" | <code>()</code> | ||
+ | | style="border-bottom-style: none; border-top-style: none" | Apel de metodă | ||
+ | | style="vertical-align: center" rowspan="4" | De la stânga la dreapta | ||
+ | |- | ||
+ | | style="border-bottom-style: none; border-top-style: none" | <code>[]</code> | ||
+ | | style="border-bottom-style: none; border-top-style: none" | Acces la elemente din vector | ||
+ | |- | ||
+ | | style="border-bottom-style: none; border-top-style: none" | <code>.</code> | ||
+ | | style="border-bottom-style: none; border-top-style: none" | Acces la membrul unei clase | ||
+ | |- | ||
+ | ! 2 | ||
+ | | style="border-bottom-style: none" | <code>++</code> <code>--</code> | ||
+ | | style="border-bottom-style: none" | Incrementare și decrementare ca sufix | ||
+ | |- | ||
+ | ! rowspan=5| 3 | ||
+ | | style="border-bottom-style: none" | <code>++</code> <code>--</code> | ||
+ | | style="border-bottom-style: none" | Incrementare și decrementare ca prefix | ||
+ | | style="vertical-align: center" rowspan="5" | De la dreapta la stânga | ||
+ | |- | ||
+ | | style="border-bottom-style: none; border-top-style: none" | <code>+</code> <code>-</code> | ||
+ | | style="border-bottom-style: none; border-top-style: none" | Plus și minus unar | ||
+ | |- | ||
+ | | style="border-bottom-style: none; border-top-style: none" | <code>!</code> <code>~</code> | ||
+ | | style="border-bottom-style: none; border-top-style: none" | NU logic și NU pe biți | ||
+ | |- | ||
+ | | style="border-bottom-style: none; border-top-style: none" | <code>(''type'') val</code> | ||
+ | | style="border-bottom-style: none; border-top-style: none" | Type cast | ||
+ | |- | ||
+ | | style="border-top-style: none" | <code>new</code> | ||
+ | | style="border-top-style: none" | Instanțiere de obiecte sau de vectori | ||
+ | |- | ||
+ | ! 4 | ||
+ | | <code>*</code> <code>/</code> <code>%</code> | ||
+ | | Înmuțire, împărțire și modulo (rest) | ||
+ | | style="vertical-align: center" rowspan="13" | De la stânga la dreapta | ||
+ | |- | ||
+ | ! rowspan=2| 5 | ||
+ | | style="border-bottom-style: none;" | <code>+</code> <code>-</code> | ||
+ | | style="border-bottom-style: none;" | Adunare și scădere | ||
+ | |- | ||
+ | | style="border-top-style: none" | <code>+</code> | ||
+ | | style="border-top-style: none" | Concatenare de stringuri | ||
+ | |- | ||
+ | ! 6 | ||
+ | | <code><<</code> <code>>></code> <code>>>></code> | ||
+ | | Shift pe biți la stânga, shift pe biți la dreapta cu semn și fără semn | ||
+ | |- | ||
+ | ! rowspan=3| 7 | ||
+ | | style="border-bottom-style: none;" | <code><</code> <code><=</code> | ||
+ | | style="border-bottom-style: none;" | Operator de comparare "mai mic decât" și "mai mic sau egal" | ||
+ | |- | ||
+ | | style="border-bottom-style: none; border-top-style: none" | <code>></code> <code>>=</code> | ||
+ | | style="border-bottom-style: none; border-top-style: none" | Operator de comparare "mai mare ca" și "mai mare sau egal" | ||
+ | |- | ||
+ | | style="border-top-style: none" | <code>instanceof</code> | ||
+ | | style="border-top-style: none" | Comparare de tip | ||
+ | |- | ||
+ | ! 8 | ||
+ | | <code>==</code> <code>!=</code> | ||
+ | | Operator de comparare "egal cu" sau "diferit de" | ||
+ | |- | ||
+ | ! 9 | ||
+ | | <code>&</code> | ||
+ | | AND (și) pe biți | ||
+ | |- | ||
+ | ! 10 | ||
+ | | <code>^</code> | ||
+ | | XOR (sau exclusiv) pe biți | ||
+ | |- | ||
+ | ! 11 | ||
+ | | <code><nowiki>|</nowiki></code> | ||
+ | | OR (sau) pe biți | ||
+ | |- | ||
+ | ! 12 | ||
+ | | <code>&&</code> | ||
+ | | AND (și) logic | ||
+ | |- | ||
+ | ! 13 | ||
+ | | <code><nowiki>||</nowiki></code> | ||
+ | | OR (sau) logic | ||
+ | |- | ||
+ | ! 14 | ||
+ | | <code>''c'' ? ''t'' : ''f''</code> | ||
+ | | Operator ternar condițional (vezi [[#Operatorul condițional (?)]]) | ||
+ | | style="vertical-align: center" rowspan="6" | De la dreapta la stânga | ||
+ | |- | ||
+ | ! rowspan=5| 15 | ||
+ | | style="border-bottom-style: none" | <code>=</code> | ||
+ | | style="border-bottom-style: none" | Asignare simplă | ||
+ | |- | ||
+ | | style="border-bottom-style: none; border-top-style: none" | <code>+=</code> <code>-=</code> | ||
+ | | style="border-bottom-style: none; border-top-style: none" | Asignare cu sumă sau diferență | ||
+ | |- | ||
+ | | style="border-bottom-style: none; border-top-style: none" | <code>*=</code> <code>/=</code> <code>%=</code> | ||
+ | | style="border-bottom-style: none; border-top-style: none" | Asignare cu produs, cât sau rest | ||
+ | |- | ||
+ | | style="border-bottom-style: none; border-top-style: none" | <code><<=</code> <code>>>=</code> <code>>>>=</code> | ||
+ | | style="border-bottom-style: none; border-top-style: none" | Asignare cu shift la stânga, la dreapta, sau la dreapta fără semn | ||
+ | |- | ||
+ | | style="border-top-style: none" | <code>&=</code> <code>^=</code> <code><nowiki>|</nowiki>=</code> | ||
+ | | style="border-top-style: none" | Asignare cu AND, XOR, sau OR pe biți | ||
+ | |} | ||
+ | |||
+ | == Resurse == | ||
+ | |||
+ | # [http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf Specificația limbajului Java, v.7] | ||
+ | # [http://docs.oracle.com/javase/specs/jvms/se7/jvms7.pdf Specificația mașinii virtuale Java, v.7] | ||
+ | # [http://en.wikipedia.org/wiki/Java_syntax Sintaxa Java - Wikipedia] |
Versiunea curentă din 25 octombrie 2012 08:39
O aplicație Java este formată din două tipuri de elemente: clase și interfețe.
Înainte să prezentăm structura lexicală a claselor și interfețelor, trebuie să discutăm despre tipurile de date.
Tipuri de date
În Java, există două categorii de tipuri de date: primitive și referințe. Tipurile primitive se referă la cele care au valori imediate (valori numerice sau logice), iar referințele sunt nume care identifică obiecte.
Tipuri primitive
În Java, tipurile primitive sunt:
Nume | Categorie | Număr de biți | Valori posibile |
---|---|---|---|
byte | întreg | 8 | -128 : 127 |
short | întreg | 16 | -32768 : 32767 |
int | întreg | 32 | -2147483648 : 2147483647 |
long | întreg | 64 | -9223372036854775808 : 9223372036854775807 |
char | caracter | 16 | Orice caracter Unicode |
boolean | logic | 8 | true, false |
float | virgulă mobilă | 32 | ±1.18 x 10-38 : ±3.4 x 1038 |
double | virgulă mobilă | 64 | ±2.23 x 10-308 : ±1.80 x 10308 |
Variabilele de tip primitiv se declară în același fel ca cele din C. Ca exemplu:
int someInteger;
int someOtherInteger = 10;
float someFloat = 10.5f;
double someDouble = 5.3 + someFloat;
boolean condition = true;
char oneChar = 'g';
char newLineChar = '\n';
Atenție: În Java nu există tipuri de date fără semn.
Similar cu C, există și în Java operatori de cast pentru tipuri de date primitive. Unele operații de conversie sunt implicite (de la întreg la virgulă mobilă), dar unele trebuie specificate (de la virgulă mobilă la întreg, de la char la întreg), iar altele nu sunt posibile deloc (de la boolean la orice alt tip sau invers).
În Java, tipurile primitive numerice se inițializează implicit cu valoarea 0, iar cele logice cu valoarea false.
Tipuri referință
Variabilele de tip referință sunt identificatori ale unor obiecte. Două referințe pot identifica același obiect, dar o referință nu poate identifica două obiecte în același timp.
Referințele se inițializează implicit cu valoarea null.
Referință la obiecte
Obiectele de orice tip (clasă), se creează folosind operatorul new conform următorului exemplu:
1Object obj;
2new Object();
3obj = new Object();
Se observă linia 2, care instanțiază un obiect nou, de tipul clasei Object, dar nu există nici o referință la acest obiect nou creat. Astfel, imediat după instanțiere, memoria alocată este eliberată de către garbage collector, aceasta ne mai putând fi accesibilă. Linia 3 instanțiază un obiect nou, și variabila obj va fi referință la obiectul nou creat. Mai multe despre instanțierea obiectelor și constructori în capitolele care urmează.
Șiruri de caractere în Java - clasa String
În Java, șirurile de caractere sunt implementate de clasa String:
String _nume;
_nume = "George";
//urmatoarele doua constructii sunt echivalente:
String _prenume = "Vasile";
String _prenume2 = new String("Vasile");
Singurul operator supraîncărcat permis în Java este operatorul + folosit pentru concatenarea șirurilor de caractere. Dacă operatorul + este folosit pentru a concatena un String cu o valoare primitiva sau de tip referință, atunci aceasta este convertită automat în șir de caractere folosind metoda String.valueOf() pentru primitive sau Object.toString() pentru variabile de tip referință. Aceasta din urmă poate fi suprascrisă de alte clase.
String _nume;
_nume = "George";
String _prenume = "Vasile";
String _numeIntreg = _nume + " " + _prenume;
String _title = "I am number " + 7;
String _prenume = "Vasile";
String _prenume2 = new String("Vasile");
if(_prenume2 == _prenume){
System.out.println("Obiecte egale");
}else{
System.out.println("Obiecte diferite");
}
if(_prenume2.equals(_prenume)){
System.out.println("Stringuri egale");
}else{
System.out.println("stringuri diferite");
}
Afișarea unui String pe ecran se face utilizând metoda "print" sau "prinln" ale câmpului out de tip PrintStream din clasa System:
System.out.println("Hello world!");
String _someString = "Trust " + "no. " + 1;
System.out.println(_someString);
Vectori multi-dimensionali
Și vectorii, în Java, se tratează ca niște obiecte, adică există variabile de tip referință care identifică zona de memorie alocată pentru vector.
Atenție: În cazul instanțierii vectorilor de referințe (unde fiecare locație este o referință, și nu un tip primitiv de date), operatorul new alocă memorie doar pentru vector, nu și pentru fiecare locație în parte.
Atenție: Ca și în C, numărătoarea elementelor dintr-un vector începe de la 0. Astfel, pentru un vector de 5 elemente, există pozițiile 0, 1, 2, 3 și 4.
Toți vectorii conțin un câmp numit length care reține numărul de elemente ale vectorului:
int[] _array1 = new int[5];
System.out.println(_array1.length); //se va afisa 5
int[][] _array2 = new int[5][9];
System.out.println(_array2.length); //se va afisa 5
System.out.println(_array2[0].length); //se va afisa 9
Clasa Java
Clasa este tipul de bază în Java, ca și în orice alt limbaj bazat pe obiecte.
Cuvântul cheie care definește o clasă este class, acesta fiind urmat pe numele clasei și de implementarea acesteia între acolade.
class SomeClass{
// here comes the implementation of the class
}
Implementarea unei clase este formată din definiții de câmpuri și definiții și implementări de metode. Câmpurile reprezintă datele conținute de clasă și metodele reprezintă funcționalitatea clasei, adică funcțiile care acționează asupra câmpurilor.
Pachetele Java
Clasele unei aplicații Java sunt structurate într-o ierarhie similară cu cea a fișierelor și directorelor (folder-elor) de pe o partiție, unde fișierele sunt similare claselor și directorele sunt similare pachetelor. Separatorul folosit între numele de pachete și clasă este caracterul ".".
Cuvântul cheie care determină pachetul în care este plasată o clasă este package. Dacă această directivă lipsește, clasa este plasată implicit în "rădăcina" ierarhiei de pachete.
package myPackage;
import java.util.ArrayList;
import java.io.*;
class TestClass{
public static void main(String[] _args){
//ArrayList class is in package java.util so it needs to be imported
ArrayList _arrayList = new ArrayList();
//both FileOutputStream and IOException are in package java.io so they
//are both available.
try{
FileOutputStream _fileOutputStream = new FileOutputStream("test");
_fileOutputStream.close();
}catch(IOException _ioe){
_ioe.printStackTrace();
}
//Class System is in package java.lang so it is automatically imported
System.out.println("Done!");
}
}
Definiția câmpurilor
Câmpurile, ca orice variabilă, pot fi de tip primitiv sau referință. Ele se declară în interiorul clasei, dar în afara oricărei metode:
class SomeClass{
//fields here
int somePrimitiveField;
boolean someOtherPrimitiveField;
Object aReferenceField;
int[][] anotherReferenceFieldToAnArray;
}
Atenție: Câmpurile au valori diferite pentru fiecare instanță, adică pentru fiecare obiect.
Definiția metodelor
Metodele se pot defini și implementa exclusiv în interiorul unei clase. Metodele acționează asupra câmpurilor clasei. Ca și în C, metodele se declară folosind următorul tipar:
- zero sau mai mulți modificatori;
- tipul returnat (sau void dacă metoda nu întoarce nimic) - atenție, constructorii nu au tip returnat, nici măcar void;
- numele metodei;
- între paranteze rotunde, lista de argumente, definite prin tip și nume și separate prin virgulă;
- între acolade, corpul metodei.
class SomeClass{
//fields here
int somePrimitiveField;
boolean someOtherPrimitiveField;
Object aReferenceField;
int[][] anotherReferenceFieldToAnArray;
//methods here
//---------------------------------------------------------------------
int getSomePrimitiveField(){
return somePrimitiveField;
}
//---------------------------------------------------------------------
void setSomePrimitiveField(int _somePrimitiveField){
somePrimitiveField = _somePrimitiveField;
}
//---------------------------------------------------------------------
boolean aMoreComplexMethod(Object _aReferenceField){
if(_aReferenceField != null){
aReference = _aReferenceField;
}
return aReference != null;
}
}
Variabilele primitive sau de tip referință declarate în interiorul unei metode, sau ca argumente ale unei metode, se numesc variabile locale și nu sunt câmpuri ale clasei.
Constructorii claselor
Constructorii sunt metode speciale ale unei clase care se apelează obligatoriu la instanțierea unui obiect. Acestea au următoarele proprietăți:
Exemplu de constructori pentru clasa SomeClass:
class SomeClass{
//fields here
int somePrimitiveField;
boolean someOtherPrimitiveField;
Object aReferenceField;
int[][] anotherReferenceFieldToAnArray;
//constructors here
//---------------------------------------------------------------------
SomeClass(){ //this is a constructor
somePrimitiveField = 0;
someOtherPrimitiveField = false;
aReferenceField = new Object();
anotherReferenceFieldToAnArray = null;
}
//---------------------------------------------------------------------
SomeClass(int _somePrimitiveField){ //this is another constructor
somePrimitiveField = _somePrimitiveField;
someOtherPrimitiveField = false;
aReferenceField = new Object();
anotherReferenceFieldToAnArray = null;
}
//methods here
//---------------------------------------------------------------------
int getSomePrimitiveField(){
return somePrimitiveField;
}
//---------------------------------------------------------------------
void setSomePrimitiveField(int _somePrimitiveField){
somePrimitiveField = _somePrimitiveField;
}
//---------------------------------------------------------------------
boolean aMoreComplexMethod(Object _aReferenceField){
if(_aReferenceField != null){
aReference = _aReferenceField;
}
return aReference != null;
}
}
Exemplu de apelare a constructorilor:
class MainClass{
public static void main(String[] _args){
SomeClass _obj1 = new SomeClass(); //this calls the first constructor
SomeClass _obj2 = new SomeClass(1234); //this calls the second constructor
System.out.println(_obj1.getSomePrimitiveField()); //this will print 0
System.out.println(_obj2.getSomePrimitiveField()); //this will print 1234
}
}
Cuvintele cheie this și super
Cuvântul cheie this poate fi folosit în două situații:
- ca apel de constructor din alt constructor;
- ca referință la obiectul curent ca instanță a clasei curente.
Exemplu de utilizare a cuvântului cheie this:
import java.util.ArrayList;
class SomeClass{
//fields here
int somePrimitiveField;
boolean someOtherPrimitiveField;
Object aReferenceField;
int[][] anotherReferenceFieldToAnArray;
//constructors here
//---------------------------------------------------------------------
SomeClass(){ //this is a constructor
this(10); //this is a call to the other constructor
// (see method overloading)
}
//---------------------------------------------------------------------
SomeClass(int _somePrimitiveField){ //this is another constructor
somePrimitiveField = _somePrimitiveField;
someOtherPrimitiveField = false;
aReferenceField = new Object();
anotherReferenceFieldToAnArray = null;
}
//methods here
//---------------------------------------------------------------------
int getSomePrimitiveField(){
return somePrimitiveField;
}
//---------------------------------------------------------------------
void setSomePrimitiveField(int somePrimitiveField){
this.somePrimitiveField = somePrimitiveField;
/*here, "this" is a reference to the
*current object. It is used to make the difference
*between the field somePrimitiveField and the local
*variable with the same name. Writing "somePrimitiveField"
*with no object specifier ("this") will direct the compiler
*to the closest defined variable with that name: the local
*variable:
*/
somePrimitiveField = 10; //this is the local variable
this.somePrimitiveField = 10; // this is the field
/*"this" can also be used for passing the current object
*as argument to other methods:
*/
ArrayList _list = new ArrayList();
_list.add(this);
}
//---------------------------------------------------------------------
boolean aMoreComplexMethod(Object _aReferenceField){
if(_aReferenceField != null){
aReference = _aReferenceField;
}
return aReference != null;
}
}
Cuvântul cheie super este folosit în două situații (vezi ierarhii de clase):
- ca apel al unui constructor al superclasei dintr-un constructor al clasei curente;
- ca referință la obiectul curent ca instanță a superclasei.
import java.util.ArrayList;
class SomeClass{
//fields here
int somePrimitiveField;
boolean someOtherPrimitiveField;
Object aReferenceField;
int[][] anotherReferenceFieldToAnArray;
//constructors here
//---------------------------------------------------------------------
SomeClass(){ //this is a constructor
this(10); //this is a call to the other constructor
// (see method overloading)
}
//---------------------------------------------------------------------
SomeClass(int _somePrimitiveField){ //this is another constructor
super();
/* Class SomeClass is extended from Object class so
* the super() call is the call to the Object()
* constructor.
*/
somePrimitiveField = _somePrimitiveField;
someOtherPrimitiveField = false;
aReferenceField = new Object();
anotherReferenceFieldToAnArray = null;
}
//methods here
//---------------------------------------------------------------------
int getSomePrimitiveField(){
return somePrimitiveField;
}
//---------------------------------------------------------------------
void setSomePrimitiveField(int somePrimitiveField){
this.somePrimitiveField = somePrimitiveField;
/*here, "this" is a reference to the
*current object. It is used to make the difference
*between the field somePrimitiveField and the local
*variable with the same name. Writing "somePrimitiveField"
*with no object specifier ("this") will direct the compiler
*to the closest defined variable with that name: the local
*variable:
*/
somePrimitiveField = 10; //this is the local variable
this.somePrimitiveField = 10; // this is the field
/*"this" can also be used for passing the current object
*as argument to other methods:
*/
ArrayList _list = new ArrayList();
_list.add(this);
}
//---------------------------------------------------------------------
boolean aMoreComplexMethod(Object _aReferenceField){
if(_aReferenceField != null){
aReference = _aReferenceField;
}
return aReference != null;
}
//---------------------------------------------------------------------
String toString(){
return "SomeClass " + super.toString();
/* Here, the "super" keyword is used as a reference to the current
* object but it is calling the method "toString" defined in the
* superclass (see method overwriting). If the "super" was missing,
* it would recursively call the same method, crashing the program.
* Instead, it is now calling an entirely different method belonging
* to the superclass.
*/
}
}
Membrii statici
Membrii statici ai unei clase reprezintă membrii care nu-și schimbă valoarea sau comportamentul pentru obiecte distincte, adică țin de clasă, și nu de fiecare instanță în parte.
class SomeClass{
//fields here
static int someStaticField;
int somePrimitiveField;
boolean someOtherPrimitiveField;
Object aReferenceField;
int[][] anotherReferenceFieldToAnArray;
}
Modificatori speciali pentru membrii
Modificatori de access
Modificator | Clasa Curenta | Pachet | Clasa Derivată | În afara pachetului |
---|---|---|---|---|
public | DA | DA | DA | DA |
protected | DA | DA | DA | NU |
implicit (fără specificator) | DA | DA | NU | NU |
private | DA | NU | NU | NU |
import java.util.ArrayList;
public class SomeClass{
//fields here
private int somePrimitiveField;
private boolean someOtherPrimitiveField;
private Object aReferenceField;
private int[][] anotherReferenceFieldToAnArray;
//constructors here
//---------------------------------------------------------------------
public SomeClass(){ //this is a constructor
this(10); //this is a call to the other constructor
// (see method overloading)
}
//---------------------------------------------------------------------
public SomeClass(int _somePrimitiveField){//this is another constructor
super();
/* Class SomeClass is extended from Object class so
* the super() call is the call to the Object()
* constructor.
*/
somePrimitiveField = _somePrimitiveField;
someOtherPrimitiveField = false;
aReferenceField = new Object();
anotherReferenceFieldToAnArray = null;
}
//methods here
//---------------------------------------------------------------------
public int getSomePrimitiveField(){
return somePrimitiveField;
}
//---------------------------------------------------------------------
protected void setSomePrimitiveField(int somePrimitiveField){
this.somePrimitiveField = somePrimitiveField;
/*here, "this" is a reference to the
*current object. It is used to make the difference
*between the field somePrimitiveField and the local
*variable with the same name. Writing "somePrimitiveField"
*with no object specifier ("this") will direct the compiler
*to the closest defined variable with that name: the local
*variable:
*/
somePrimitiveField = 10; //this is the local variable
this.somePrimitiveField = 10; // this is the field
/*"this" can also be used for passing the current object
*as argument to other methods:
*/
ArrayList _list = new ArrayList();
_list.add(this);
}
//---------------------------------------------------------------------
private boolean aMoreComplexMethod(Object _aReferenceField){
if(_aReferenceField != null){
aReference = _aReferenceField;
}
return aReference != null;
}
//---------------------------------------------------------------------
public String toString(){
return "SomeClass " + super.toString();
/* Here, the "super" keyword is used as a reference to the current
* object but it is calling the method "toString" defined in the
* superclass (see method overwriting). If the "super" was missing,
* it would recursively call the same method, crashing the program.
* Instead, it is now calling an entirely different method belonging
* to the superclass.
*/
}
}
public
Un element public este accesibil oricărei alte clase.
protected
Un câmp sau metodă protejată este accesibilă claselor din același pachet și claselor derivate din alte pachete.
implicit (fără specificator)
Lipsa unui modificator de access implică faptul că elementul este accesibil clasei curente sau claselor din același pachet, dar nu și claselor din alte pachete.
private
Un câmp sau metodă privată este accesibilă doar clasei curente.
Modificatorul final
Modificatorul final poate fi aplicat:
- unei clase - clasa nu poate fi extinsă;
- unei interfețe - interfața nu poate fi extinsă;
- unei metode - metoda nu poate fi suprascrisă;
- unui câmp - acestuia i se poate da o singură valoare care va rămâne constantă pe toată durata existenței obiectului.
Un câmp care este static și final este o constantă a clasei.
Modificatorul abstract
O metodă abstractă este o metodă care nu are implementare (doar prototipul).
Exemplu:
abstract class Sorter{
protected Object[] data;
public Sorter(Object[] _data){
data = _data;
}
//this is an abstract method
protected abstract void sort();
public Object[] getResult(){
sort();
return data;
}
}
class BubbleSorter extends Sorter{
public BubbleSorter(Object[] _data){
super(data);
}
//this is the implementation of the abstract method
protected void sort(){
boolean _done;
do{
_done = true;
for(int i=0; i<data.length - 1; i++){
if(compare(data[i], data[i + 1]) < 0){
Object _tmp = data[i];
data[i] = data[i + 1];
data[i + 1] = _tmp;
_done = false;
}
}
}while(!_done);
}
private int compare(Object _obj1, Object obj2){
//...
}
}
Modificatorul volatile
Un câmp este declarat volatil atunci când este scris de mai mult de un fir de execuție și în acest caz valoarea respectivă va fi încărcată de fiecare dată din memorie și nu se vor încărca în memoria cache.
Câmpurile volatile reprezintă o alternativă la mecanismul de sincronizare, dar poate fi folosit doar în anumite situații în care nu există race conditions. Vezi Programare concurentă - fire de execuție (Threads).
Modificatorul transient
Un câmp declarat transient nu va fi salvat împreună cu obiectul la serializarea acestuia (vezi serializarea obiectelor).
Modificatorul synchronized
O metodă sincronizată nu este accesibilă decât unui singur thread la un moment dat. Acest cuvânt cheie poate fi utilizat atât ca modificator pentru o metodă, cât și ca bloc de instrucțiuni în interiorul unei metode:
import java.util.ArrayList;
public class Queue extends ArrayList{
public Queue(){
super();
}
public synchronized void push(Object _obj){
add(_obj);
}
public Object pop(){
if(size() != 0){
synchronized(this){
return remove(0);
}
}else{
throw new RuntimeException("Queue empty!");
}
}
}
Mai multe despre thread-uri în capitolul Programare concurentă - fire de execuție (Threads).
Modificatorul native
Există situații în care anumite funcții de sistem nu pot fi apelate în Java, sau alte cazuri în care din Java trebuie apelate funcții dintr-o bibliotecă (.dll sau .so, etc.). În acest caz, din aplicația Java trebuie apelate funcții compilate în limbajul nativ al mașinii, și nu în limbajul mașinii virtuale. Aceste funcții se numesc native, iar mecanismul prin care se pot apela ele din Java se numește JNI (Java Native Interface).
Mai multe despre cum se implementează metodele native pe site-ul Oracle.
Constante de clasă
Un câmp declarat în același timp static și final se numește constantă a clasei.
Extinderea claselor
Limbajul Java suportă moștenirea simplă (vezi ierarhii de clase și polimorfism). Cuvântul cheie care permite extinderea unei clase este extends.
Exemplu:
//---------------------------------------------------
//file Vehicle.java
public class Vehicle{ //class Vehicle extends Object
protected int cylinders;
protected float maxSpeed;
protected static float maxAcceptedVehicleMass;
protected float vehicleMass;
public void startEngine(){
//...
}
}
//---------------------------------------------------
//file Truck.java
public class Truck extends Vehicle{ //class Truck extends Vehicle
protected float maxCargoWeight;
protected float currentCargoWeight;
public void loadCargo(float _cargo){
// protected fields maxAcceptedVehicleMass and vehicleMass
// are inherited from Vehicle class
if(currentCargoWeight + _cargo <= maxCargoWeight &&
vehicleMass + currentCargoWeight + _cargo <= maxAcceptedVehicleMass){
currentCargoWeight += _cargo;
}
}
}
Șabloane (generics)
Există situații în care o anumită instanță a unei clase lucrează exclusiv cu un anumit tip de date. În acest caz, dacă clasa este definită ca folosind, de exemplu, date de tip Object, atunci trebuie făcuți pași suplimentari, consumatori de timp, pentru a face up-cast de la Object la tipul de date (clasa) cu care se lucrează. În plus, aceste operații de up-cast sunt verificate doar la runtime, crescând șansa să apară erori de programare ne-detectabile la compilare. Ca exemplu, vom descrie o clasă Stack care stochează referințe de tip Object:
public class Stack{
private Object[] stackArray;
private int stackTop;
public Stack(int _size){
stackArray = new Object[_size];
stackTop = 0;
}
public Object pop() throws Exception{
if(stackTop > 0){
return stackArray[--stackTop];
}
throw new Exception("Stack empty");
}
public void push(Object _obj) throws Exception{
if(stackTop < stack.length){
stackArray[stackTop++] = _obj;
return;
}
throw new Exception("Stack full");
}
}
Și o clasă care folosește o stivă exclusiv pentru obiecte de tip String:
public class StringStacker{
public static void main(String[] _args){
Stack _stack = new Stack(10);
try{
// String is automatically down-cast to Object
// we could just as well push any kind of reference
// on this stack, by mistake, and reading and trying
// to up-cast it as String will give a runtime ClassCastException
_stack.push("Hello world!");
_stack.push("Byebye world");
// Object must be manually up-casted to String
// every time, even if it's obvious that all
// objects on the stack are Strings
String _secondString = (String)_stack.pop();
String _firstString = (String)_stack.pop();
System.out.println(_secondString + ", " + _firstString);
}catch(Exception _e){
System.out.println("Stack error: " + _e.getMessage());
}
}
}
Această problemă se poate rezolva folosind șabloane. Vom rescrie clasa Stack:
public class Stack <GenericType>{
private GenericType[] stackArray;
private int stackTop;
public Stack(int _size){
stackArray = new GenericType[_size];
stackTop = 0;
}
public GenericType pop() throws Exception{
if(stackTop > 0){
return stackArray[--stackTop];
}
throw new Exception("Stack empty");
}
public void push(GenericType _obj) throws Exception{
if(stackTop < stack.length){
stackArray[stackTop++] = _obj;
return;
}
throw new Exception("Stack full");
}
}
Și clasa StringStacker:
public class StringStacker{
public static void main(String[] _args){
// at this point, the _stack object is an instance
// of the class Stack, where GenericType has been
// replaced by String
Stack<String> _stack = new Stack<String>(10);
try{
// now the push method only takes Strings as
// an argument; trying to push an Object will
// fail with a compile time error
_stack.push("Hello world!");
_stack.push("Byebye world");
// pop() will now return a String so casting
// is no longer necessary
String _secondString = _stack.pop();
String _firstString = _stack.pop();
System.out.println(_secondString + ", " + _firstString);
}catch(Exception _e){
System.out.println("Stack error: " + _e.getMessage());
}
}
}
Mai multe despre șabloane în tutorial-ul Oracle.
Interfața Java
Interfața Java este o structură echivalentă cu o clasă abstractă în care toate metodele sunt abstracte. Spre deosebire de sistemul de moștenire (extindere), unde o clasă poate moșteni o singură altă clasă (moștenire simplă), o clasă poate implementa oricâte interfețe.
//---------------------------------------------------
//file Closeable.java
public interface Closeable{
public void close();
}
//---------------------------------------------------
//file Openable.java
public interface Openable{
public void open();
}
//---------------------------------------------------
//file Stream.java
public class Stream implements Openable, Closeable{
public void close(){
//.. something here
}
public void open(){
//... something here
}
}
//---------------------------------------------------
Mai multe despre interfețe în capitolele ierarhii de clase și polimorfism.
Construcții repetitive
Expresia for
Expresia for are două forme posibile. Prima este identică cu cea din C:
for(expresie_initializare; condiție_continuare; expresie_bucla){
//...
}
- expresie_inițializare - reprezintă o expresie care se execută o singură dată la intrarea în buclă;
- condiție_continuare - reprezintă o condiție care se evaluează la începutul fiecărei iterații; ciclul se continuă dacă condiția e adevărată sau dacă ea lipsește;
- expresie buclă - reprezintă o expresie care se execută necondiționat la sfărșitul fiecărei iterații.
Exemplu pentru un array:
int[] someArray = getArray();
for(int i=0; i<someArray.length; i++){
System.out.println(someArray[i]);
}
Exemplu pentru o listă:
Node firstNode = getList();
for(Node _eachNode = firstNode; _eachNode != null; _eachNode = _eachNode.getNextNode()){
System.out.println(_eachNode);
}
Exemplu pentru o buclă infinită:
for(;;){
System.out.println("Freedom!");
}
Al doilea tip de expresie for este utilizat pentru vectori în felul următor (identic ca funcționare cu primul exemplu):
int[] someArray = getArray();
for (int element : someArray) {
System.out.println(element);
}
Expresia while
Expresia while este identică cu cea din C:
while(conditie_continuare){
//... something
}
- conditie_continuare - este o condiție care se evaluează la începutul fiecarei iterații și bucla se încheie dacă aceasta este falsă.
int a = 20;
int b = 3;
while(a != b){
a++;
b--;
System.out.println(a * b);
}
Expresia do - while
Expresia do - while este identică cu cea din C:
do{
//... something
}while(conditie_continuare);
- conditie_continuare - este o condiție care se evaluează la sfârșitul fiecarei iterații și bucla se încheie dacă aceasta este falsă.
int a = 20;
int b = 3;
do{
a++;
b--;
System.out.println(a * b);
}while(a != b);
Instrucțiunile break & continue
Instrucțiunile break și continue sunt folosite identic cu cele din C și anume pentru a întrerupe un ciclu repetitiv (break) sau a continua cu următoarea iterație (continue).
Spre exemplu, pentru a căuta primul număr par mai mare ca 100 într-un vector:
int search(int[] someArray){
int result = 0;
for(int element: someArray){
if(element % 2 != 0){
continue;
}
if(element > 100){
result = element;
break;
}
}
return result;
}
Construcții condiționale
Operatorul condițional (?)
Operator condițional este identic cu cel din C:
(expresie_de_evaluat ? expresie_adevarat : expresie_fals)
- expresie_de_evaluat - reprezintă o expresie booleană (adevărat sau fals) de care depinde valoarea finală a expresiei condiționale;
- expresie_adevarat - dacă expresie_de_evaluat este adevărată, atunci expresia condițională va lua valoarea expresie_adevarat;
- expresie_fals - dacă expresie_de_evaluat este falsă, atunci expresia condițională va lua valoarea expresie_fals;
public class Utils{
//private constructor means the class can't be instantiated
private Utils(){
//nothing here
}
public static float max(float a, float b){
// if a is greater than b, the expression is
// evaluated to a and the value of a is returned
// else the expression is evaluated to b and the
// value of b is returned
return a > b ? a : b;
}
}
Expresia if - else
Expresia if-else este expresia condițională standard și este și ea identică cu cea din C:
if(conditie){
//instructiuni
}else{
//instructiuni
}
- conditie - este o expresie booleană care se evaluează și în funcție de care se execută primul bloc de instrucțiuni (dacă expresia este adevărată) sau al doilea bloc de instrucțiuni (cel de după else, dacă expresia este falsă).
Exemple de blocuri if:
public class Utils{
private Utils(){
// nothing here
}
public static float clamp(float _value, float _lowestValue, float _highestValue){
float _result = 0;
if(_value < _lowestValue){
_result = _lowestValue;
}else if(_value > _highestValue){
_result = _highestValue;
}else{
_result = _value;
}
return _result;
}
public static float max(float a, float b){
float _result = 0;
if(a > b){
result = a;
}else{
result = b;
}
return result;
}
public static float abs(float a){
if(a < 0){
a = -a;
}
return a;
}
}
Expresia switch
Expresia switch este identică cu cea din C. Se folosește atunci când în funcție de valoarea unei expresii trebuie executate diferite instrucțiuni:
switch(expresie){
case Valoare_1:
// bloc_instructiuni_1
break;
case Valoare_2:
// bloc_instructiuni_2
break;
case Valoare_3:
// bloc_instructiuni_3
break;
default:
// bloc_instructiuni_default
}
- expresie - reprezintă expresia în funcție de valoarea căreia se sare la blocul de instrucțiuni corespunzător;
- Valoare_i, bloc_instructiuni_i - dacă expresia expresie are valoarea Valoare_i, atunci se sare la bloc_instrucțiuni_i; Valoare_i trebuie să fie constantă.
- default - este un cuvânt cheie care determină blocul la care se sare (bloc_instructiuni_default) în cazul în care valoarea expresiei nu corespunde nici unei valori specificate in blocul switch.
public String intToString(int _value){
String _result = "";
switch(_value){
case 0: _result = "zero"; break;
case 1: _result = "one"; break;
case 2: _result = "two"; break;
case 3: _result = "three"; break;
case 4: _result = "four"; break;
case 5: _result = "five"; break;
case 6: _result = "six"; break;
case 7: _result = "seven"; break;
case 8: _result = "eight"; break;
case 9: _result = "nine"; break;
default: _result = "more than nine"; break;
}
return _result;
}
Cuvinte cheie pentru tratarea excepțiilor
O excepție se aruncă folosind cuvântul cheie throw. O metodă care nu administrează o excepție trebuie să o declare în prototip folosind cuvântul cheie throws. Un bloc de administrare a excepțiilor este de tip try-catch-finally sau, din Java 7, try-with-resources:
public class TestClass{
private int value;
public static void main(String[] _args){
try{
TestClass _obj = new TestClass(10);
_obj.someMethod();
}catch(Exception _e){
System.out.println("Exception caught: " + _e.getMessage());
}
try{
TestClass _obj = new TestClass(-10);
_obj.someMethod();
}catch(Exception _e){
System.out.println("Exception caught: " + _e.getMessage());
}
}
public TestClass(int _value) throws Exception{
if(_value < 0){
throw new Exception("The value must not be negative: " + _value);
}
value = _value;
}
public void someMethod(){
System.out.println("Running method for value " + value);
}
}
Mai multe despre excepții în capitolul tratarea excepțiilor.
Operatori
Aceasta este lista de operatori permiși în limbajul Java. Spre deosebire de C++, în Java nu este permisă supraîncarcarea operatorilor.
Precedență | Operator | Descriere | Asociativitate |
---|---|---|---|
1 | ()
|
Apel de metodă | De la stânga la dreapta |
[]
|
Acces la elemente din vector | ||
.
|
Acces la membrul unei clase | ||
2 | ++ --
|
Incrementare și decrementare ca sufix | |
3 | ++ --
|
Incrementare și decrementare ca prefix | De la dreapta la stânga |
+ -
|
Plus și minus unar | ||
! ~
|
NU logic și NU pe biți | ||
(type) val
|
Type cast | ||
new
|
Instanțiere de obiecte sau de vectori | ||
4 | * / %
|
Înmuțire, împărțire și modulo (rest) | De la stânga la dreapta |
5 | + -
|
Adunare și scădere | |
+
|
Concatenare de stringuri | ||
6 | << >> >>>
|
Shift pe biți la stânga, shift pe biți la dreapta cu semn și fără semn | |
7 | < <=
|
Operator de comparare "mai mic decât" și "mai mic sau egal" | |
> >=
|
Operator de comparare "mai mare ca" și "mai mare sau egal" | ||
instanceof
|
Comparare de tip | ||
8 | == !=
|
Operator de comparare "egal cu" sau "diferit de" | |
9 | &
|
AND (și) pe biți | |
10 | ^
|
XOR (sau exclusiv) pe biți | |
11 | |
|
OR (sau) pe biți | |
12 | &&
|
AND (și) logic | |
13 | ||
|
OR (sau) logic | |
14 | c ? t : f
|
Operator ternar condițional (vezi #Operatorul condițional (?)) | De la dreapta la stânga |
15 | =
|
Asignare simplă | |
+= -=
|
Asignare cu sumă sau diferență | ||
*= /= %=
|
Asignare cu produs, cât sau rest | ||
<<= >>= >>>=
|
Asignare cu shift la stânga, la dreapta, sau la dreapta fără semn | ||
&= ^= |=
|
Asignare cu AND, XOR, sau OR pe biți |