Java 1
Java 1
Java este un limbaj de programare orientat obiect, asemãnator cu C++, dar cu un alt conţinut
important ceea ce il face un instrument foarte robust pentru dezvoltarea de aplicaţii WWW.
Menirea limbajului Java este de a fi un standard pentru transferul de conţinut executabil pe
Internet prin WWW. Datorită limbajului Java se schimbă natură pasivă a reţelei Internet, deoarece
un program binar portabil generat de compilatorul Java, poate fi încarcat şi executat în mod
interpretativ pe orice calculator legat la Internet.
Proiectarea orientată pe obiecte este un instrument puternic, deoarece facilitează definirea clară a
interfeţelor şi permite reutilizarea unor module de program identificate ca şi obiecte. Fiind
conceput ca un limbaj obiectual, tot ce există într-un program este incapsulat în obiecte, care în
Java poartă denumirea de clase, limbajul permiţâd moştenirea şi extinderea unei clase şi
reutilizarea oricărui program sau modul în alte programe.
O clasa Java este o colecţie de variabile şi de metode, care încapsulează o anumită funcţionalitate,
într-un obiect reutilizabil şi încărcabil în mod dinamic. Mediul Java încarcã în mod dinamic
clasele, ceea ce înseamnă ca un program Java care se execută poate adăuga funcţionalităţi noi în
mod dinamic, prin încãrcarea claselor necesare la un moment dat.
Portabilitatea programelor este un deziderat major, care nu se poate realiza numai printr-o execuţie
interpretativa şi în acest sens în mediul Java pentru Internet un program sursă este compilat mai
intâi în cod binar portabil (codul binar), care este apoi adaptat cerinţelor codului nativ al
calculatorului pe care se execută. Aceast mecanism este o maşină Java virtuală (JVM), care la
rândul ei este implementată pe orice calculator ca şi interpretorul Java. Portabilitatea este asigurată
şi prin standardizarea tipurilor fundamentale.[LEMA-96]
Robusteţea mediului permite scrierea unor programe suple şi puternice, care funcţionează corect
astfel încât totul se decide dinamic, în timpul execuţiei, pentru a evita conflicte. Gestiunea
memoriei se realizează automat, nu prin instrucţiuni scrise în programul sursă ci printr-un sistem
complex implementat astfel încât să gestioneze clasele şi obiectele utilizate, interfeţele necesare şi
să elibereze în mod dinamic spaţiul de memorie neutilizat.
Avand în vedere ca mediul Java este un mediu de programare şi utilizare distribuit pe Internet,
care este implementat pe principiile tehnologiei Corba, se impun metode de protecţie atât pentru
sistemele clienţilor, cât şi pentru servere. Java permite crearea unor sisteme protejate, realizate
prin:[An-97]
Eliminarea pointerilor ca punctele slabe ale securităţii sistemelor împreună cu
aritmetica pointerilor, recunoscută ca o cauză importantă ce determină distrugeri
accidentale ale sistemelor.
Gestiunea automată a memoriei prin alocarea spaţiului la crearea un obiect şi
urmărirea pe parcursul execuţiei appletului până în momentul în care acesta nu mai este
referit, caz în care memoria este dezalocată automat. In opoziţie, gestiunea memoriei in C
şi C++ este realizată explicit de programatori cu ajutorul instrucţiunilor malloc şi free,
precum şi cu alte funcţii standard de gestiune a memoriei.
1
Alocarea dinamicã a memoriei este realizată automat în timpul execuţiei pentru
clasele create, eliminând alocarea statică a memoriei.
Gestionarea spaţiului alocat separat pentru fiecare clasă este soluţionată de
interpretorul Java care oferă spaţiu separat de variabile pentru clasele create.
Verificarea codului binar înainte de execuţie de către interpretorul Java, care
testeazã anumite convenţii ale limbajului şi ale mediului Java. Astfel se verifică dacă nu se
va execută o acţiune daunatoare pentru sistem: violarea restrictiilor de acces, efectuarea
unor conversii ilegale de date, depãşirea superioară sau inferioară a stivei, etc.
Reţea, clurul cu protocoale TCP/IP (Transmission Control , UDP(User Datagram
protocol), IP (Internet Protocol)
Internaţionalizare prin adaptarea programelor la setări locale de limbă şi fus orar.
Securitate la diverse niveluri, gestiunea cheilor publice şi private, restricţii selective
de acces, control şi securitate,etc.
Componente software reutilizabile -JavaBeans integrabile în arhitectura existentă.
Serializare/ deserializare de obiecte, care permite persistenţa şi comunicaţia între
obiecte la distanţă folosind Remote Method Invocation (RMI)
Acces la baze de date relaţionale, de diverse tipuri, folosint Java Database
Connectivity (JDBC)
Grafică bi/tridimensională, animaţie, etc.
Performanţele mediului sunt date şi de codul binar portabil rezultat în urma compilãrii, care este
adaptat în timpul execuţiei la codul nativ al calculatorului real pe care se rulează aplicaţia. In
anumite situaţii, compilarea este amânată pană în momentul execuţiei.
Java este un sistem dinamic extensibil, care poate achizitiona fişiere din orice punct al retelei
Internet. Fiind orientat pe obiecte, extensibilitatea dinamică se răsfrânge şi asupră obiectelor, caz
în care un program poate achizitiona în mod dinamic, din orice punct al reţelei, clasele de care are
nevoie în timpul execuţiei. In Java legarea variabilelor şi a metodelor se face tarziu (late binding),
chiar în momentul execuţiei iar interpretorul este cel care rezolvă referinţele simbolice şi
determină alocarea dinamică a memoriei. Regăsirea variabilelor şi a metodelor se face prin nume,
nu prin adrese relative. Orice clasa poate fi modificată in orice moment, fără a fi nevoie să se
recompileze toate subclasele sale. Avantajul referinţelor în momentul execuţiei este dat de
posibilitatea utilizării dinamice a claselor, care se pot actualiza tot timpul.
Limbajul Java a fost proiectat cu scopul de a se realiza un mijloc de transfer a conţinutului
executabil, dinamic, pe Internet iar funcţiile de reţea sunt cele care trebuie implementate în mediul
Java astfel încât să poată fi exploatat ca un mediu distribuit în Internet.
Odată cu paradigma business object, Enterprise1 Java s-a răspândit rapid în lumea calculatoarelor
desemnând acele aplicaţii Java dezvoltate pentru intranet-ul unei companii, care foloseşte
tehnologii Internet ca:e-mail, ftp, telnet, news, servicii Web,etc.
2
programul aşteaptă intervenţia utilizatorului, sau este ocupat cu accesul la fişiere sau la reţea. In
aplicaţiile cu un singur fir de aşteptare, unitatea centralã rãmâne neocupată intervale lungi de timp.
In mediul Java, acest timp este ocupat imediat de alte fire de execuţie, prin care se realizează
anumiţe acţiuni specifice.[Naugh-96]
Deşi este un limbaj de programare destinat WWW, permite definirea de aplicaţii independente,
fiind executate în mod interpretativ. Astfel se pot realiza aplicaţii pentru domenii ca: editoare de
texte, foi de calcul, baze de date, proiectare asistată de calculator. Utilizarea aplicaţiilor
independente în contextul unui mediu distribuit pe Internet oferă posibilitatea lansării de aplicaţii
care se află pe alte calculatoare dar pentru utilizarea applet-urilor java este necesară accesarea unor
site-uri Web cu browsere dotate cu interpretoare Java.
Pentru programatori, limbajul Java oferă o platformă unică pentru dezvoltarea de aplicaţii - un
calculator virtual, maşină virtuală Java şi aplicaţiile care se dezvoltă sau se distribuie pe reteaua
Internet. Pentru utilizatori, conţinutul executabil Java asigură integrarea perfectă a datelor cu
funcţiile şi interactiunile programelor, precum şi cu lucrul în retea, fără a fi sunt necesare aplicaţii
ajutatoare (helper applications) sau fişiere ajutătoare pentru diferite tipuri de protocoale, deoarece
Java permite încapsularea datelor şi a metodelor în clase.
Appleturile Java (sau programele interactive) permit abordarea de la nivelul superficial - imagini
animate, text în mişcare, etc- la nivelul substanţial - educaţie interactivă continuă, aplicaţii
orientate în afaceri. etc. Java este proiectat ca limbaj cross-platform, ceea ce înseamnă că poate
rula pe orice maşină, folosind orice sistem de operare. Codul sursă Java este compilat în
instrucţiuni pentru o maşină virtuală (un cip imaginar în exenţă simulat soft) iar aceste
instrucţiuni sunt interpretate de interpreterul Java, ce translatează codul binar în instrucţiuni în
limbaj maşină, care vor fi executate pe calculatorul virtual. Setul de instrucţiuni pentru maşina
virtuală şi codul binars în care acestea vor fi convertite sunt întotdeauna aceleaşi, fără a ţine seama
de diferenţele date de suportul hardware pe care rulează interpreterul.
Interpreterul în sine, pentru a-şi realiza obiectivele, trebuie să cunoască limbajul maşină al
dispozitivului hardware specific pe care rulează. De acceea softul scris în Java este independent
de platformă, fără a necesita portare sau recompilare, interpreterul Java portând platforma înainte
de a rula programul pe calculator.
Animaţia este un beneficiu simplu pe care îl aduce Java permiţând paginilor Web să conţină
imagini în mişcare. Appleturile Java oferă abilitatea animaţiei astfel încât paginile sunt continuu
interactive, pentru a răspunde direct, în timp real, intrărilor utilizatorului.
Interactivitatea pe partea clientului este realizată diferit faţă de paginile Web tradiţionale, unde
procesul este preluat pe partea serverului. Utilizând un browser disponibil java, pagina Web
conţine URL-ul appletului Java. Accesând această pagină, appletul este trimis pe calculatorul
propriu, care îl execută. Marea majoritate a prelucrărilor este transferată pe partea clientului, de la
serverul la distanţă. Aceasta permite interactivitate, fără întârzierile datorate timpului de răspuns ce
apar când informaţia este trimisă înapoi pe Internet. Intrările utilizatorului sunt trimise direct
programului responsabil pentru procesarea lor, ceea ce aduce interactivitatea paginilor Web.
Dezvoltarea API (Application Programming Interface) oferă programatorului acces la clase,
furnizând structuri comune de date, rutine I/O, tabele, fişiere, dispozitive reţea, grafică şi audoi,
funcţii matematice, etc. Java API furnizează elemente predefinite (butoane, bare de defilare, casete
de dialog, etc.) necesare construcţiei GUI (Graphic User Interface) şi referite în AWT (Abstract
Window Toolkit).[java_4]
3
Aplicaţiile de sine stătătoare (standalone) sunt foarte uşor de realizat deoarece Java este un limbaj
de programare complet, configurat OO. Când appleturile rulează fără browser disponibil java,
aplicaţiile standalone sunt complet autorizate, putând rula pe un calculator, sau preluâd avantajele
suportului Internet oferit de Java API. Spre exemplu Sun HotJava este scris complet în limbajul
Java.
Un alt exemplu este cel în care există o bază de date (BD) centrală pe un calculator şi toţi
utilizatorii din firmă au acces la ea, chiar dacă birourile sunt plasate în diverse locuri din oraş sau
chiar în oraşe diferite. Practic întregul program front-end care accesează BD este conceput ca
aplicaţie client ce nu trebuie portată şi recompilată pentru diverse platforme, avantaj resimţit mai
ales la construcţia interfeţei utilizator. Acelaşi program client este compilat o singură dată şi poate
rula pe toate platformele, iar funcţiile interfeţei utilizator sunt aceleaşi. Chiar dacă HTML este
independent de platformă, apar probleme când se introduce o cerere incompletă sau impropriu
formulată în cadrul unui formular. Java oferă posibilitatea de a crea “forme inteligente” (smart
form) care verifică legitimitatea cererilor de intrare ale clientului, eliminând consumurile
inadecvate de lăţime de bandă din scenariul anterior.
Din punct de vedere teoretic nu sunt restricţii cu privire la aplicaţiile de sine stătătoare, respectiv
tot ce realizează acestea poate realiza un applet rezident pe pagina Web. Se preferă appleturile
deoarece oferă securitate a structurilor construite pe un browser.Java poate utiliza structuri de date
gestionate de Security Manager şi indiferent de localizarea calculatorului poate activa sau inhiba
programe Java pentru a prelucra operaţii certe: încărcarea automată a unui program sau formă
dintr-o locaţie Internet, închiderea/deschiderea unui fişier,etc.Acest lucru este utilizat pentru a
preveni încărcarea unui applet infectat (ca şi virulsul Troian Horse), care poate crea prejudicii
acestui applet (sau sistemului local de fişiere) ori să faciliteze curiozităţi neautorizate din exterior.
Unele caracteristici de securitate sunt accesibile din caseta de dialog a meniului Security
Preferences dar nu pot fi modificate de utilizator şi nici nu pot fi alterate de codul încărcat de un
host la distanţă. Netscape ca şi alte browsere impune doar limitări extinse la appleturile ce
beneficiază de înteaga gama de facilităţi Java, dar este necesară dezvoltarea browserelor pentru a
limita extensiile de către acei utilizatori care pot relaxa restricţiile de securitate locală ale
appleturilor. Interacţiunea utilizator-utilizator prin reţea poate fi necesară pentru a avea aplicaţii
Java de sine stătătoare, care sunt implementate cu politici diferite de securitate pe Netscape, luând
măsuri specifice pentru drepturi, pentru a se asigura că nu pot apare breşe de securitate.[An_96]
Protocol handler este un progam care aparţine JDK şi permite unui browser disponibil Java
interpretarea unui nou tip de protocol. Acest lucru elimină inconvenientul browserelelor
tradiţionale, unde apariţia unui nou protocol implica dezvoltarea browserului, astfel încât să
conţină tot codul ce permite manipularea solicitărilor făcute de protocol, ceea ce implică realizarea
unui program monilitic, care consumă multă memorie RAM. Dezvoltarea browserelor disponibile
Java este modulară şi extensibilă iar browserul în sine este un program cu flux liniar, care
utilizează un set de protocoale ce reprezintă repertoriul curent ce poate fi interpretat.
Manipulatorul poate fi încărcat "transparent" astfel încât utilizatorul nu trebuie să fie preocupat de
detalii, singura sarcină fiind accea de a naviga în URL-ul propice. Protocul handler încarcă în
background tot ce trimite browserul iar browserul îşi încarcă doar handler-ele necesare realizând o
optimizare a memoriei RAM ocupate.
Content handlers are rolul de a furniza o alternativă a ideii de aplicaţii standallone, permiţând
programatorului Java să scrie codul ce extinde browserul, dându-I abiliatea de a interpreta
conţinutul inline fără a solicita apelul unor aplicaţii externe. In dezvoltarea browserelor
programatorii şi-au dat seama că nu se poate determina tipul conţinutului trimis prin MIME şi
apoi să se lege browserul de "helper-e" prezente pe calculatorul local al utilizatorului. Content
4
handler este încărcat automat la fel ca şi protocul handler, atunci când se accesează pagina Web, ce
conţine un nou tip (video, audio, conţinut special de pe Web, etc) deşi Netscape nu suportă
modelul Java pentru content handler.
Pentru a realiza o aplicaţie Java sunt necesare un editor de texte, JDK (Java Development Kit) şi
un browser disponibil Java.Indiferent de platforma utilizată, la despachetarea JDK se crează
directorul JAVA şi o serie de subdirectoare (lib - ce conţine fişierul classes.zip, bin - ce conţine
codul binar executabil pentru unelte Java memorate, javac - interpretor java de sine stătător şi
appletviewer). Acestea nu se despachetează pentru a nu consuma spaţiu de memorie pe disc. In
final se setează variabilele de mediu CLASSPATH care identifică locaţia unde se caută uneltele
Java pentru orice clasă care nu este găsită în partea standard, inclusă în JDK.
In momentul de fată sunt întâlnite mai multe tipuri de aplicaţii scise în limbajul Java:
♦ appleturi - aplicaţiile ce rulează într-un browser ce suportă Java şi respectă convenţii clar
definite;
♦ aplicaţiide sine stătătoare (standalone)- foarte uşor de realizat deoarece Java este un limbaj
de programare complet, configurat OO. Când appleturile rulează fără browser disponibil java,
aplicaţiile standalone sunt complet autorizate, putând rula pe un calculator, sau preluâd
avantajele suportului Internet oferit de Java API. Spre exemplu Sun HotJava este scris complet
în limbajul Java.
♦ appletcation sau applet-aplicaţiile care sunt tratate în context, fie ca aplicaţii grafice
standalone de către interpretorul Java, fie appleturi de către browser disponibil java, sau
appletviewer.
Aplicaţii specifice J2EE
♦ servlet - aplicaţii similare cu appleturile dar care rulează într-o aplicaţie ce rezidă pe un Web
server care suportă Java şi respectă conveţiile impuse. Practic servle-urile rezidă în aplicaţii
Web interactive şi înlocuiesc CGI-urile, mărind performanţele aplicaţiilor. Pentru a extinde
funcţionalitatea serverelor Web se folosesc Java Servlets care sunt programe Java
independente de platformă, care fac parte din componentele server-side şi care interacţionează
cu motorul servlet-ului, suportat de serverul Web, bazându-se pe protocolul de comunicaţie tip
cerere-răspuns, axat la rândul lui pe protocolul HTTP. Spre deosebire de acestea, appleturile
fac parte din componentele client-side care rulează într-un browser Web, în interiorul unei
pagini HTML sau a interfeţei grafice. Java Server Pages (JSP) extind funcţionalitatea
paginlior Web asigurând manipulare şi generare dinamică de conţinut.
♦ Obiectele de business sunt implementate ca şi enterprise beans sau componente EJB
(Enterprise Java Bean):entity beans şi session beans, driven messanger. Abordate din prisma
clientului, session beans sunt fie resurse private fie destinate clienţilor care le-au creat, fiind
privite ca şi anonime. Entity beans au în schimb o identitate unică prezentată sub forma unei
chei primare. Inafara acestor obiecte, enterprise bean defineşte în plus trei entităţi: servere,
conteinere şi clienţi. EJB există în interiorul unor conteinere care gestionează ciclul lor de
viaţă şi furnizează o serie de alte servicii.
Crearea şi editarea codului Java presupune încapsularea în clase Java. In general fiecare clasă
trebuie să meargă cu propriul fişier sursă, numit prealabil înaintea clasei (spre exemplu:
Primul.java). De fapt se pot edita mai multe clase într-un fişier sursă, depinzând de declaraţiile
public realizate şi se poate utiliza un editor standard, pentru Windows sau Unix.
5
Dacă se utilizează IDE (Java Integrated Development Environment) ca şi Symatecs Café
pentru Windows NT sau Natural Intelligence Roaster pentru Macintosh, se apelează la editorul
încorporat. IDE are avantajul creării documentului sursă, compilării, rulării şi depanării într-un
mediu încorporat.
Dacă appletul este integrat într-un fişier HTML, apelul se face din secţiunea BODY astfel:
Explicaţiile codului:
Pentru a avea acces la metodele de desenare pe ecran se importă clasa/clasele în care sunt declarate
aceste metode (Graphics), din pachetul java.awt. Pachetul este o legătură de clase aflate în relaţie.
Appletul este declarat ca şi clasa public, pentru a putea fi accesibilă interpreterului construit în
Web browser sau aplletviewer, de oricâte ori rulează.
Când codul sursă este compilat, numele fişierelor class este luat din numele clasei din codul sursă
şi nu din numele fişierului ce conţine codul sursă, (spre exemplu: Primul.class) iar dacă în codul
sursă sunt încă două clase declarate (A şi B), atunci vor apare 3 fişiere: Primul.class, A.class şi
B.class. Menţinerea paralelismului între fişierul sursă şi fişierul de ieşire este făcută uşor,
permiţând recompilarea automată a oricărei clase necesare.
Metoda paint este apelată din exteriorul appletului ori de câte ori interpreterul java are nevoie să
afişeze sau să reafişeze un applet. Atunci când este apelată, se trece obiectul în context grafic,
(clasa Graphics) ca parametru. De aceea se importă clasa Graphics pentru a furniza compilatorului
caracteristicile clasei. AWT este legat de limbajul Java şi nu este construit în acesta astfel încât ori
de câte ori g.drawString() este apelat, se apelează metoda definită în clasa Graphics pentru a
desena în context grafic. Primul parametru este şirul desenat iar ceilalţi doi sunt coordonatele
verticale şi orizontale ale punctului de unde începe linia de bază a primului caracter din şir.
Punctul este măsurat în pixeli din marginea stânga-sus a appletului pe pagină, astfel încât y creşte
ca şi cum s-ar muta în jos pe ecran.[Ramb_96]
Compilarea appletului presupune că directorul ce conţine codul binar Java este în PATH iar
uneltele JDK sunt în CLASSPATH. Comanda de compilare este:
javac nume_fişier.java
Compilatorul rulează şi apoi se întoarce la prompter iar în cazul erorilor de compilare se fac
corecţiile necesare, relansând compilatorul. De obicei apelul compilatorului se face din directorul
unde se află fişierul sursă, rezultând, conform exemplului anterior:
Primul.class
Primul.html
Primul.java
6
Dacă se doreşte vizualizarea sursei compilate se foloseşte:
javap -c Primul
şi apare reprezentarea în instrucţiuni a codul binar generat pentru acest fişier.
Execuţia appletului solicită un browser disponibil Java sau appletviewer oferit de JDK. Browserul
permite vizualizarea întregii pagini ce conţine appletul iar appletviewer vizualizează doar appletul,
ignorând comenzile HTML ce nu privesc execuţia appletului.
Exemple:
file://../Primul/Primul.html
sau appletviewer Primul.html
Dacă apelul se face din alt director se indică şi calea completă către fişier astfel:
C:>appletviewer file://../Primul/Primul.html (la Windows NT)
sau:
appletviewer file://../classes/Primul/Primul.html (la UNIX)
Observaţie:
Argumentul din appletviewer nu este fişierul.class sau .java ci mai degrabă URL-ul fişierului html,
care include protocolul utilizat pentru acest fişier (file sau http dacă este accesat la distanţă).
Aplicaţiile standalone (de sine stătătoare) sunt semnificativ diferite faţă de appleturi în termeni de
structură. Appleturile moştenesc avantajele atributelor şi comportamentului claselor din AWT şi ca
rezultat, sunt capabile să iasă "din tipar pentru a utiliza facilităţi ale GUI din AWT. Aplicaţiile
standalone pot fi utilizate cu GUI din AWT dar solicită efort suplimentar pentru a le realiza.
Toate aplicaţiile au definită o metodă main(), care indică interpretorului de unde începe execuţia
programului.
Exemplu :
class NumeClasa{
public static void main (String args[]) {
System.out.println ("Test de programare Java");
…
}
}
Daca în clasa care se defineşte se vor folosi elemente din alte clase disponibile în mediul Java, este
nesesară realizarea unui import de clase iar declaraţia de import trebuie să apară înaintea claselor
care folosesc elementele respective.
Exemplu : import NumeClasa
Metoda main() trebuie să accepte argumente din linia de comandă, sub forma şirului de caractere
args[ ] şi nu returneaza nici o valoare (tipul void). Metoda este aceeaşi pentru toate instanţele
clasei, fapt specificat prin cuvântul cheie static, şi poate fi invocată de orice altă clasa, fiind
declarată public. Funcţia main() ia parametri din tabloul de obiecte String trecute în linia de
comandă.
Apelând aplicaţia
Java ClasaIn master 9 9.5
Constatăm că tabloul are 3 elemente ("master","9", "9.5") iar dimensiunea acestuia este
dată de variabila args.lenght
System.out.println ("Test de programare Java"); echivalent cu printf din C şi cont din C++ apelând
tipărirea la consolă. Termenul de aplicaţie stand alone este greşit utilizat pentru că aplicaţia însuşi
necesită interpreterul Java pentru a o utiliza deci nu este de sine stătătoare.
7
Exemplu:
java Clasa
După scrierea unui program, se impune utilizarea unui compilator Java (javac) pentru a traduce
programul sursa într-un cod binar portabil. Acestă preia programul sursă Java scris în format
Unicode şi identifică elementele lexicale ale limbajului (tokens). Aceste elemente lexicale pot fi
identificatori, cuvinte cheie, literali, operatori şi separatori. In programul sursă Java, elementele
lexicale trebuie să fie separate între ele cu ajutorul următorilor separatori lexicali: spatiu (blanc),
sfârşit de linie (Enter), sau comentariu. Compilatorul traduce programul sursa Java într-un cod
binar, independent de calculator, neglijând separatorii lexicali.[java_1]
1.3.1.Comentariile
Comentariile sunt secvenţe de caractere care nu afectează semantica programelor, ele având rolul
de a explica secvenţe de instrucţiuni din programul sursă. In limbajul Java există trei stiluri de
comentarii:
• Stilul /* … */, utilizat iniţial în limbajul C standard, a fost preluat apoi in C++, iar acum este
disponibil în Java şi se foloseste în cazul comentariilor pe mai multe linii.
• Stilul // … a fost adaugat în limbajul C++ pentru a uşura scrierea comentariilor într-o linie,
acest tip de comentariu fiind disponibil şi în Java.
• Stilul /** … */ este nou adaugat de limbajul Java şi este utilizat pentru întocmirea automată a
documentaţiei pentru programele Java. Acesta se poate plasa numai în faţa declaraţiilor, textul
comentariului fiind copiat automat în documentaţia aplicaţiei de către generatorul automat al
documentatiei (javadoc).
8
acelaşi pachet să aibă acces la oricare din metode, fără a ţine cont de compromisul încapsularii
oferit de programarea orientată pe obiecte.
Declararea unui pachet se face prin inserarea la începutul fişierului a unei declaraţii de forma:
package nume_pachet, unde numele pachetelor sunt identificatori Java. Grupurile de instrucţiuni
package leagă clasele şi interfeţele pentru a evita conflictele şi pentru o mai bună organizare.
Spre exemplu definim clasa ecran utilizată atât de appletul aplic1 cât şi de aplic2. Acestea
se disting prin pachetul unde sunt plasate astfel:
aplic1_pack.ecran
aplic2_pack.ecran
unde aplic1_pack şi aplic2_pack sunt directoare din CLASSPATH.
Exemplul sugerează faptul că fiecare clasă şi interfaţă are nume unic, clasele şi interfeţele din
aceaşi pachet au nume unic şi pachetele la rândul lor au nume unic. Problema gravă apare când 2
persoane au clase pe acelaşi host, caz în care se recomandă numirea ierarhică a pachetelor.
Exemplu:
NumeOrganizaţie.divizie.utilizator.numePachet
Numele pachetelor este separat cu punct în componente, nefiind limitat numărul componentelor
dintr-un pachet. Fiecare componentă reprezintă un element din structura ierarhică, mapat direct pe
structura de directoare a sistemului unde se află memorat pachetul.
Instrucţiunea package este prima linie din unitatea de compilare, toate clasele şi interfeţele din
unitate fiind legate de acest pachet. O unitate de compilare poate avea mai multe clase şi interfeţe
membre, dar numai o instrucţiune package. Fiecare clasă aparţine unui pachet iar dacă o unitate
de compilare nu are instrucţiunea package este plasată în pachetul implicit (fără nume). Pentru
aplicaţii simple nu este recomandată dar dacă apar aplicaţii complexe cu multiple clase şi interfeţe
este de recomandat organizarea acestora într-un pachet, conform figurii 1.1.
1 FIRMA
CLIEN
2 FURNIZOR
TIFIRM
I
A
Considerăm pachetele Furnizori şi Clienţi (nivel 2) care corespund celor 2 subdirectoare create ca
făcând parte din directorul FIRMA (nivel 1), sub CLASSPATH. Fiecare din cele 2 subdirectoare
vor conţine unităţile de compilare (nivel 3) proprii.
Astfel includem:
package Firma.FurnizoriPack;
package Firma.ClientiPack;
9
Respectând convenţia standard de creare a pachetelor, pachetele utilizator încep cu majusculă şi li
se dă nume unic bazat e DNS (Internet Domain Name).Pachetele ce fac parte din API standard
încep cu componenta java (litere mici).
Exemple:
COM.bettersoft.AmazingJavaStuff
EDU.ryu.cs.students.phd.jontstudent.IndependentStudy
Instrucţiunea import permite claselor utilizarea numelor abreviate pentru referirea claselor şi
interfeţelor declarate în exteriorul acestei unităţi de compilare, ceea ce conduce la un cod uşor de
citit. In schimb aceasta nu permite alte avantaje decât convenţia sintactică utilă pentru
programatori. Import se poate utiliza o singură dată într-un pachet cu nume complet de calificare
astfel:
import java.applet.Applet;
şi odată plasată se poate referi clasa importată simplu: Applet fără calificare completă
java.applet.Applet.
10
Fiecare pachet sau program java importă automat toate clasele şi interfeţele exenţiale din java şi
nu este necesar importul explicit de interfeţe ca java.lang.Object, java.lang.Boolean,
java.lang.Float, java.lang.Runable,etc. Instrucţiunile package şi import nu generează cod ci au un
rol bine definit în programarea OO.
Relaţia 1-1 între clasele public şi numele fişierului sursă permite compilartorului căuarea,
verificarea şi recompilarea fişierului sursă ce este memorat, cu menţiunea că numele clasei şi
fişirului sunt case-sensitive.
Java Runntime Environment (JRE) conţine maşina virtuală Java, clasele de bază şi alte fişiere
necesare rulării, Java 2 SDE (Software Development Kit) incluzând pe lângă JRE compilatorul
javac, debugger-ul şi alte instrumente de dezvoltare. O trecere în revistă a bibilotecilor existente în
limbajul Java:
11
java.lang – aici se pot gasi clase în care sunt implementate funcţiile de bază din
mediul Java şi acest pachet va fi încărcat automat, odată cu compilatorul, fără a fi
necesară o declaraţie explicită de import. Această bibliotecă conţine clase pentru
extensia tipurilor elementare de date, pentru prelucrarea sirurilor de caractere, pentru
funcţii matematice, pentru interactiuni de baza cu sistemul, pentru fire de executie,
clase abstracte şi pentru biblioteci.
java.lang.reflect se utilizează pentru verificarea entităţilor Java, a claselor şi
obiectelor, foarte utilă în realizarea unor aplicaţii dinamice şi flexibile.
java.applet – cu rol de implementare a applet-urilor, care sunt destinate a fi
executate de un browser pentru conţinut executabil Java. Pentru a crea un applet
executabil într-o pagină Web sau rulat cu appletviewer, se poate extinde această clasa
cu metode de includere a efectelor sonore, legături cu alte pagini Web, pentru definirea
unor formate.
java.awt (Abstract Window Toolkit) – în această biblioteca se afla clasele de bază
care oferă instrumente pentru crearea elementelor de interfaţă grafica. Prin includerea
acestor elemente de interfaţă grafica, appletul va deveni o altă intefată grafica. Clasele
din acest pachet includ java.awt.datatransfer, java.awt.event, java.awt.image
java.awt.font, java.awt.color, java.awt.geom metode pentru crearea de ferestre,
meniuri, butoane, comutatoare, liste, bare de defilare verticale şi orizontale, operarea cu
fonturi, imagini 2D şi 3D, java.awt.im ce permite definirea de clase şî metode de
intrare.
java.io – conţine clase de bază pentru implementarea operaţiilor de intrare-ieşire în
mediul Java. Se pot efectua citiri de la dispozitivul de intrare, scrieri la unitatea
standard de ieşsire, citiri de pe disc sau din retea. Pentru efectuarea acestor operatii este
necesară folosirea metodelor gată pregatite pentru diferite structuri de informaţii:
fişiere, zone tampon (buffere), filtre, pipes.
java.util – este destinată funcţii speciale în mediul Java, ca suport pentru lucrul cu
date calendaristice, operaţii cu stive, operaţii cu tabele sau operaţii cu vectori. Dacă
appleturile folosesc algoritmi de compresie/ decompresie au la dispoziţie java.util.zip
şi java.util.jar
java.net – cuprinde clase de baza pentru crearea de interfeţe pentru protocoale de
reţea (telnet, ftp, nttp, WWW) şi legături de tip socket.
java.math se foloseşte pentru diverse funcţii matematice standard implementate.
java.beans este destinată creării de componente reutilizabile, denumite beans-uri.
java.rmi, java.rmi.dcg, java.rmi.registry, java.rmi.server asigură accesul la
obiectele distribuite şi facilitează acces la metode ale acestora. Pachetele sunt destizate
dezvoltării aplicaţiilor distribuite folosind Remote Method Invocation (RMI).
java.security, java.security.acl, java.security.interfaces asigură mecanismele de
securitate a softului în care sunt incluse.
org.omg.CORBA facilitează maparea API OMG CORBA în limbajul Java,
incluzând clasa ORB pe care programatorul o poate utiliza ca şi un Object Request
Broker.
javax.namimg, javax.namimg.directory, javax.namimg.event,
javax.namimg.ldap, javax.namimg.spi permit dezvoltarea metodelor de intrare care
pot fi utilizate cu orice JRE.
12
Platforma Java conţine JVM şi JAVA API
1) Java Basic API conţine applet, AWT, I/0 (sau fluxuri inclusiv serializarea obiectelor),
language (inclusiv reflection) şi utility incluzând data structures and events).
2) Java Enterprise API – asigură suport pentru database entreprise şi aplicaţiile legacy şi
conţine :
- JDBC – standard SQL
- Java RMI – invocarea la distanţă client-server;
- Java IDL – furnizează interoperabilitatea şi conectivitatea cu CORBA ;
- JNDI – interfaţa standard cu nume multiple şi servicii de directoare în entreprise.
3) Java Bean API
4) Java Security API – include criptografia, semnătura digitală, criptare, autentificare.
5) Java Foundation Clases (JFC) API este GUI pentru programare şi faţă de AWT include:
• SWING SET – reflectă un grup de componente legate în AWT, extinzându-le prin
butoane simple şi completându-le cu arii text şi arii vizuale şi folder ;
• Accesibility API – furnizează interfaţa clar în cititoare de ecou, sisteme de
recunoaştere a vocii, extinzând JFC şi AWT
6) Java Server API – permite crearea de Servleţi Java şi încorporarea în aplicaţii Web,
furnizează acces consistent şi uniform la server Web şi resursele administrative ale
sistemului ;
7) Java Commerce API – este un API pentru comerţ şi management financiar. Java Wallet –
specifică un cadrul client-side pentru cărţi de credit, debit şi tranzacţia cu bani electronici.
8) Java Media and Communication API asigură integrarea clipuri audio-video, prezentări
animate, grafice, imagini 3D, modele 3D.
- Java 2D API - set de clase pentru grafică şi imagini BD incluzând linii text şi imagini
în model unic.
- Java 3D API – pentru aplicaţii 3D şi applets
- Java Media Framework API - dă arhitectură unificată, protocolul mesajelor,
programarea interfeţelor pentru media players, capturi media şi conferinţe.
- Java SOUND API dezvoltă 32 chanel audio cu calitate bună şi asigură control MIDI al
sintezei sunetului.
- Java Telephony API – interfaţă portabilă în aplicaţii computer –telephony.
- Java Speech API – cross-platform interface, ce permite controlul recunoaşterii,
sistemului de dictare şi sinteza vorbirii.
9) Java Management API – set de obiecte extensibile şi metode destinate reţelelor, serviciilor
de management în reţele eterogene.
10) Personal Java API – destinată conectării la distanţă a dispozitivelor personale: mobile,
calculatoare, hand-held, boxe Set-top, console de jocuri, smart phone.
11) Embeded Java API - pentru dispozitive complexe ca: mobil, pagere, instrumentare de
control al proceselor, periferice de control, rutere reţea şi switchuri reţea.
13
Dacă politica de securitate permite, API poate fi folosit la:
- descoperirea informaţiilor despre câmpuri, metode şi constructori din clasele încărcate;
- construcţia de noi clase şi noi tablouri;
- accesul şi modificarea câmpurilor, obiectelor şi claselor ;
- accesul şi modificarea elementelor de tablou ;
- invocarea metodelor obiectelor şi claselor.
Spre exemplu Java Beans şi Entreprise Java Beans, solicită acces la public members pe un obiect
ţintă iar Java ObjectSerialization are nevoie de acces la toţi membri declaraţi pentru o clasă dată.
Java Reflection API conţine :
• Class – furnizând instanţe pentru Field, Method şi Constructor;
• Field, Method, Constructor – furnizează informaţii reflexive despre membri asociaţi,
implementează intefaţa Member. Numai JVM poate crea instanţe ale acestei clase.
o Field - poate fi o clasă statică sau o instanţă variabilă;
o Method – metodă abstractă, metodă (statică), a clasei sau instanţă a metodei;
• Array- furnizează metode de construcţie dinamică şi acces la tablouri. Sunt clase finale şi de
aceea neinstanţiabile.
• Modifier – permite modificarea informaţiilor (static şi public) despre clase şi membri. Sunt
clase neinstanţabile.
Security Model
Java Security manager are 2 nivele de verificare :
- metodele din clasa Class ce dau acces reflexiv sau set de membri surse pentru
instanţele Field Method, Constructor. Aceste metode leagă verificările de securitate
către system security manager:
- o dată ce system security manager dă acces la membri, orice membru, reflectat poate
apela pe obiecte Java (protected, default la package şi clase private pentru membri).
Pentru a folosi clasele din bibliotecile de mai sus este posibil importul pachetului în întregime,
folosind declaraţia de import corespunzătoare.
Exemple:
import java.lang.*;
import java.applet.*;
Dacă se doreşte includerea selectivă a unor clase, pentru a reduce dimensiunile programului binar,
se precizează în declaraţiile respective.
Exemple:
import java.awt.Image;
import java.net.URL;
Prezentăm câteva detalii ale clasei applet, destinată a fi utilizată în realizarea unei pagini HTML,
care pune accentul mai ales pe o interfaţă grafică atractivă şi interactivitate mare.
In proiectarea de applet-uri trebuie urmărit scopul aplicaţiei respective şi modul în care acesta
poate fi atins de potenţialii utilizatori pentru că un applet Java este mai mult decât un cod care să
realizeze operaţii elementare de calcul şi afişare - un mod de realizare a interfeţei cu utilizatorii.
Biblioteca de clase applet conţine peste 40 de clase şi interfeţe pentru dezvoltarea de programe de
tip applet iar functia de baza a acestora este de a realiza, prin intermediul metodelor obţinute, un
control asupră applet-urilor din mediu.
Clase cum sunt Basicstyle, Document ajută in controlul vizualizarii documentelor HTML şi a
oricarui applet la care se face referire din aceste documente. Clasa applet este superclasa pentru
14
toate applet-urile nou create şi pot fi vizualizate de browser iar un applet creat moşteneste toate
metodele clasei applet, care constau nu numai din clasa applet şi din metodele superclaselor
acestei clase, care fac parte din awt (nu din clasa applet).[Naugh-96]
Setul de caractere Unicode, care se foloseşte acum în locul setului de caractere standard ASCII
permite reprezentarea caracterelor pe 16 biti, în timp ce setul de caractere ASCII foloseşte numai
8 biti. Cele doua subseturi de caractere sunt compatibile, vechiul standard ASCII fiind un subset al
setului Unicode. Această necesitate de extindere a setului de caractere - determinată de nevoia de
a reprezenta mai mult de 256 de caractere - a apărut din dorinţa de a reprezenta literele ce există în
diferite alfabete de pe glob.
Cuvintele cheie, sau cuvintele rezervate, sunt identificatori utilizati în limbajul Java într-un mod
bine precizat prin gramatica limbajului, fiind interzisăa utilizarea lor în alte scopuri. Un
identificator este o secventă de litere, cifre şi alte caractere în format Unicode, primul caracter
fiind obligatoriu o literă, un caracter underscore (_) sau simbolul dolar ($). Aceştia trebuie să fie
diferiţi de cuvintele cheie şi se utilizează pentru a desemnă variabile, clase şi metode.
Literalii se folosesc pentru a desemna valori constante în cadrul unui program Java şi au la baza
doua categorii de date: numere şi caractere. Literalii numerici se împart în două subcategorii:
întregi ( cu format: zecimal, hexazecimal, octal) şi flotanţi (numere cu parte fracţionară). Un
caracter literal se referă la o singură valoare din setul de caractere Unicode, în timp ce un şir de
caractere se referă la o succesiune de unul să mai multe caractere. Pe lângă aceştia mai există
caracterul boolean, literal considerat numeric pentru compatibilitate cu limbajele C şi C++, iar
valorile de adevar true şi false în C şi C++, sunt reprezentate prin valorile intregi 1 şi 0.
Constantele literale pot fi exemplificate astfel:
Intregi
5 întreg
5l (intreg scurt)
5L(întreg cu tip lung)
O5 întreg octal
OxaBa (hexazecimal case-sensitive)
Double şi Float
4.5, 6.7d, 7.8D - constante duble
3.4E8 - constante duble cu exponent
6.7f sau 6.7F - tip float
Booleene: true, false
Constante caracter (Escape)
\ continuare în linia următoare
\n linie nouă
\t tab orizontal
\r carriage return
\f form feed
\\ backslash
\' apostrof simplu
\" apostrof dublu
15
\ddd formă octal
\xdd formă hexa
\uddd caracter unicode
"exemplu" sir de caractere
Tipulile întregi sunt tip de dată şi pot fi caracterizate: byte ( 8 biţi), short (16 biţi), int (32 biţi) şi
long (64 biţi) dar spre deosebire de clasă nu există un comportament asociat tipului întreg.
Clasa Integer din java.lang are declaraţia:
class IntegerClass // conţine variabile intregi
//si set de metode de activare
16
int MAX_VALUE;
int MIN_VALUE;
public static String toString(int i) //metoda
{…}
}
Spre deosebire de C sau C++ unde dimensiunea diferitelor tipuri de primitive este dependentă de
calculator la Java tipurile de primitive au dimensiune fixă, indiferent de hard-ul unde rulează
maşina virtuală Java.
Tipurile întregi sunt cu semn, fiecare variabilă declarată întreg putând lua valori +/- iar tipul
determină nivelul valorii şi proprietăţile aritmetice ale variabilei ce-l deţine. Dacă o valoare
depăşeşte dimensiunea de reprezentare se trunchiază automat la modulo rang.
Exemplu:
Dacă byte b=-129; => b=-129-(-256)=127
Dacă byte b=128; => b=-128-256=128
Tipul Floating-Point (IEEE 754) permite reprezenarea float (32 biţi) şi double (64 biţi) implicit
fiind double. Pentru testarea depăşirii superioare sau inferioare se utilizează variabila NaN (not a
number).
Tipul caracter este definit conform reprezentării Unicode la 16 biţi/caracter (spre deosebire de C
unde se reprezintă la 8 biţi/caracter) iar la iniţializare se foloseşte apostof simplu.
Exemplu:
char a, b='parola', c='\n';
Tipul boolean are două valori (true sau false) iar maşina virtuală Java îl gestionează în mod
propriu, manipulând biţi individuali ai caracterelor întregi, astfel încât se pot declara mai multe
variabile boolean, fiecare solicitând un bit. In Java valorile booleene nu sunt numere şi nu pot fi
convertite sau operate ca întregi.
Tablourile sunt liste de elemente separate prin virgulă, crete cu operatorul new.
Exemple:
int col[ ]= new int [3];
int [ ]col= new int [15];
int col[ ]; // echivalent cu int [ ] col
…
col = new int[3]; //alocarea dinamică a memoriei
Variabila col are lungime 3 (întreagă) indexată [0-2] şi poate beneficia de alocare
dinamică ceea ce permite programatorului să rezerve spaţiu optim pentru memoria alocată.
Exemple:
int n=2;
double d=5.5;
double Dtablou1[ ]=new float[n+1] //corect
double Dtablou2[ ]=new float[d] //eronat
double Dtablou3[ ]=new float[int(d+2)] //corect
//iniţializarea elementelor
Dtablou[0]=0.1;
Dtablou[1]=0.12;
Dtablou[2]=-0.13;
17
//tablouri multidimensionale
int mat1[ ] [ ] = new int [2] [3];
//sau
int [ ] [ ]mat1 = new int [3] [5];
La tablourile multidimensionale precizarea ultimei dimensiuni este opţională:
int [ ] [ ]mat1 = new int [3] [ ];
Este necesară însă definirea celei de a n-a dimensiuni prealabil utilizării ei:
Exemplu:
for (i=1, i<3, i++) {
mat1[I]=new int [5];
}
Alocarea memoriei pentru tablouri se face tot cu operatorul new, cu excepţia iniţializării în
timpul declarării:
char litere[ ]={'a','j', 'p','l','m','n'};//tablou de 6 elemente
Operatorul new este utilizat pentru memorarea oricărui tip compus (tablou, obiecte din
clasă, interfeţe) iar alocarea explicită pentru tipurile de bază nu este necesară.
Exemplu:
char a; // nu trebuie new
char char Tab1[ ] = new char[3];
In timpul compilării se crează clasa tablou are marchează clasa compilată şi este un obiect
ce nu trebuie subclasat explicit (figura 1.2).[Hoff_96]
Obiect
Array
Este deja cunoscut faptul că în C pointerul este adresa unei variabile, orice porţiune de memorie
fiind accesibilă prin pointeri. Pointerul aritmetic oferă unul din cele mai puternice concepte C
oferind posibilitatea calculelor (+,-,/,*) şi putând fi utilizat la accesarea memoriei. In Java s-a
elinminat accest concept recunoscută fiind periculozitatea utilizării eronate a pointerilor aritmetici
şi s-a introdus handler (manipulator).[Chan_95] Un handler Java este asociat cu un obiect şi nu cu
o adresă.
Exemple:
int col [ ];//handler null
18
Instrucţiunea precedentă alocă memorie pentru cei 4 manipulatori (mat1[0], mat1[1], mat1[2],
mat1[3]) şi fiecare punct la null. Alocarea dinamică pentru tabloul actual se realizează cu secvenţa:
for (i=1, i<3, i++){
mat1[I]=new int [3];
}
matricea mat1 este:
0 1 2...
3
int int
int int int int int int
int
int int int
2
1.4.3. Operatori
Operatorii sunt folosiţi pentru a realiza anumite operaţii elementare între obiecte, fiecare operator
joacă şi rolul de separator între două elemente lexicale şi au prorpietăţi similare cu cei din C:
precedenţa (ordinea în care sunt interpretaţi) şi asociativitatea (direcţia de evaluare). [Laur-98]
19
Operatori Precedenţa Asociativitatea
!= Test not equal
& Si binar
^ XOR binar
| OR binar
&& And
|| OR
?! Operator ternar condiţional Dreapta la stânga
=,+,=,- Atribuiri
=,*=,/+,
%=,&=,^=,|
=,<<=,>>=
a operand b Echivalent cu a=a operand b
a+=b echivalent cu a=a+b
Dacă rezultatul calculelor este de tip întreg şi operandul este long se realizează conversia la tipul
long, înrest rezultatul este int.
Exemplu:
class Test1{
public static void main(String args[ ]) {
short i=10, j=11,k;
int m;
k=i+j; //eroare, trebuie forţată explicitarea
k=(short) (i+j); // k=21
m=i+j; // m=21
}
}
Exemplu:
class Test2 {
public static void main(String args[ ]) {
Integer i= new Integer(0);
int overflowN=i.MAX_VALUE+1;
//valoarea maximă posibilă
System.out.println ("valoarea minimă posibilă=" +i.MIN_VALUE);
System.out.println ("valoarea care depăşeşte="+overflowN);
if(i. MIN_VALUE=overflowN)
System.out.println ("truncherea");
}
}
Rezultatul programului:
20
valoarea minimă posibilă=-2147483648
valoarea care depăşeşte=-2147483649
truncherea
Operatorii acceptaţi pentru tipuri întregi sunt =,-,*,/,%,++,-- şi op=
Operatorii ~,<<,>>,>>>,&,^,| iau operanzi de tip întreg şi întorc valori întregi iar operatorii
<,>,<=,>= iau operanzi de tip întreg şi întorc valori booleene. Pentru tipurile de virgulă flotantă
sunt acceptaţi operatorii de tip întreg mai puţin cei la nivel de bit. Definiţia modulo este diferită de
cea dată pentru întregi. Dacă x şi y sunt double sau float:
x%= x-Math.rint(x/y)*y
Dacă numărul are parte fracţionară 5 este convertit la întregul superior.
Math.rint(7.0/2.0)= Math.rint(3.5)=4
Spre deosebire de tipul întreg la cele float depăşirea superioară generează Inf(infinit) şi cea
inferioară generează 0 iar rezultatul împărţirii cu o generează Inf.
Exemple:
double depsup=1.0/0.0 // overflow
double depinf=27/0.0 // underflow
Operatorii relaţionali se utilizează cu precauţii în comparaţii pentru că dacă a<b este fals, nu
implică a>=b sau a!=b nu înseamnă a>b || a<b
NaN este un număr fără semnificaţie, fără semn şi nu poate fi comparat nici măcar cu el însuşi,
pentru că rezultă din calcule.
Exemplu:
double a=0.0/0.0;
if (Double.isNaN(a))
System.out.println ("a este NaN");
else
System.out.println ("a nu este NaN");
double b=a;
if (Double.isNaN(b))
System.out.println ("b este NaN");
else
System.out.println ("b nu este NaN");
if (a==b)
System.out.println ("a==b");
else
System.out.println ("a!=b");
Rezultatul obţinut:
a este NaN
a!=b
Operatorii de tip boolean sunt relaţionali sau logici şi folosesc şi produc valori booleene.
Exemplu:
return((mask>0)?true:false;
echivalent cu:
21
if (mask>0)
return true;
else
return false;
Transformarea subclaselor şi superclaselor este permisă dar deşi o instanţă poate fi transformată în
superclasă, transformarea unei subclase generează erori de execuţie. Interpreterul Java verifică
dacă subclasa este extensie a unei superclase transformate şi dacă un obiect nu este instanţă de
subclasă (sau una din subclase) se rulează rutina Class CastException. Expresiile sunt combinaţii
de variabile, literali şi operatori ce determină un rezultat. Atribuirea este procesul de memorare a
valorii iar variabila căreia I se atribuie se numeşte variabila stângă. Separatorii Java din expresii
sunt ( ), { }, [ ] ;,. Ordinea de evaluare este dată de dictată de precedenţele operatorilor şi de
separatorii incluşi.
22
scurtcircuitarea evaluărilor astfel încât pentru un operator de tip && la prima evaluare de expresie
falsă renunţă la evaluarea expresiei rămase. Pentru o mai bună optimizare, dacă în compilare se
identifică valoarea falsă întotdeauna, la o evaluare de expresie dintr-un if, nu se generează cod
pentru ramura true.
1.5.2. Instrucţiunea IF
if <expl1> {
Instrucţiuni1 ;
[else } if <expl2> {
instrucţiuni2;
}else {
instrucţiuni3 ;]
}
switch (expr) {
case const1: instrucţiuni1;
break;
case const2: instrucţiuni2;
break;
…
default: instrucţiuniN;
}
Instrucţiunea switch este în realitate echivalentul unui if imbricat, unde:
expr - este o expresie tip caracter, byte, short sau int;
const1, const2, constN - valori constante ce sunt asociate execuţiei grupurilor
de instructiuni;
instrucţiuni1, instrucţiuni2, … - grupuri de instrucţiuni care se execută
condiţionate de const1, const2, constN;
default -- grup de instrucţiuni (instrucţiuniN) care se execută dacă nici una din
condiţiile de const1, const2, constN nu este îndeplinită.
Exemplu:
import java.io.*;
class UnDictionar {
public static void main (String args [ ] ){
char alege;
System.out.println ("Selectati una din lectiile de instruire:");
System.out.println ("AWT");
System.out.println ("API");
23
System.out.println ("Corba");
…
System.out.flush();
try {
switch (alege=(char)System.in.read();
{
case "W": System.out.println ("am selectat AWT");
break;
case "P": System.out.println ("am selectat API");
break;
case "C": System.out.println ("am selectat Corba");
…
default: System.out.println ("Selectie eronata");
}
catch(IOException e)
{ System.out.println (e.toString());
}
}
}
Instrucţiunea while permite execuţia grupului de instrucţiuni până când expresia logică
expl evaluată este adevărată.
Exemplu:
int i;
boolean test=false;
while (test == false){
i=(int)(Math.random()/500);
}
if (i%2==0)
test=true;
}
1.3.5. Instrucţiunea do
do {
instrucţiuni;
}
while (exprl) ;
24
i=(int)(Math.random()/500);
}
if (i%2==0)
test=true;
}
while (test == false)
Instrucţiuea for (de ciclare) execută grupul de instrucţiuni, pornind de la expresia1, până
când este îndeplinită condiţiă dată de expresia booleană, cu pasul (incrementul) dat de
expresie2.
Exemplu:
int k=7;
int []vo= new int[k];// vector
for (int i=0, i<k, i++) {
vo[i]=(int)(Math.random()/100);
}
Exemplu:
public int cautMatrice (int [ ] [ ] matrice, int [ ] tinta){
int sumaMatr=0;
for (int nTinta=1, nTinta<tinta.length, nTintai++) {
nouaTinta:
for (int i=o, i<matrice.length,i++) {
for (int j=0, i<matrice[0].length, j++) {
sumaMatr++;
break nouaTinta;
}
}
}
return sumaMatr;
}
25
Instrucţiunea continue este similară cu break şi se foloseşte în corpul instrucţiunilor
iterarive ca: while, do, for, mai puţin switch.In absenţa etichetei controlul este redat la
sfârşitul blocului unde se află aceasta. Dacă este plasată într-un bloc finally se execută
blocul finally şi se predă contolul la sfârşitul blocului. Intr-o buclă do sau while, expresia
booleană este evaluată imediat după continue, iar dacă este plasată într-o buclă for, înaintea
expresiei booleene se execută expressionexe_after_one_iteration. Dacă instrucţiunea este
etichetată, eticheta trebuie să fie inclusă în instrucţiuni iterative, altfel se trece controlul la
cel mai apropiat bloc iterativ.
Exemplu:
class Lot ;
int numMatrice [ ];
//constructorul
Lot(int [ ]nP){
//alocarea memorieii
NumMatrice= new int[nP];
}
//generare numere aleatoare
public void pick(){
int num;
for (int i=0, i<nP.length) {
//I se incrementează dacă numărul din curenta iteratie nu a fost //extras
num=(int)(Math.random()*33)+1;
if (duplicat(i,num)) {
//num se atribuie lui numMatr si i nu se incrementează
continue;
}
numMatr[i++]=num;
//aici continua
}
}
//intoarce true daca numarul a fost extras
private boolean duplicat(int nP, int num) {
for (int i=0, i<nP, i++) {
if (numMatr[i]==num)
return true;
}
return false
}
}
}
26
forţa întoarcerea, ca mod de prevenire a execuţiei restului metodei, ceea ce salvează nivelul
indentărilor, permiţând un cod uşor de citit (în aceste cazuri este inclusă în if).
Exemplu:
void Lot (int x) {
if (x<=20) {
return;
} else return;
void altLot (int x){
if (x>20) {
return;
}
}
In cazul în care metoda sau constructorul este declarat cu tip de valoare întoarsă, instrucţiunea
return trebuie să întoarcă tipul corespunzător declaraţiei. Dacă return este inclus într-un bloc try,
urmat de finally, instrucţiunile finally din bloc sunt executate înainte de a reda controlul
apelantului.
Crearea şirurilor în Java se realizează cu operatorul new iar concatenarea lor cu append
Exemplu:
String d = new StringBuffer ("Am obtinut");
.append (calif)
.append ("la testul de baza")
.toString();
27
Point (int x, int y);
this.x=x;
this.y=y;
}
public String toString() {
return "punctul ("+x+","+y+")";
}
}
class DemoSir() {
public static void main ( String args [ ] ) {
Point p = new Point (20,30);
System.out.println("Obtinem"+p);
}
}
Versiunea clasei Point include suprascrierea metodei toString din object, formată dintr-un şir
conţinând valorile curente (x,y) ale instanţei Point. Ieşirea este dată de:
Obtinem punctul (20,30).
Metoda getChars nu include char la sfârşitul indexului şi este foarte utilă în special la exportul
String într-un mediu ce nu suportă 16-biţi Unicode. Protocoalele Internet folosesc 8-biţi ASCII
pentru text. Faţă de această metodă, apar particularităţi de xtragere a caracterelor la metodele:
toCharArray, care întoarce un tablou de caractere pentru întregul şir;
getBytes care ia caractere dintr-un tablou de biţi, în ordinea apariţiei acestora şi este
similară cu getChars cu deosebirea că al treilea parametru este tablou de byte.
28
Comparaţia prin egalitate la tipul string se realizează cu metodele equal sau equalIgnoreCase.
Metoda regionMatches este folosită pentru compararea unei regiuni specifice din interiorul unui
şir cu o altă regiune specifică din alt şir, ignorând sau nu UpperCase şi LowerCase. Prototipul
funcţional este:
boolean regionMatches (int tooffset, String altsir, int aoffset, int len);
boolean regionMatches (boolean ignoreCase, int tooffset, String altsir, int aoffset, int
len);
unde int tooffset - regiunea specifică
String altsir al doilea şir
int aoffset - regiunea specifică din al doilea şir
int len - dimensiunea de comparaţie.
Cele două şiruri sunt comparate pe dimensiunea len caractere, începând de la cele două offset-uri
specificate. Pentru verificări speciale impuse şirurilor se folosesc două metode
pereche:startsWith, care verifică dacă şirul începe cu parametrul transmis şi endWith, care
verifică dacă şirul se termină cu parametrul transmis şi sunt deosebit de utile în programarea
appleturilor.[Chan_95]
Exemple:
"Categorie.endsWith("ie") returnează true
"Categorie.startsWith("Cat") returnează true
"Categorie.startsWith("eg",3) returnează true
Egalitatea dintre şiruri poate fi testată fie cu metoda equal, fie cu operatorul ==, deosebirea fiind
fundamentală deoarece metoda equal compară caracterele din interiorul tipului String pe când
operatorul == compară două referinţe obiect.
Exemplu:
class DemoEgalSir() {
public static void main ( String args [ ] ) {
String s1= "Exemplu de utilizare a metodei equal");
String s2= new String(s1);
System.out.println(s1+"egal cu sirul s2"+s2+'->"+ s1.equal(s2));
System.out.println(s1+"==cu sirul s2"+s2+'->"+ (s1==s2));
}
}
In exemplul de mai sus, s1 este creat ca instanţă de şir iar s2 este creată prin construtor String care
ia intrarea şi o întoarce caracter. Fiind obiecte distincte ele nu sunt == dar sunt equal. Ordinea într-
un şir este determinată cu metoda compareTo.
Exemplu:
class DemoBubbleSortlSir() {
static String arr[ ] = {"acum", "facem","ordonare", "prin", "comparatie", "de",..}
public static void main ( String args [ ] ) {
for (int j=0, j<arr.length, j++) {
for (int i=0, i<arr.length, i++) {
if arr[i].compareTo(arr[j])<0) {
String t= arr[j];
arr[j] = arr[i];
29
arr[i]=t;
}
System.out.println(arr[j]);
}
}
}
Căutarea în şir se poate face cu indexOf sau lastIndexOf care sunt supraîncărcate în orice mediu,
pentru a căuta caractere sau subşiruri, începând de la offset până la sfârşitul sursei String.
Exemple de utilizare:
int indexOf ( int ch);
int lastIndexOf ( int ch);
int indexOf ( String str);
int lastIndexOf ( String str);
int indexOf ( int ch, int index); - cautare de la indexul precizat
int lastIndexOf ( int ch, int index);
int indexOf ( String str, int index );
int lastIndexOf ( String str, int index);
Această clasă oferă o gamă diversificată de metode necesare efectuării operaţiilor de bază la
nivelul tipurilor int, double, float, etc.Fără a intra în detalii de funcţionare, cunoscute de altfel la
limbajele de generaţia a treia şi a patra, prezentăm câteva funcţii utile:[Naugh_96]
30
pow(double x, double y);- puterea unui număr yx
Exemplu:
x=pow(2,3); //x=8
exp (double x);
log (double x);
sqrt (double x);
Random este clasa ce generează 5 tipuri de numere aleatoare care pot fi extrase din obiectul
Random:[java_1]
int, uniform distribui în rang int, extras cu metoda nextInt;
long, uniform distribui în rang long, extras cu metoda nextLong;
float, uniform distribui în rang float, extras cu metoda nextFloat;
double, uniform distribui în rang double, extras cu metoda nextDouble;
nextGaussian, care întoarce distribuţia Gaussiană double, centrată 0.0, cu deviaţie standard
de 1.0 (curba clopot- bell curve);
Clasa Date este utilizată la reprezentarea orei şi/sau timpului şi are câţiva constructori de bază:
Date(year, month, date);
Date(year, month, date, hours, minutes);
Date(year, month, date, hours, minutes, seconds).
31
Obiectele Date pot fi convertite în String prin metoda toString sau toLocalString respectiv
toGMTString. Dacă se doreşte obţinerea unui offset în minute faţă de GMT se foloseşte
getTimezoneOffset.
Runtime este clasă încapsulată în procesul de rulare a interpreterului Java. Practic nu se poate
instanţia Runtime, se pot doar referi obiecte ce rulează prin metoda statică Runtime.getRuntime.
Sunt câteva metode de control a stării şi comportamentului maşinii virtuale prin
SecurityException. Metoda exit (int cod) dă o ieşire cu codul erorii întâlnmite la execuţia
programului.[java_8]
Managementul memoriei se face prin GC iar metodele totalMemory() şi freeMemory() din
Runtime dau memoria totală ocupată respectiv memoria liberă.
Metoda exec() permite apelul altor programe cu nume specificat la fel ca şi parametri de intrare.
Problema este că programul se execută independent de sistem. Metoda exec() întoarce obiectul
Process care poate fi utilizat la controlul modului în care programul java interacţionează cu noul
proces executabil.
Exemplu:
class ExeDemo {
public static void main (String args [ ] ) {
Runtime s = Runtime.getRuntime();
Process p=null;
Sting cmd[ ] = {"notepad", "java/lang/Runtime.java"};
try {
p=r.exec(cmd);
} catch (Exception e) {
System.out.printn ("eroare la execuţie"+cmd[0]);
}
}}
Procesul returnat de exec poate fi manipulat după ce noul program a început rularea şi se poate
distruge procesul cu metoda destroy().
Metoda waitfor() determină aşteptarea programului până când a terminat subprocesul iar metoda
exitValue() întoarce valoarea de ieşire din subproces ( număr natura sau 0 dacă ieşirea a avut loc
fără probleme).
2.1.Clasele Java
2.1.1. Caracteristicile claselor în Java
Arhitectura limbajului Java este bazată pe metodologia orientată spre obiecte. Inafară de tipurile
fundamentale (int, float, char, boolean), în Java totul se reprezintă prin obiecte denumite clase.
Prin încapsularea caracteristicilor limbajului în clase, Java devine un mediu extensibil în care
programatorii pot folosi rutinele din alte programe sau aplicaţii. Limbajul Java evalueaza structura
32
claselor în mod dinamic în momentul executiei şi datorită dinamicii, bibliotecile de clase pot fi
reutilizate cu uşurinţă.
Clasa Object
Clasa 1 Clasa n
Limbajul Java pune la dispozitie metode şi operatori pentru crearea variabilelor de clasă, dar este
necesară definirea unei metode de creare a clasei şi ulterior se poate crea o altă clasa că şi copie a
obiectului (adică a definiţiei de clasă) utilizând operatorul new. [Lema_98]
Metoda de creare are acelaşi nume cu numele clasei şi nu returnează nici o valoare dar prelabil
apelului metodei de creare trebuie alocată memoria necesară instanţierii şi initializată cu valorile
specificate sau implicite. Pentru a crea o clasă care foloseşte o altă clasă (initial construită),
este necesară o instanţiere a clasei cu operatorul new.
Exemplu:
clasa varClasa= new clasa()
unde clasa este numele clasei, varClasa este numele variabilei care se declară, iar clasa este
constructorul variabilei respective. In continuare, variabila varClasa va putea conţine o referintă la
un obiect de clasa clasa sau la un obiect derivat din clasa creată.[Lema-96]
La executia unui applet sau o aplicaţie de sine stătătoare într-un browser, în mediul Java se
creeaza o instanţiere (adica o variabilă) a clasei încărcate. Toate clasele in limbajul Java sunt
descendente dintr-o clasa superioară numită Object, clasele proprii putând fi create prin derivare
sau moştenire din Object sau din orice altă clasa, care la rândul ei moşteneste direct sau indirect
clasa Object. In figura de mai jos se prezintă structură ierarhică a claselor din mediul Java.
Pe fiecare ramură din ierahia de mai sus, subclasa moşteneşte proprietăţile superclasei şi astfel,
chiar dacă o clasă nu succede direct din clasa Object, ci în urma unei şir de succesiuni, această
33
clasă este totusi o subclasă a lui Object. Clasa Object este singură clasa care nu are o superclasa şi
poate fi considerată ca un tip fundamental dar dacă pentru clasă nu se declară explicit ascendentul,
în mod implicit acea clasă este o succesoare directă a clasei Object.[Naugh-96]
}
Dacă se declară o clasa cu public class NumeClasa, această clasă nou creată va fi o subclasă a
clasei obiect, deoarece nu este specificată în declaraţie clasa din care este derivata. Clasa se
declară public pentru ca apoi să fie plasată intr-un pachet şi exportata. In cazul in care clasa este
declaraţă in acelasi fişier in care este şi utilizata, declaraţia public nu este necesară.
După crearea unei clase este necesară definirea variabilelor clasei. Pentru fiecare variabila din
interiorul unei clase, se va specifica tipul precum şi identificatorul variabilei după modelul: tip
nume. In clase se includ şi metode, pentru a realiza anumite calcule, iar rezultatul să poată fi
returnat sub forma unei valori de tipul tipReturnat, conform declaraţiei de metodă:
TipReturnat nume(parametru1, parametru2,…) {
// corpul funcţiei
}
In alte cazuri o metoda indică faptul ca s-au incheiat cu succes anumite operaţii, nefiind necesară
returnarea unui rezultat iar o astfel de metodă (care nu returnează o valoare în urma execuţiei), are
în definiţie cuvântul void.
Alături de metoda de creare există şi o metoda de finalizare care are rol de a închide fişierele care
au fost deschise şi de curăţare a obiectului pentru care este finalizator, pentru ca ulterior
colectorul de reziduri să elimine obiectul din memorie. Nu există nici o garanţie că limbajul Java
va invoca metoda de finalizare definită, considerand metoda ca şi o optimizare a codului, motiv
pentru care este indicat ca aplicaţia să nu depinda prea mult de această metodă pentru a evita
anomalii în execuţie.
Pentru a se şterge un obiect, trebuie apelată metoda de finalizare care distruge variabila
respectivă, şi ulterior se apeleaza colectorul de reziduri. In limbajul Java nu este necesară apelarea
în mod implicit a distrugerii unei variabile de clasă, deoarece sistemul are un mecanism de
colectare a rezidurilor care descoperă situaţiile în care o variabilă de clasa ( sau un obiect) nu mai
este referită şi o distruge automat. Se recomandă însă ca metoda de finalizare să fie apelată
explicit pentru a nu apărea manifestări accidentale în execuţie.
Aceesibilitatea clasei şi informaţiile despre variabilele şi metodele definite în clasă sunt date prin
modificatorii clasei. Dacă aceştia sunt omişi în întregime, obiectele din clasă sunt definite şi
accesate de alte clase din acelaşi pachet iar această clasă poate avea la rândul ei subclase în acelaşi
pachet. Sunt cunoscuţi trei modificatori de clasă: public, abstract şi final.
O clasă declarată public este global accesibilă, ceea ce însemnă că orice clasă definită în acelaşi
pachet poate accesa obiectele din această clasă. Dacă nu este declarată public, accesibilitatea se
limitată la nivelul pachetului sau claselor din care derivă. Dacă o clasă este declarată public, ea
34
trebuie să fie publică în codul sursă şi mai mult, numele fişierului sursă trebuie să fie acelaşi cu
numele clasei public, cu extensie java.
Exemplu
public class Clasa1 {
Corpul clasei
…}
Observaţie:
In fişierul Clasa1.java există doar o clasă declarată public.
In general se declară o clasă public, atunci când se doreşte a fi global accesibilă, astfel încât orice
applet public permite utilizatorului care navighează în pagină, să îl execute. Suplimenar se pot
declara pachete relative la clase, ce au intenţia de a furniza funcţionalitate generală, adesea pentru
a fi reutilizate în programe diferite. Pentru a face clasele accesibile în exteriorul pachetului, acestea
trebuie declarate public. Totuşi nu toate clasele dintr-un asemenea pachet pot fi utilizate în
exterior; unele sunt destinate doar uzului intern deşi se poate declara o clasă public, care poate fi
invizibilă în exteriorul pachetului.
O clasă abstract este cea care conţine una sau mai multe metode abstract. Uneori se declară o
metodă în clasă fără a preciza detaliile interne ce presupun metode de implementare diferite pentru
fiecare subclasă. Spre exemplu, dacă declarăm clasa java.awt.Image, are sens să se definească
metoda de afişare pentru fiecare tip de format al fişierului (JPEG,GIF,BMP, etc.) pentru că este
cunoscut faptul că există în plus informaţii legate de dimensiunea fişierelor, care determină
implementări diferite. Intr-un asemenea caz este necesară structurarea definiţiilor acestei metode
ale subclaselor. Pentru a realiza acest lucru, se lasă definiţia blank şi se declară metoda abstractă.
Dacă o clasă conţine una sau mai multe metode abstract, atunci clasa însuşi se declară abstract,
pentru a evita erori de complilare. Nu trebuie instanţiat direct un obiect din clasa abstract. Pentru
a-l utiliza este necesară crearea unei subclase ce include definiţiile pentru metodele lăsate blank în
clasa abstract, iar această clasă trebuie apoi instanţiată.
Clasele abstract permit implementarea polimorfismului pur, în care aceste clase abstract nu pot fi
ele însele instanţiate ci au rol de a servi ca şi clase de bază pentru un grup de clase aflate în relaţie.
Aceste clase de bază sunt generice astfel încât este greu sau aproape imposibil de definit detaliile
sau comportamentul acestora. Delatiile sunt lăsate subclaselor şi fiecare subclasă implementează
comportamente diferite. De aceea se începe fără implementări finalizând apoi cu implementări
distincte, proprii fiecărei subclase. Clasele abstracte se pot declara public sau fără acces implicit,
caz în care sunt vizibile doar în interiorul pachetului.[Ramb_96]
Clasele final nu pot fi subclase, sunt opuse lui abstract, motiv pentru care nu pot fi simultan final
şi abstract pentru că generează erori de complilare. Există două motive pentru care se folosesc
aceste clase: eficienţa şi posibilitatea de a extinde metodele definite în clasele părinte. De aceea
când o metodă dintr-o clasă este apelată, nu este posibil să se determine la momentul compliării ce
versiune a metodei se execută, deoarece versiunea metodei definită în clasă poate fi extinsă într-o
subclasă, cu acelaşi nume şi tip de parametri. Acest lucru trebuie determinat dinamic, în timpul
execuţiei de fiecare dată când se rulează acea secţiune de cod, depinzând de segmentele generate
când obiectul este instanţiat.
35
De fiecare dată când se fac determinări, se poate solicita încărcarea unei clase ce nu a fost anterior
rezidentă în memorie. Aceste performanţe se asociază cu costul încărcării clasei. Cum o clasă
finală nu are subclase, pentru a garanta faptul că aceste metode nu vor fi estinse, înstrucţiunile ce
le compun sunt incluse în codul compilat, eliminând necesitatea de a lua o decizie şi posibilitatea
încărcării unei noi clase, în timp ce programul rulează. Al doilea motiv de declarare a acestor clase
final este dat de securitatea şi claritatea asigurată, deoarece se poate specifica o clasă cu
comportament cert, se poate dori ca nimeni să nu aibă posibilitatea de modificare a
comportamentului unei clase, extinzându-I metodele. Declarând-o final, se previn subclase
asociate, respectând funcţionalitatea şi securitatea ei.[java_8]
Numele clasei este identificator uni în acelaşi pachet. La importul claselor din alte pachete, numele
claselor din pachetul propriu nu trebuie să intre în conflict cu numele celor din pachetele
importate. Prin convenţie, programatorii Java scriu primul caracter din clasă cu majuscule, pentru
a asigura numele clasei şi variabilelor distincte, făcând codul uşor de citit.
Clasele extends specifică clasa din care se moştenesc, fiind superclase imediate sau clase părinte.
O subclasă estinde funcţionalitatea clasei părinte, în Java existând doar moşteniri simple. Clasele
final nu apar în clase extends iar în absenţa clauzei extends, clasa moşteneşte implicit
caracteristicile clasei Object (rădăcina tuturor claselor).
Moştenirea, conceptul central OOP este implementat în Java cu un puternic mecanism de control
ceea ce însemnă că se pot specifica acele caracteristici ale clasei, care vor fi/ nu vor fi vizibile în
subclase şi acele metode care pot/ nu pot fi extinse.
Implicit o clasă moşteneşte toate câmpurile (variabile şi metode), exceptând constructorii, din
superclasă. Inafara constructorilor, variabilele şi metodele declarate private, vor fi invizibile
oricărei clasă ce o moşteneşte.
implements Interfata1, Interfata2,…InterfaţaN
Mecanismul interface oferă unele funcţionalităţi ce permit implementarea moştenirilor multiple,
evitând caracteristici circulare şi alte elemente periculoase ce implică moştenirile multiple.
[An_96] O clasă poate extinde doar o superclasă dar poate implementa oricâte interfeţe (nelimitate
ca număr). Interfeţele se specifică în declaraţia de clasă după cuvântul rezervat implements ca şi
listă separată prin virgulă.Clauza implements este opţională, prezentă doar dacă se implementează
interfeţe.
Studiu de caz:
Creăm o subclasă Point3D care moşteneşte implementările distanţei dintre două puncte din
superclasă (Point), pe care o supraîncarcă2 apoi.
Exemplu:
Class Point()
int x,y;
Point( int x, int y){
this.x=x;
this.y=y;
}
2
Sursa: Java Handbook
36
double distance(int x, int y){
int dx=this.x-x;
int dy=this.y-y;
return Math.sqrt(dx*dx+dy*dy);
}
double distance(Point p){
return distance(p.x,p.y);
}
}
37
Java, metoda este selectată bazându-se pe tipul instanţei la un moment dat şi nu pe clasa în care
metoda curentă este executată.
Când se apelează la o metodă utilizând operatorul punct (.) şi referinţa obiect, declararea tipului
obiectului referit este verificată la compilare, pentru a se asigura că metoda apelată există în
declaraţia de clasă. In rulare, obiectul referinţă poate fi referit ca şi o instanţă a unei sublclase a
tipului de referinţă declarat. In acest caz, Java foloseşte actuala instanţă pentru a decide ce metodă
apelează evenimentul pe care subclasa supraîncarcă metoda ce a fost apelată3. [Hoff_96]
Exemplu:
Presupunem două clase care au o superclasă cu o singură metodă supraîncărcată în clasă.
class A {
void apel(){
System.out.println.("Metoda de apel a lui A");
}
}
class B extends A {
void apel(){
System.out.println.("Metoda de apel a lui B");
}
}
class disp () {
public static void main(String args [ ]){
A a = new B();
A apel();
}
}
Această formă de polimorfism dinamic al execuţiei este cel mai puternic mecanism pe care îl oferă
programarea OO atât pentru codul reutilizat cât şi pentru robusteţea programelor.
In clasa disp definim metoda main() în interiorul căreia se declară variabila a de tip A, care
memorează o referinţă la o instanţă din clasa B. In linia următoare apelăm apel() ca metodă a lui a
dar când compilatorul Java verifică dacă a are această metodă rezultatul este corect. In schimb
Java runtime notează că referinţa este de fapt instanţa lui B şi astfel cheamă metoda apel a clesei
B. Vom obţine astfel:
Metoda de apel a lui B
2.1.6. Finalizarea
In timp ce Java runtime este un sistem colector de deşeuri (garbage collector system) nu este
necesar managementul memoriei însă apar unele situaţii de excepţie în care se impune efectuarea
unui cod special atunci când un obiect este solicitat de garbage collector. Spre exemplu dacă o
clasă foloseşte resurse non-Java ( spre exemplu: fişiere manipulate sau fonturile ferestrei sistem)
3
Dynamic method dispatch
38
trebuie utilizată metoda de finalizare pentru a ne asigura că sunt eliberate toate resursele. Această
metodă funcţionează similar cu destructorul din C şi nu se poate confunda cu final.
Rezolvarea acestor excepţii se face adăugând metoda finalize în orice clasă caz în care Java
runtime o apelează de oricâte ori se reclamă eliberarea saţiului pentru un obiect. Metoda trebuie să
ia explicit orice acţiune solicitată pentru a elibera resursele deoarece garbage collector rulează
periodic, verificând obiectele care nu mai sunt referite de alte stări în lucru, sau referite indirect,
prin alte obiecte.
Colectorul de reziduri elibereaza resursele de memorie utilizate de obiectele pe care le distruge dar
obiectele mai păstrează şi alte tipuri de resurse cum ar fi descriptorii sau socket-urile. Colectorul
de reziduri nu poate elibera aceste resurse, astfel încât este necesară o metodă de finalizare proprie
fiecarui obiect care să realizeze operaţii specifice cum ar fi închiderea de fişiere care ramân
deschise accidental sau terminarea unei conexiuni în reţea.
2.2.Variabile şi metode
2.2.1. Variabilele
In Java variabilele înmagazinează dată iar conform paradigmei OO înglobează starea unui obiect
dat. Acestea sunt divizate în 2 categorii: variabile de instanţă, ce permit individualizarea
obiectelor din clasă şi variabile statice, care se referă la toate obiectele dintr-o clasă dată. Fiecare
obiect individual dintr-o clasă dată este numit instanţă sau instanţiere a clasei. Când se creează un
obiect specific al unei clase, se instanţiază un obiect din clasă şi spaţiul este alocat pentru toate
variabilele de instanţă ale obiectului. Fiecare obiect ce este instanţiat are un spaţiu alocat
independent de variabilele de instanţă.
Variabilele static, pe de altă parte, sunt create odată şi sunt folosite de toate obiectele din clasa
dată şi de clasele moştenite. Nu are importanţă câte obiecte se creează dintr-o clasă, se face o copie
a variabilelor statice ce aparţin clasei. Spre exemplu, în clasa java.lang.Integer, variabila
MAX_VALUE este statică şi conţine valoarea maximă a unui întreg. Deoarece acest număr este
unic, nu are importanţă câte obiecte întregi sunt instanţiate, se face o singură copie a acestei
variabile şi astfel se alocă memorie minimă.
Referirea variabilelor de instanţă a unui obiect se face prin:
numele_instanţei_specifice.numele_variabilei_de_instanţă.
Exemplu:
In clasa Clasa1 definim variabile de instanţă por şi două obiecte care instanţiază clasa: ap2
şi ap3. Referinţa la variabilă se va face:
ap2.por
ap3.por
In definiţia de clasă varibilele statice şi de instanţă se pot referi şi fără calificare (suprafata, por,
etc)
39
2.2.2. This, super şi null
Fiecare obiect are încapsulate trei variabile: this, super şi null. This este pseudonimul obiectului
însuşi dat fiind faptul că în interiorul definiţiei de clasă se pot referi instanţe ale clasei fără a
specifica un obiect; this.n este spre exemplu o variabilă de instanţă a clasei în timp ce fără punct
(n) este variabilă a metodei. Explicitarea this este necesară pentru a distinge între variabila locală n
şi varibila de instanţă this.n.
Super este pseudonimul obiectelor din superclasa imediată, numită în clauza extends. Deoarece
variabilele din superclasă sunt moştenite în subclasă (dacă nu se limitează accesul prin private) se
referă simplu fără calificarea ca variabile de instanţă a clasei locale. Totuşi este posibil să se
declare ca variabilele de instanţă într-o subclasă, cu acelaşi nume ca şi variabilele de instanţă din
superclasă. Variabila definită în subclasă "maschează" sau "umbreşte" variabila definită în
superclasă. Pentru a o referi, se foloseşte cuvântul cheie super.
Exemplu:
Class SuperClasa {
int n=10; // se iniţializează n
}
class Clasa1 extends Superclasa {
int i,n;
public void main Method (int n) {
this.n=n; // necesar this, altfel apare conflict de nume
i=super.n; //i=10
}
}
This şi super sunt folosite numai în interiorul metodelor non-statice.
Inainte de a iniţializa un obiect el nu are valoare dar după iniţializare el are valoare implicită null.
Există situaţii în care atribuirea explicită a valorii null este necesară pentru obiecte, în special la
determinarea structurii dinamice de date ca arbori, liste, etc. Aceste structuri pot creşte şi se pot
extinde fără limite iar valoarea null marchează sfârşitul structurii. Un alt caz este thread(firul) de
execuţie, care se opreşte setându-l pe null. [Lema_98]
Observaţie: Se poate atribui valoarea null obiectelor sin orice clasă dar nu şi metodelor şi
variabilelor unor tipuri primitive de dată ( int, float, char, etc).
Exemplu: String str;
După această declaraţie str, este manipulat de obiectul String. Manipulatorul (handle) este similar
cu pointerul C, C++. După declaraţie nu se alocă memorie lui str, considerat ca manipulator null.
Handle nu are sens de "poiter la pointer" ca şi în C sau C++ ci mai degrabă ca referinţă la obiect şi
nu implică adresă fizică.
40
Accesibile tuturor claselor din interiorul pachetului;
Inaccesibile din exteriorul pachetului;
Dacă nu există alte intenţii se indică specificând unul din cuvintele rezervate: public, protected,
private, static, sau final.
Variabila declarată public are aceeaşi aceesibilitate ca şi clasa dar nu depăşeşte accesibilitatea
clasei. Intr-o clasă cu acces implicit variabila public este accesibilă numai în interiorul pachetului
dar într-o clasă cu acces public varibila public va fi accesibilă oriunde.Variabilele public sunt
moştenite în orice subclasă derivată din lcasa în care sunt declarate.
Variabilele declarate protected sunt aceesibile tuturor claselor din pachetul ce conţine clasa în
care sunt declarate. In exteriorul pachetului variabilele protected sunt accesibile doar subclaselor
derivate din clasa în care sunt declarate.Variabilele protected sunt eliberate de restricţii implicite
de moştenire dar reţin restricţiile de acees la clasele fără legătură din exteriorul pachetului .
Observaţie: Spre deosebire de C++ unde variabilele protected sunt aceesibile nimai în clasa dată şi
sublcasele ei, Java extinde conceptul la nivel de pachet, în interiorul căruia variabilele sunt
aceesibile tuturor claselor, chiar dacă aceste clase nu derivă din clasa în care au fost create.
Variabilele private sunt accesibile numai în clasele în care sunt declarate şi restricţiile se extind şi
la clasele derivate.
Variabilele static sunt instanţiate odată şi împărţite între toate obiectele clasei în care sunt
declarate şi în toate subclasele moştenite.
Există distincţie între variabilele statice (care aparţin clasi ca întreg) şi varibilele de instanţă care
sunt create separat pentru fiecare obiect al clasei şi este instanţiat ca aparţinând obiectului. Toate
variabilele ce nu sunt explicit declarate static sau final sunt variabile de instanţă.. Static poate fi
combinat cu orice specificator de acces: public, protected, private sau implicit.
Variabilele final sunt de fapt constantele şi de aceea la declararea lor se atribuie şi valoare, altfel
valoarea nu mai poate fi modificată. Deseori se declară constante ca final static. Tip-ul poate fi tip
primitiv, tablou, tip obiect, incluzând obiectele din această clasă. Nume variabilă începe de obicei
cu literă mică.[java_1], [java_8]
2.2.4. Metodele
Comenzile executate de Java sunt conţinute în metode, excepţie făcând blocurile statice. Toate
metodele sunt aflate în clase şi esistă o strictă similitudine cu OO din C++, unde funcţiile pot
exista independente de obiecte dacă programatorul doreşte.
Blocurile statice conţin cod executabil în interiorul metodei şi sunt excepţii. Aceste coduri sunt
folosite pentru a iniţializa variabilele statice ce nu pot fi complet iniţializate sau liniile de declaraţii
(ca şi tablourile).
Blocul static se referă doar la variabile statice şi la cele locale decarate în interiorul blocului.
Exemplu:
class Repar{
static double[] vcos= new double[100]; // variabile statice
static {
// blocul static
for (int i=1, i<100, i++) {
vcos[I]=Math.cos((double)i/100.0);
}
…}
41
}
}
Chiar variabila locală I este implicit statică deoarece este declarată în bloc static şi nu este
accesibilă din esteriorul acestui bloc.In interiorul clasei Repar sunt date valori specifice pentru
repar.vcos.
Metodele statice la fel ca şi variabilele statice sunt instanţiate odată pentru toate obiectele din clasă
şi de aceea nu pot referi variabile de instanţă, care aparţin obiectelor specifice, nu clasei ca
întreg.Metodele statice pot accesa variabile statice şi sunt implicit final fără a putea fi
supraîncărcate de clase derivate. Invocarea se face cu numele clasei ca şi calificator sau numele
obiectului instanţiat ca şi calificator de clasă.
Exemple:
Metoda static din java.lang.String
String unSir= new String();
String altSir= new String();
UnSir =String.valueOf(5);// echivalente
UnSir =UnSir.valueOf(5);// echivalente
UnSir =altSir.valueOf(5);// echivalente
Metodele statice nu pot utiliza this şi super şi sunt împărţite de toate instanţele clasei, motiv pentru
care nu aparţin unei instanţe specifice.Referind o metodă cu this pot fi sute de obiecte ce
instanţiază clasa şi nu se poate determina la care se face referire. La super, care este nivelul
moştenirii la care se află metoda? Care clasă e superclasă?- Intrebări fără răspuns. De aceea
metodele statice nu pot face referire la câmpuri non-statice.
Exemplu:
public class Test1{
42
String str="un sir"// constructor apelat implicit
public static void main (String args[ ]) {
System.out.println (str);//eroare, str nu este variabilă non-statică
System.out.println (this.str);//eroare, nu se foloseşte this în metodă
}
}
Metoda final nu poate fi acoperită de clase derivate şi se poate combina cu public, private,
protected sau static sau specificată însuşi cu combinaţiile acestora, în concordanţă cu accesul
implicit precizat. Metoda abstact este declarată dar are implementări diferite în subclase, având
inteles contextual. Ea nu poate fi combinată cu metode ce restrâng moştenirea sau acoperirea
(private, static sau final) iar deoarece un constructor nu poate fi moştenit, nu poate fi final.
Native este metodă proprie în esenţă un apel exterior la funcţii scrise în alt limbaj de programare
(C, C++, etc.). Dearece Java este multithread (multifir) este necesară furnizarea mecanismului de
control al concurenţei pentru că sunt câteva operaţii care se execută simultan iar alte operaţii
(citire, scriere de date comune implică manipulări delicate. Declarând metoda sycronized se
garantează că doar un fir va fi executat la un moment dat.[Naugh_96]
Apelul unei metode presupune şi transferul parametrilor (argmentelor) care sunt substituiţi în
interiorul metodei în timpul execuţiei acesteia. Parametri de tip primitiv (int, float, char, boolean)
sunt transferaţi prin valoare, ceea ce înseamnă că se crează o copie locală cu acceaşi valoare ca
parametrul în interiorul metodei iar în exteriorul metodei nu se resimt modificările făcute în copia
locală. Obiectele de tip tablou sunt transferate prin referinţă, ceea ce înseamnă că în interiorul
metodei nu există o copie locală ci poate fi chemat prin valoare. Modificările afectează obiectul
actual şi de aceea ele persistă şi după metodă. [An_96] La declararea metodei se cunosc explicit
tipurile de parametri ce urmează a fi primiţi din lista de argumente a metodei. In OOP nu este
necesară precizarea tuturor informaţiilor solicitate în lista de parametri deoarece metoda ştie deja
despre ele şi are acces la toate variabilele de instanţă precum şi la cele statice în care este
definită.In lista de termeni se precizează doar acele informaţii la care metoda nu are acces, ca şi
instanţele variabilelor pentru alte obiecte, care pot fi diferite de fiecare dată când metoda este
apelată.
Exemplu:
class Fargum{
double d=3.14;
public void fMetoda (double d, Fargum other){
x=x*2.0;
d=other.d;
other.d=0.0; //efect global
}
}
43
Fargum nouFargum= new Fargum;
Fargum altFargum= new Fargum;
nouFargum.d=14.4;
altFargum.d=19.2;
System.out.println ('Inainte de apel");
System.out.println ("noud "+noud);
System.out.println ('nouFargum.d "+ nouFargum.d);
System.out.println ('altFargum.d "+ altFargum.d);
//apel metodă
nouFargum.fMetoda (noud, altFargum);
System.out.println ('După apel");
System.out.println ("noud "+noud);
System.out.println ('nouFargum.d "+ nouFargum.d);
System.out.println ('altFargum.d "+ altFargum.d);
}
}
Rezultatele obţinute:
Inainte de apel
noud 28.8
nouFargum.d 14.4
altFargum.d 19.2
După apel
noud 28.8
nouFargum.d 1105.92
altFargum.d 0
De multe ori se doreşte crearea unei metode utilizată în exteriorul contextului oricărei instanţe, caz
în care se folosesc metodele statice, care pot apela direct doar metode static şi nu pot fi referite ca
this şi super .In cadrul acestor metode se declară doar variabile static.
Exemplu:
class Static {
static int a=3;
static int b;
static void metoda (int x) {
System.out.println ("x="+x);
System.out.println ("a="+a);
System.out.println ("b="+b);
}
44
static {
System.out.println ("Initializarea blocului static");
b=a*8;
}
public static void main (String args[] ){
metoda (33);
}
}
Un alt mod de a utiliza static este crearea metodelor ce pot fi apelate direct, referind numele clasei
în care sunt declarate. Similar cu apelul metodelor de instanţă prin variabilele de referinţă ale
obiectului, se apelează metoda static pentru a referi variabile static, utilizând . (punct) în numele
clasei.
Exemplu:
class StaticClass {
static int a=23;
static int b=90;
static void apel () {
System.out.println ("a="+a);
}
class StaticprinNume {
public static void main (String args[] ){
StaticprinNume.apel ();
System.out.println ("b="+StaticprinNume.b);
}
}
Modificatorii sunt cuvinte cheie ale limbajului Java care specifică proprietăţi speciale pentru unele
variabile sau metode. Un astfel de modificator este cuvântul rezervat static iar variabilele şi
metodele declarate static într-o clasă, sunt acelaşi pentru toate clasele, adică pentru toate
variabilele de tipul acelei clase. Variabilele statice pot fi accesate fără a fi nevoie o instanţiere a
clasei respective şi analog, nici metodele statice nu au nevoie de o instanţiere a clasei pentru a fi
folosite. Metodele statice pot utiliza variabile statice declarate în interiorul clasei.
Semnătura unei metode este definită prin lista de argumente specificată (număr, ordine şi tip) al
fiecărui argument.Metodele se disting prin prin combinaţii de nume şi semnătură. In Java, la fel ca
şi în C++, este posibilă crearea metodelor supraîncărcate (overloading), care au acelaşi nume şi
semnături diferite. Deseori este utilă oferirea unor funcţionalităţi similare pentru diferite tipuri de
argumente, ceea ce permit metodele cu acelaşi nume iar când acestea sunt apelate, nu apar
ambiguităţi la execuţie, pentru că metodele sunt distinse prin semnătură.
Exemplu:
In clasa java.lang.String sunt metodele:
public static String valueOf(int i) {…}
public static String valueOf(float i) {…}
Metoda String valueOf(i) ia de fiecare dată tipul de parametru transferat şi în converteşte
în şir. Este normal ca paşii ce se execută la conversia întregului să difere de cei executaţi a
45
conversia float. Compilatorul foloseşte semnătura pentru a determina versiunea ce trebuie
executată.
Metoda supraîncărcării este mecanismul prin care Java furnizează polimorfismul adhoc în care
compilatorul decide versiunea metodei prin semnătura ei, la momentul apelului metodei, în
contrast cu polimorfirmul pur, furnizat de clasele abstracte. [Chan_96]
Toate metodele cu exceptia constructorilor, trebuie declarate cu valoare întoarsă şi în caz contrar
cu void, deoarece în Java, omiterea tipului întors este o eroare, spre deosebire de C, C++ care
declară implicit tip int.
Spre deosebire de metodele care întorc void, instrucţiunea return se include în corpul metodelor în
orice punt de execuţie; aceasta opreşte execuţia metodei şi redă controlul metodei apelante.
Compilatorul se asigură de acest lucru şi trateaza fiecare if..then…else din metodă pentru a se
asigura că pe orice ramură metoda este terminată.
Exemplu:
Class MulteIntoarceri {
void maIntorc(String s){
if s.equals("M-am intors"){
return;//intoarcere rapida
}
…// alte instructiuni
return //optional
}
int eronat (Boolean b, Boolean t} {
int i;
double d;
if (b) {
…
return; //eroare, trebuie intors int
}else if (t){
…
return d;// eroare, d este double
}else if (i>0t){
return i;//bine
}else{
46
…
// lipseste return pentru ca nu este declarat void
}
}
}
Numele metodei urmează regulile anterior descrise şi se recomandă scrierea cu literă mică pentru a
o distinge de constructorii apelaţi.
Lista de argumente se include între paranteze, solicitate chiar în lipsa parametrilor, pentru a fi
distinse de declaraţii de variabile şi metode. Fiecare parametru este precedat de tip
Exemplu:
void diM(String s, int[ ] unTablou, double altTablou[ ])
//sir, tablou de intregi, tablou de reale duble
In general se aşteaptă ca excepţiile să fie rare iar în lipsa lor throws poate fi omis. In rest fiecare
exceptie tratată este separată prin virgulă.
2.3. Constructorii
Declaraţiile pure ale unui obiect nu alocă spaţii pentru variabile de instanţă ale acestora. Când un
obiect este delcarat, se instanţiază valoarea null. Instanţierea obiectului se face cu operatorul new.
Exemplu: Contul c=new Contul();
Constructorul este în fapt apelul unei metode speciale definită în orice clasă şi acesta împarte
acelaşi nume cu clasa în care este definit, având rolul de a iniţializa variabilele de instanţă ale unui
obiect, atunci când obiectul este iniţializat.[Lema_98]
47
String(String) construieşte şir nou, copie a celui transmis
String(Char[ ]) construieşte şir nou, din tablou de caractere
Când se declară clase derivate, se moştenesc variabilele de instanţă din superclasă. Deoarece
constructorul din clasa derivată nu este el însuşi moştenit, este necesară o iniţializare a variabilelor
de instanţă moştenite. Acest lucru se poate face manual, ceea ce ia mult timp, însă dacă sarcina
este preluată de superclasă este mult mai comod, mai ales dacă se moştenesc varibile private la
care utilizatorul nu are acces. Din fericire, apelând la constructorul super cu condiţia că apare ca
primă instrucţiune în corpul constructorului.
Exemplu:
class Aclass extends AsuperClass {
double unDublu;
Aclass (int I, int j, double d){
super(i,j);//apel Aclass(i,j)
UnDublu=d; //nu a fost iniţializat de super
}
…
}
Se poate declara o clasă fără a specifica constructorul, fapt mai comod în special când o clasă este
moştenită direct din altă clasă. Omiţând constructorul din clasă, compilatorul Java, generează
automat constructorul implicit din superclasă.
Exemplu:
class FinalAclass extends B {
// nu se furnizează constructor
// compilatorul generează automat
FinalAclass{
super();//apel B()
}
…
}
Dacă superclasa imediată (B în exemplu) nu are constructor care să preia argumentele, apar erori
de compilare.
48
In programare se pot declara constructori private, furnizând metode public static care apelează
constructorul şi întoarce obiectul construit. Pentru crearea unui obiect din exteriorul pachetului se
apelează metoda static însă este util să se verifice argumentele din constructor şi să se trateze
excepţiile care pot apare. Constructorul în sine nu tratează excepţiile dar metodele static pot
analiza excepţiile şi să apeleze constructorul cu argumente corecte.
Limbajul Java pune la dispozitie o metoda pentru crearea claselor complet abstracte, cunoscute ca
şi interfete. Interfeţele sunt destinate pentru a suporta rezoluţiile metodelor dinamice în timpul
execuţiei. Pentru ca o metodă să poată fi apelată dintr-o clasă în alta, ambele clase trebuie să fie
prezente la un moment dat în timpul compilării, pentru a ne asigura că semnăturile metodelor sunt
compatibile. Mecanismul de deconectare a metodei/metodelor din ierarhia moştenirii este protocol
în C obiectual şi interfaţă în Java.[Chan_95], [java_1]
Exemplu:
interface P(){
byte[]pack();
void unpack(byte b[]);
}
class Punct {
int x,y;
Punct (int x, int y) {
this.x=x;
this.y=y;
}
}
class AltPunct extends Punct implements P {
AltPunct (int x, int y){
super (x,y);
}
AltPunct(){
this (0,0);
}
private byte p(int t, int n) {
return (byte)((t>>n)&Oxff); //octal
}
public byte pack()[]{
byte ret[]=new byte[8];
ret[0]=p(x,24);
ret[1]=p(x,16);
49
ret[2]=p(x,8);
ret[3]=p(x,0);
ret[4]=p(y,24);
ret[5]=p(y,16);
ret[6]=p(y,8);
ret[7]=p(y,0);
return ret;
}
private int n(byte b, int n){
return ((b&Oxff)<n);
}
public void unpack(byte b[]){
x=u(b[0],24| b[1],16| b[2],8| b[3],0);
x=u(b[4],24| b[5],16| b[6],8| b[7],0);
}
public String toString(){
return("Noul punct"+x+'.'+y);
}
}
class PointPack{
public static void main(String args[]){
P p=Altpunct(123456789,555566667);
byte packed[]=p.pack();
AltPunct pnou= new AltPunct();
pnou.unpack(packed);
System.out.println ("p"+pnou);
}
}
Interfeţele pot avea şi subinterfeţe, care moştenesc variabile (constante în cazul interfeţei) şi
metodele interfeţei din care derivă, dar au posibilitatea de a folosi variabile şi metode proprii.
Pentru a implementa o intefaţă, se utilizeaza cuvantul cheie implements. O clasa poate
implementă mai multe interfete iar daca o clasă declară implementarea unei interfeţe, este
obligatoriu ca ea să implementeze toate metodele din intefaţa respectivă. Programele Java
utilizează interfeţele pentru a suplini lipsa moştenirilor multiple, adică a claselor care derivă din
două sau mai multe clase.
Putem utiliza interfeţele pentru a importa constante împărţite în multiple clase, declarând simplu o
interfaţă ce conţine toate numele şi toate variabilele. Când se implementează apoi această interfaţă,
toate numele acestor variabile vor fi folosite în scop de constante (similar cu fişierul header din
C++ utilizat la crerea unor constante definite prin #defined ca şi constructor). Dacă interfaţa nu
conţine metode, orice clasă ce o implementează nu trebuie să implementeze nimic în plus şi se
comportă ca şi un import de constante dintr-o clasă, ca variabile de tip final.
Exemplu:
import java.util.Random;
interface ConstanteImpartite {
50
int a=0;
int a1=1;
int a2=2;
int a3=3;
int a4=5;
}
class Prima implements ConstanteImpartite {
Random r=new Random();
int intreb{
int prob= (int)(100*rand.nextDouble());
if (prob<30)
return a;
else if prob(<60)
return a1;
else if prob(<75)
return a2;
else if prob(<90)
return a3;
}
}
class Doi implements ConstanteImpartite {
static void rasp (int rez) {
switch(rez) {
case a:
System.out.println ('Da");
case a1:
System.out.println ('Nu");
case a2:
System.out.println ('Poate");
case a3:
System.out.println ('Nu sunt sigur");
}
}
public static void main (String args[]){
Prima q1= new Prima();
rasp(q1.intreb);
rasp(q1.intreb);
rasp(q1.intreb);
rasp(q1.intreb);
}
}
In interiorul celor două clase codul care referă constantele este dat ca şi cu ele ar fi definite sau
moştenite direct. Toate metodele declarate într-o interfaţă sunt implicit abstract şi similar, toate
variabilele dintr-o interfaţă sunt implicit static şi final deoarece sunt formate ca şi constante. Spre
deosebire de clasă, o interfaţă poate extinde multiple interfeţe moştenind variabilele şi metodele
51
definite în interior. Orice clasă ce implementează o asemenea interfaţă trebuie să ofere definiţii
pentu toate metodele definite în interfaţă şi toate interfeţele esenţiale.
Exemplu:
interface Simplu1 {
int a;
void absolM1(){
}
interface Simplu2 {
String str;
void absolM2(){
}
Interface Combinata extends Simplu1,Simplu2 {
void absolM3(){
}
}
//ImpClasa cere implementarea metodelor absolM1()
// absolM2(), absolM3()
class ImpClass implements Combinata {
public absolM1 (){
// definitia metodei 1
}
public absolM2 (){
// definitia metodei 2
}
public absolM3 (){
// definitia metodei 3
}
// alte metode ale clasei ImpClasa
}
Dacă o clasă implementează o interfaţă sublcasele moştenite pot extinde aceste metode
implementate, respectând restricţiile impuse de specificatorii de acces. In plus dacă o clasă
implementează o interfaţă sau un set de interfeţe nu este necesară includerea acestora în clauzele
implements ale subclaselor.
52
Protected
Clasa - inaplicabilă;
Variabile - vizibile tuturor claselor ce acceseză această clasă în interiorul pachetului;
- vizibile numai în clasele derivate în exteriorul pachetului;
Metode - vizibile tuturor claselor ce pot extinde această clasă în interiorul pachetului;
- vizibile doar claselor derivate din această clasă în exteriorul pachetului;
[default] (implicit)
Clasa - în interiorul pachetului accesibile tuturor claselor;
- în exteriorul pachetului inaccesibile;
Variabile - vizibile tuturor claselor în interiorul pachetului;
- vizibile numai în clasele derivate în exteriorul pachetului;
Metode - vizibile tuturor claselor ce pot suprascrie această clasă în interiorul pachetului;
- vizibile doar claselor derivate din această clasă şi pot fi suprascrise de aceste clase, în
exteriorul pachetului;
Private protected
Clasa - inaplicabilă;
Variabile - vizibile doar claselor derivate din aceasta în interiorul şi exteriorul pachetului;
Metode - vizibile doar claselor derivate din această clasă în interiorul/exteriorul pachetului
- pot fi acoperite de clase derivate
Private
Clasa - inaplicabilă;
Variabile - vizibile doar în interiorul clasei;
Metode - - vizibile doar în interiorul clasei.
Final
Clasa - nu pot fi extinse;
Variabile - atribute cu valoare permanentă în declaraţiile lor;
- valoarea nu poate fi schimbată în orice clasă chiar dacă sunt sau nu sunt derivate din
acestă clasă;
metode - nu poate fi acoperită.
Static
Clasa - inaplicabilă;
Variabile - numai copia variabilelor se împarte de toate subclasele;
Metode - - metoda este împărţită de toate subclasele dar nu poate fi extinsă.
Abstract
Clasa - conţine una sau mai multe metode abstracte;
- nu poate fi instanţiată;
Variabile inaplicabilă;
Metode - nu este definită şi va fi pusă la dipoziţie de subclasă;
- trebuie acoperită când este subclasată sau subclasa însuşi este abstract.
Native
Clasa - inaplicabilă;
Variabile inaplicabilă;
Metode - este definită în alt limbaj (exterior) ca şi C, C++, etc.
Syncronized
Clasa - inaplicabilă;
Variabile inaplicabilă;
Metode - la momentul dat, numai un fir poate spune obiectului instanţat să
53
execute această metodă;
- dacă este static, numai un fir poate executa această metodă la un timp dat, periodic.
In definirea unei clase se pot include şi nivele de protecţie pentru variabile şi metode, cu ajutorul
unor cuvinte rezervate numite modificatori de acces: protected, public sau private. In lipsa acestor
nivele de protecţie implicit se consideră nivelul prietenos (friendley).[An_96]
54
In Java protected induce comportament similar cu friend din C++ iar private protected ca şi
protected din c++.
Semnificatiile acestor nivele de protecţie sunt diferite, astfel:
• Protected – metodele şi variabilele sunt declarate protected, sunt disponibile în
clasa în care sunt definite şi în subclasele din această clasă.
• Public - metodele şi variabilele sunt declarate public, fiind disponibile în toate
clasele.
• Private - metodele şi variabilele sunt declarate private, fiind disponibile numai în
clasa în care sunt definite; nici măcar subclasele derivate din această clasă nu au acces
la ele.
• Prietenos(friendly) – nivelul implicit, ele sunt disponibile pentru toate clasele din
pachetul curent.
O variabilă sau o metodă nu poate avea declaraţe mai multe nivele de protecţie simultan, sau în
discordanţă cu pachetul din care face parte, acestea determinând erori la compilare.
Exemplu:
package p1;
public class Protectia {
int n=1;
private int n_pri=2;
protected int n_pro=3;
private protected int n_pripro=4;
public n_pub=5;
public Protectia(){
System.out.println ("Constructorii de bază");
System.out.println (n);
System.out.println (n_pri);
System.out.println (n_pro);
System.out.println (n_pripro);
System.out.println (n_pub);
}
}
class Derivata extends Protectia {
Derivata(){
System.out.println ("Constructori derivati");
System.out.println (n);
//numai în clasă
//System.out.println (n_pri);
System.out.println (n_pro);
System.out.println (n_pripro);
System.out.println (n_pub);
}
}
class acPachet {
acPachet(){
Protectia p=new Protectia();
System.out.println ("Constructori in acelaşi pachet");
System.out.println (p.n);
55
//numai în clasă
//System.out.println (p.n_pri);
System.out.println (p.n_pro);
//in clasa si subclasa
System.out.println (p.n_pripro);
System.out.println (p.n_pub);
}
}
In pachetul p2 două definiţii de clasă acoperă două condiţii ce sunt afectate de controlul accesului.
Prima clasă este subclasă a lui p1.Protectia ce garantează acces la toate variabilele p1.Protectia, cu
excepţia lui n_pri (deoarece ea este private) şi n declarată prin protecţie implicită (în interiorul
clasei sau în pachet nu în subclase extrapachet).Clasa AltPachet are acces doar la o variabilă n_pub
declarată public.
Exemplu:
package p2;
class Protectia2 extends p1.Protectia {
Protectia2 () {
System.out.println ("Constructor derivat din alt pachet");
// numai in clasa sau pachet
//System.out.println (n);
//numai in clasa
//System.out.println (n_pri);
System.out.println (n_pro);
System.out.println (n_pripro);
System.out.println (n_pub);
}
}
class AltPachet{
AltPachet (){
p1.Protectia p= new p1.Protectia();
System.out.println ("Constructor in alt pachet");
// numai in clasa sau pachet
System.out.println (p.n);
//numai in clasa, subclasa si pachet
//System.out.println (p.n_pro);
//numai in clasa sau sbclasa
//System.out.println (p.n_pripro);
System.out.println (p.n_pub);
}
}
56