Structuri lexicale

Setul de caractere

Limbajului Java lucrează în mod nativ folosind setul de caractere Unicode. Acesta este un standard internațional care înlocuieste vechiul set de caractere ASCII şi care foloseşte pentru reprezentarea caracterelor 2 octeţi, ceea ce înseamnă că se pot reprezenta 65536 de semne, spre deosebire de ASCII, unde era posibilă reprezentarea a 256 de caractere. Primele 256 caractere Unicode corespund celor din ASCII, referirea la celelate făcându-se prin \uxxxx, unde xxxx reprezintă codul caracterului.

Exemplu:

  • \u0030 - \u0039 : cifre ISO-Latin 0 - 9
  • \u0660 - \u0669 : cifre arabic-indic 0 - 9
  • \u4e00 - \u9fff : litere din alfabetul Han (Chinez, Japonez, Coreean)

Cuvinte cheie

Cuvintele rezervate în Java sunt cele din C++, cu câteva excepţii. Cuvintele cheie Java pot fi gasite aici.

Identificatori

Sunt secvenţe nelimitate de litere şi cifre Unicode, începând cu o literă. Identificatorii nu au voie să fie identici cu alte cuvinte rezervate.

Literali

Literali întregi: Sunt acceptate 3 baze de numeraţie : baza 10, baza 16 (începând cu caracterele 0x) şi baza 8 (începând cu cifra 0) şi pot fi de două tipuri:

  • normali, (se reprezintă pe 4 octeţi - 32 biţi)
  • lungi (8 octeţi - 64 biţi) : se termină cu caracterul L (sau l).

Literali flotanţi: Pentru ca un literal să fie considerat flotant el trebuie să aibă cel puţin o zecimală după virgulă, să fie în notaţie exponenţială sau să aibă sufixul F sau f pentru valorile normale (reprezentate pe 32 biţi), respectiv D sau d pentru valorile duble (reprezentate pe 64 biţi).

Literali logici:

  • true : valoarea booleană de adevăr
  • false : valoarea booleană de fals

Spre deosebire de C++, literalii întregi 1 şi 0 nu au rolul de adevărat şi fals.

Literali caractere

Un literal de tip caracter este utilizat pentru a exprima caracterele codului Unicode. Reprezentarea se face fie folosind o literă, fie o secvenţă escape scrisă între apostrofuri. Secvenţele escape permit reprezentarea caracterelor care nu au reprezentare grafică şi reprezentarea unor caractere speciale precum “backslash“, caracterul apostrof etc. Secvenţe escape predefinite în Java pot fi gasite aici.

Literali şiruri de caractere

Un literal şir de caractere este format din zero sau mai multe caractere între ghilimele. Caracterele care formează şirul de caractere pot fi caractere grafice sau secvenţe escape ca cele definite la literalii caracter. Șirul vid este “”. Dacă şirul este prea lung el poate fi scris ca o concatenare de subşiruri de dimensiune mai mică. Concatenarea şirurilor se face cu operatorul “+”, exemplu: “alfa ” + “ beta ” + “ gama ”. Orice şir este de fapt o instanţă a clasei String, definită în pachetul java.lang. Obiectele String sunt imutabile (orice modificare a șirului de caractere determină crearea unui nou obiect).

Separatori

Un separator este un caracter care indică sfîrşitul unei unităţi lexicale şi începutul alteia. În Java separatorii sunt următorii: ( ) { } [ ] ; , . Instrucţiunile unui program se separă cu punct şi virgulă.

Operatori

atribuirea: =

operatori matematici: +, -, *, /, %

operatorii pentru autoincrementare şi autodecrementare (post şi pre): x++, ++x, n–, –n

Evaluarea expresiilor logice se face prin metoda scurtcircuitului, evaluarea se oprește în momentul în care valoarea de adevăr a expresiei este sigur determinată.

operatori logici: &&(and), ||(or), !(not)

operatori relaţionali: <, ⇐, >, ⇐, ==, !=

operatori pe biţi: & (and), |(or), ^(xor), ~(not)

operatori de translaţie «, », »> (shift la dreapta fără semn)

operatorul if-else: expresie_logica ? val_pt_true : val_pt_false

operatorul , (virgulă) folosit pentru evaluarea secvenţială a operaţiilor: int x=0, y=1, z=2;

