Sintaxa limbajului Java; Structura lexicală a unui program
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ă.
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.
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.
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.
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.
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. */
}
} </syntaxhighlight>
Membrii statici
Membrii statici ai unei clase sunt opusul