operatorul “+” pentru concatenarea şirurilor, exemplu:

String s="abcd";
int x=100;
System.out.println(s + " - " + x);

operatori pentru conversii (cast) : (tip_de_data), exemplu:

int i = 200;
long l = (long)i; //widening conversion - conversie prin extensie
long l2 = (long)200;
int i2 = (int)l2; //narrowing conversion - conversie prin contracţie

Tipuri de date

În Java tipurile de date se împart în două categorii: tipuri primitive şi tipuri referinţă. Java porneşte de la premisa că “orice este un obiect”. Aşadar tipurile de date ar trebui să fie de fapt definite de clase şi toate variabilele ar trebui să memoreze de fapt instanţe ale acestor clase (obiecte). În principiu acest lucru este adevărat, însă, pentru usurinţa programării, mai există şi tipurile primitive de date, care sunt cele uzuale:

întregi: byte (1 octet), short (2), int (4), long (8)
reale: float (4 octeţi), double (8)
caracter : char (2 octeţi)
logic : boolean (true şi false)

În alte limbaje formatul şi dimensiunea tipurilor primitive de date folosite într-un program pot depinde de platforma pe care rulează programul. În Java acest lucru nu mai este valabil, orice dependenţă de o anumită platformă specifică fiind eliminată.

Vectorii, clasele şi interfeţele sunt tipuri referinţă. Valoarea unei variabile de acest tip este, în contrast cu tipurile primitive, o referinţă (adresă de memorie) către valoarea sau mulţimea de valori reprezentată de variabilă respectivă.

Există trei tipuri de date în C care nu sunt suportate de limbajul Java. Acestea sunt: pointer, struct şi union. Point-erii au fost eliminaţi din cauză că erau o sursă constantă de erori, locul lor fiind luat de tipul referinţă, iar struct şi union nu îşi mai au rostul atât timp cât tipurile compuse de date sunt formate în Java prin intermediul claselor.

Variabile

Variabile sunt in java de doua tipuri:

  • tip primitiv
  • tip referinta

În funcţie de locul în care sunt declarate variabile acestea se împart în urmatoatele categorii:

  • variabile membre, declarate în interiorul unei clase, vizibile pentru toate metodele clasei respective şi pentru alte clase în functie de nivelul lor de acces (vezi “Declararea variabilelor membre”);
  • variabile locale, declarate într-o metodă sau într-un bloc de cod, vizibile doar în metoda/blocul respectiv;
  • parametrii metodelor, vizibili doar în metoda respectivă;
  • parametrii de la tratarea exceptiilor.

Observatie: Variabilele declarate într-un for pentru controlul ciclului, ramân locale corpului ciclului.

Observatie: Spre deosebire de C++ nu este permisă ascunderea unei variabile:

int x = 12;
{
 int x = 96;  // ilegal
}

Controlul executiei programelor

if-else

Instructiunea if-else este cea mai simpla instructiune pentru controlul flucusului unui program. Aceasta spune programului sa execute o anumita secventa de cod doar daca expresia logica evaluata are valoare de adevar true. In caz contrar se executa ramura else.

public class IfElseDemo {
    public static void main(String[] args) {
 
        int testscore = 76;
        char grade;
 
        if (testscore >= 90) {
            grade = 'A';
        } else if (testscore >= 80) {
            grade = 'B';
        } else if (testscore >= 70) {
            grade = 'C';
        } else if (testscore >= 60) {
            grade = 'D';
        } else {
            grade = 'F';
        }
        System.out.println("Grade = " + grade);
    }
}

switch

Instrucitunea switch executa unul sau mai multe blocuri de instructiuni in functie de valoarea expresiei evaluate. In cazul in care instructiunea brake lipseste atunci se va executa si urmatorul bloc case. Blocul special default este executat in cazul in care nici unul dintre blocurile case nu este executat.

public class SwitchDemo {
    public static void main(String[] args) {
 
        int month = 8;
        String monthString;
        switch (month) {
            case 1:  monthString = "January";
                     break;
            case 2:  monthString = "February";
                     break;
            case 3:  monthString = "March";
                     break;
            case 4:  monthString = "April";
                     break;
            case 5:  monthString = "May";
                     break;
            case 6:  monthString = "June";
                     break;
            case 7:  monthString = "July";
                     break;
            case 8:  monthString = "August";
                     break;
            case 9:  monthString = "September";
                     break;
            case 10: monthString = "October";
                     break;
            case 11: monthString = "November";
                     break;
            case 12: monthString = "December";
                     break;
            default: monthString = "Invalid month";
                     break;
        }
        System.out.println(monthString);
    }
}

while

Blocul while executa ciclic o secventa de instructiuni atata timp cat valoarea expresiei logice din paranteza este adevarata.

class WhileDemo {
    public static void main(String[] args){
        int count = 1;
        while (count < 11) {
            System.out.println("Count is: " + count);
            count++;
        }
    }
}

do-while

Blocul do-while este similar cu blocul while, cu deosebirea ca acesta din urma executa cel putin o data secventa de instructiuni.

class DoWhileDemo {
    public static void main(String[] args){
        int count = 1;
        do {
            System.out.println("Count is: " + count);
            count++;
        } while (count < 11);
    }
}

for

Blocul for ofera o metoda alternativa de executare iterativa a unei secvente de instructiuni.

class ForDemo {
    public static void main(String[] args){
         for(int i=1; i<11; i++){
              System.out.println("Count is: " + i);
         }
    }
}

O varianta a instructiunii for este cea in care nu este specificata conditia de terminare ci este specificata o colectie (vector) ce trebuie parcursa (iterata) si elementul care o va parcurge (iteratorul). Aceasta varianta este o metoda mai compacta si mai eleganta de parcurgere a colectiilor.

class EnhancedForDemo {
    public static void main(String[] args){
         int[] numbers = 
             {1,2,3,4,5,6,7,8,9,10};
         for (int item : numbers) {
             System.out.println("Count is: " + item);
         }
    }
}

Siruri de elemente

Sirurile sunt in Java definite ca tipuri referinta.

Declararea sirului se face in doua moduri:

  • Tip[ ] numeVector;
  • Tip numeVector[ ];

Instanţierea se realizează prin intermediul operatorului new şi are ca efect alocarea memoriei pentru sir, mai precis specificarea numărului maxim de elemente pe care îl va avea sirul:

  • numeVector = new Tip[dimensiune];

După declararea unui sir, acesta poate fi iniţializat, adică elementele sale pot primi nişte valori iniţiale, evident dacă este cazul pentru aşa ceva. In acest caz instanţierea lipseşte, alocarea memoriei facându-se automat în funcţie de numărul de elemente cu care se iniţializează vectorul.

int[ ] intregi;
String adrese[ ];
 
int v[] = new int[10]; // se alocă spaţiu pentru 10 întregi
String[] adrese = new String[100];
 
String culori[ ] = {"Rosu", "Galben", "Verde"};
int [ ]factorial = {1, 1, 2, 6, 24, 120};

Primul indice al unui sir este 0, deci poziţiile unui sir cu n elemente vor fi cuprinse între 0 şi n-1. Nu sunt permise construcții de genul Tip numeVector[dimensiune], alocarea memoriei făcându-se doar prin intermediul opearatorului new.

În Java tablourile multidimensionale sunt de fapt siruri de siruri.

int m[][]; // declararea unei matrici
m = new int[5][10]; // cu 5 linii, 10 coloane
int l[] = m[1]; // m[1] este un vector cu 10 elemente

Cu ajutorul cuvântului cheie length se poate afla dimensiunea unui vector.

int [ ]a = new int[5];
int la = a.length;      //are valoarea 5
int m[][] = new int[5][10];
int lm = m[0].length;    //are valoarea 10
class MultiDimArrayDemo {
    public static void main(String[] args) {
        String[][] names = {
            {"Mr. ", "Mrs. ", "Ms. "},
            {"Smith", "Jones"}
        };
        // Mr. Smith
        System.out.println(names[0][0] + names[1][0]);
        // Ms. Jones
        System.out.println(names[0][2] + names[1][1]);
    }
}

Exemplu construire sir de 10 elemente de tip int initializate cu numere aleatorii:

import java.util.*;
 
public class Hello {
    public static void main(String[] args){
        System.out.println("Hi there!");
 
        Random r = new Random();
 
        int[] a = new int[10];
 
        for(int i=0;i<a.length;i++){
            a[i] = r.nextInt(100);
        }
 
        for(int i=0;i<a.length;i++){
            System.out.print("a["+i+"]="+a[i]+" ");
        }
 
 
    }    
}