A Java nyelv C++ szintaktikára épít, számos különbséggel Hello, World (alkalmazás, parancssorból indítható): A HelloWorldApp.java fájl: Java programozás alapjai A főosztály: neve = fájlnév, van benne main A program belépési pontja: statikus metódus class HelloWorldApp { public static void main(string[] args) { System.out.println("Hello World!"); cout << << \n Hello world futtatása Java adattípusok HelloWorldApp.java javac HelloWorldApp.java HelloWorldApp.class java HelloWorldApp class HelloWorldApp { public static void main(string[] args) { System.out.println("Hello World!"); Szimbólumtábla: main: public, static, void Belölti a HelloWorldApp.class fájlt és elindítja a main függvényt. Mivel még nincs ilyen objektum a main szükségképpen statikus Egyszerű adattípusok (int, float) Osztályokkal objektumok Nincs külön mutató, referencia, címe operátor, helyette: objektumok csak dinamikusan hozhatok létre és csak referenciával hivatkozhatunk rájuk Egyszerű adattípusoknak van csomagoló objektuma Tömbök (is objektumok) Sztringek Egyszerű adattípusok Unsigned egészek Egyszerű alaptípusok: byte 8-bites előjeles egész short 16-bites előjeles egész int 32-bites előjeles egész long 64-bites előjeles egész float 32-bites lebegőpontos (IEEE 754) double 64-bites lebegőpontos (IEEE 754) char 16-bites Unicode karakter boolean Bool-érték (igaz v. hamis) Az egész típusok szélessége nem függ a platformtól Előjel nélküli (unsigned) egész nincs! Az == operátor alkalmatlan két double egyenlőségének vizsgálatára! byte unsigned értékének kiolvasása: byte b; int i = b & 0xff; 32-bites int unsigned értékének kiolvasása: int i; long l = i & 0xffffffffL; 1
Implicit típuskonverzió Implicit konverziót csak bővítésnél (widening primitive conversion) lehet használni : byte -> short -> int -> long -> float -> double char -> int -> long -> float -> double Egész típusok bővítő konverziója esetén az eredeti pontos értéket megőrizzük A byte -> char, illetve short -> char konverziók nem tekinthetőek bővítésnek, mivel a char unsigned: byte b = 126; short s = 1000; char c; c = b; // compile error: possible loss of precision c = s; // compile error: possible loss of precision Az int -> float, long -> float, long -> double konverziók csökkenthetik a számábrázolás precizitását, ilyenkor az eredeti egész értékeket kerekítjük Explicit típuskonverzió Szűkítésnél (narrowing primitive conversion) kötelező explicit konverziót (cast operatort) használni: double -> float -> long -> int > char -> short > byte pl.: int i = 32; byte b = (byte)i; Szűkítés esetén az alsó biteket őrizzük meg, így előfordulhat, hogy az eredeti érték nagyságrendjét is elveszítjük Explicit típuskonverzió Típuskonverzió függvényekkel Példák implicit/explicit konverzióra int a = 1; // a == 1 float a = (float)1; // a == 1.0 float a = 1/2; // a == 0.0 float a = (float)1/2; // a == 0.5 int a = 3.14; // a == 3 Primitív és összetett típusok között nincs implicit/explicit konverzió int String String egy = Integer.toString(1); String egy = + 1; String int int a = Integer.parseInt( 1 ); Egyszerű adattípusok specialitásai Változó létrehozása default (zérus) kezdőértékkel: int i; Változó létrehozása kezdőértékkel: int i = 5; Egyszerű adattípusok deklarációja és definíciója (memória foglalás) egyszerre történik Konstans változó a final kulcsszóval (C++ const): final double pi = 3.14159286; Osztályok Minden adatstruktúra osztály (class) típusú nincs struct, union Az osztály más csomagból is public class Employee { csomagból String name; private long salary = 100; osztályból public Employee(String n, long sal) { bárhonnan name = n; salary = sal; Nem kell a végén pontosvessző Változókhoz kezdőértéket rendelhetünk vagy alapért. A törzs csak az osztályon belül lehet 2
Osztályok Osztály példány = objektum objektumok prototípusa összefüggő adatok és metódusok gyűjteménye pl. String objektum: karakterek tömbje és a rajtuk végezhető műveletek példányt mindig a new operátorral hozunk létre nem lehet objektumot lokális változóként létrehozni a változónk mindig hivatkozást tartalmaz Student s1; // deklaráció s1 = new Student( Ubul, 3.5); // definíció az = a hivatkozást másolja, az objektumot NEM! Student s2 = s1; // s2 ugyanaz az objektum // lesz, mint s1! Minden objektum dinamikus Érték versus Referencia típusok: C++ C++ Java class Vector { class Vector { int x, y; int x, y; ;.. Vector v; // stack-en Vector v = new Vector( ); Vector *pvnull = NULL; Vector pvnull; Vector *pv = &v; Vector pv = v; Vector& rv = v; Vector rv = v; Vector *pvd = new Vector(); Vector pvd = new Vector(); delete pvd; szemétgyűjtés Globális memóriában vagy a vermen Deklaráció és helyfoglalás egyszerre Sohasem null = adatot másol nem referenciát A tömbjeiben elemek vannak Akárcsak a beépített típusok int i, j=3; i = j; int array[10]; Class c; c.f( ); Class c1 = c; Dinamikus memóriából allokált Deklaráció és helyfoglalás külön Lehet null = referenciát másol nem adatot A tömbjeiben referenciák vannak Nem úgy viselkedik, mint a beépített típusok int * pi; Class* c; pi = new int; c = new Class; *pi = 3; c->f( ); int * pj = pi; Class* c1 = c; Érték versus Referencia típusok: Java Visszatérés objektummal Globális memóriában vagy a vermen Sohasem null = adatot másol nem referenciát A tömbjeiben elemek vannak BEÉPÍTETT TÍPUSOK int i, j=3; i = j; int array[10]; Class c; c.f( ); Class c1 = c; Dinamikus memóriából allokált Lehet null = referenciát másol nem adatot A tömbjeiben referenciák vannak OBJEKTUMOK int * pi; Class c; pi = new int; c = new Class; *pi = 3; c.f( ); int * pj = pi; Class c1 = c; int array[]; array = new int[10]; C++ Java class Vector class Vector { { Vector Add(const Vector& v) public Vector Add(Vector v) { { return Vector(x + v.x, y + v.y); return new Vector(x + v.x, y + v.y); ; 3
Egyszerű adattípusok osztályba csomagolása Minden egyszerű adattípusnak létezik egy osztály típusú megfelelője, pl. int és Integer konverziós függvények típusra jellemző konstansok int i1 = 5; Integer io = new Integer(i1); Integer ios = new Integer( 135 ); int i2 = io.intvalue(); float f = io.floatvalue(); String s = io.tostring(); i1 = Integer.MAX_VALUE; Példa: generikus tár C++ Java 1. Template nincs 2. void pointer nincs pointer 3. Alaposztályra Mi az alaposztály: Object!!! mutató pointer vagy referencia class Tar { Object obj; void Put(Object o) { obj = o; Object Get() { return obj; Tar tar = new Tar(); tar.put( 3 ); tar.put( new Integer(3) ); Tömbök értékek indexelt listája bármilyen típusból létrehozhatunk tömböt a [ ] operátorral int[] tomb; // üres tömb Int tomb[]; // üres tömb a tömb minden eleme azonos típusú Tömbök a tömb is objektumként viselkedik new-val kell inicializálhatjuk int tomb[] = new int[1]; létrehozáskor is inicializálhatjuk int tomb[] = { 1, 2, 300000 ; Tömbök mérete konstans a length attribútum tartalmazza a hosszát int meret = tomb.length; az elemek a [ ] operátorral érhető el a 0.. length -1 tartományban Tömb elemek bejárása while int tomb[] = new int[10]; int i = 0; while(i < tomb.length){ tomb[++i] = i*i; 4
Tömb elemek bejárása for Tömb elemek bejárása for each int tomb[] = new int[10]; for( int i = 0; i < tomb.length; ++i ){ tomb[i] = i * i; int tomb[] = { 1, 3, 2, 5, 4 ; for( int i : tomb ){ System.out.println(i); Tömbök int[] intarray = new int[5]; // vagy int intarray[] = new int[5]; int i = intarray[2]; int l = intarray.length; deklaráció és inicializálás egy lépésben: int[] intarray = { 1, 3, 2, 4, 7 ; korábban deklarált tömb átdefiniálása: intarray = new int[] { 3, 2, 4, 8, 7, 5 ; Sztringek String osztály: Tartalma a létrehozás után nem módosítható, Idézőjelek közé tett szövegből mindig String lesz, pl. String s = abc ; System.out.println( Hello ); Példák: String s = abc ; int i = s.compareto( cde ); System.out.println(String.valueOf(i) + s.substring(1,2) + ef ); int l = s.length(); Operátorok Vezérlőszerkezetek A legtöbb művelet a C++-hoz hasonlóan működik + - * / % >> << &&! & ^ > >= < <= ==!=?: () (típus) new Leglényegesebb különbségek: nincs operator overloading nincs -> operátor: mindig pontot használunk nincs :: operátor (aminek a bal oldalán nem példány, hanem osztály áll): ehelyett is pontot használunk instanceof operátor: igaz, ha az A objektum a B osztály vagy B-ből származó osztály tagja if (A instanceof B) { A legtöbb a C++-ban megszokott módon működik: for while do..while ifelse switch..case..default break continue return Leglényegesebb különbségek: az if után álló feltétel mindig boolean típusú, azaz: int value; if (value) { // Hiba! if (0!= value) { // Így jó! (nincs goto!!!) 5
Goto helyett címkézett ciklusok outer: while (true) { inner: while (true) { break; // kilép a belső ciklusból break inner; // kilép a belső ciklusból break outer; // kilép a külső ciklusból Java osztályok specialitásai Minden osztálynak van: Konstruktora feladata az objektum inicializálása több konstruktor is tartozhat egy osztályhoz minden alkalommal meghívódik amikor létrehozunk egy objektumot közös őse: minden osztály az Object-ből származik (nem kell feltüntetni) Java osztályok specialitásai Tagok Az osztályoknak nincs: másoló konstruktora (helyette más mechanizmus) = operátora destruktora (helyette finalize) Beágyazott objektum class Group { private Employee employees[]; Kezdeti érték int n_emp = 0; Group( ) { employees = new Employee[10]; Explicit helyfoglalás void Add(Employee e) {employees[n_emp++] = e; void Doctor( ) { for(int i = 0; i < n_emp; i++) { employees[i].name = new String( Dr. + employees[i].name); név belülről Minősített elérés más objektumból Metódusok Virtuális metódusok: nincs virtual kulcsszó, minden függvény virtuális ha mégsem akarjuk, hogy egy leszármazott felüldefiniálja, akkor a final kulcsszót használhatjuk Absztrakt metódus: az abstract kulcsszóval abstract class Shape { public abstract void draw(); // nincs törzs public final void move(int newx, int newy) { abstract metódusa csak abstract osztálynak lehet abstract osztály nem példányosodhat Osztályváltozók C++ Java class Dolgozo { class Dolgozo { int kor; int kor; static int nygdjkrhtr; static int nygdjkrhtr =65; int hatra() { int hatra() { return (nygdrkrhtr-kor); return(nygdrkrhtr-kor); ; Az osztály minden példányához tartozik, Külön kell inicializálni int Dolgozo::nygdjkorhtr=65; 6
Osztálymetódusok Osztály változó és metódus C++ Java class Window { class Dolgozo { static void WndProc(); static int nygdjkrhtr =65; ; static void NyEmel( ) { nygdjkrhtr++; wnd.lpfnwndproc =WndProc; RegisterClass( &wnd ) Dolgozo.NyEmel(); esemény Windows lpfnwndproc WndProc() C,PASCAL függvény Alkalmazás A static kulcsszóval deklarált változók és metódusok nem egy objektumhoz tartoznak, hanem az egész osztályra közösek. statikus függvények csak statikus függvényeket és változókat használhatnak (nincs implicit this az argumentumok között) meghívásukkor a pont elé nem egy objektum, hanem az osztály nevét kell írni: Dolgozo.NyEmel(); A main függvény Először a main függvény indul, az objektumokat ettől kezdve hozzuk létre Nincs még objektum (nem üzenhetünk senkinek) A main csak statikus lehet public static void main(string args[]) { A main new-val létrehozhat lokális objektumokat, azokon kívül csak a statikus objektumokat érheti el Statikus változók inicializálása Konstans értékadás: class Dolgozo { static int nygdjkrhtr = 65; A statikus változóknak a static initializer adhat kezdőértéket: class AClass { static { // Nincs név, visszatérő érték, semmi // Itt csinálhatunk bármit Hasonlít a konstruktorhoz, de nem egy példányt, hanem az osztályt inicializálja Statikus változók/metódusok jelentősége Adatrejtés Statikus változó = Objektum Orientált globális változó Statikus függvény = Objektum Orientált globális függvény int i = Integer.MAX_VALUE; float rnd = Math.random(); float sinpi = Math.sin( Math.PI ); String s = String.valueOf( 123 ); System.out.println( Az eredmeny ); felesleges részletek és belső állapotok elrejtése különböző hozzáférési szintek public mindenki számára hozzáférhető package az adott package-be tartozó osztályok számára érhető el (alapértelmezett) private csak az osztályon belülről érhető el legyen minden private, amíg nem indokolt publikussá tenni 7
Polimorfizmus a paraméterek típusától függően másként viselkedő függvények void szamol(int ertek); void szamol(complex ertek); felüldefiniált függvény a leszármazott osztályban ugyanazzal a névvel és paraméterekkel definiált függvény @Override jelölő Szemétgyűjtés Java-ban a létrehozott objektumokat nem kell a programnak explicit megsemmisítenie nincs destruktor nincs delete operátor van finalize() metódus: a szemétgyűjtő hívja a megsemmisítés előtt A felesleges objektumok eltüntetéséről a szemétgyűjtő (garbage collector) gondoskodik alacsony prioritással állandóan fut a háttérben figyeli, hogy mely objektumokra nincs már érvényes hivatkozás Öröklődés Java módra Öröklődés Java módra minden osztály az Object-ből származik egy osztálynak csak egy ősosztálya lehet (többszörös öröklődés nincs) a leszármazott osztály örökli a paraméter nélküli konstruktort a paraméteres konstruktorokat NEM! az ősosztály konstruktorát a super() segítségével hívhatjuk meg az osztály (class) mellett bevezeti az interface-t ez majdnem olyan, mint egy osztály, de: csak publikus, absztrakt függvényeket tartalmaz csak final változókat tartamaz nem lehet példányosítani az interfacet implementáló osztálynak az interface minden függvényét meg kell valósítani ős-interface -ből több is lehet egy osztálynak az őstípus mellett Öröklődés abstract class shape { protected int x, y, col; void move(int dx, int dy) { int c = col; col = 0; draw(); x += dx; y += dy; col = c; draw(); abstract void draw( ); shape( int x0, int y0, int c0 ) { x = x0; y = y0; col = c0; class line extends shape { private int xe, ye; line( int x1, int y1, int x2, int y2, int c ) { super( x1, y1, c ); xe = x2; ye = y2; void draw( ) { Öröklés szerepei C++ -ban Kód, változó átörökítés class Shape { int x, y, col; void SetColor( int c ) { col = c; Közös interfész megvalósítása: pl. heterogén szerk. class Shape { virtual void Draw()=0; class Line : public Shape { virtual void Draw(); class Rect : public Shape { virtual void Draw(); class Line : public Shape { class Rect : public Shape { Shape * shapes[10]; shapes[0] = new Line(); shapes[1] = new Rect(); for(int i = 0; i < 2; i++) shapes[i] -> Draw( ); 8
A második funkció interfésszel Interfészek többszörös öröklés helyett interface ShapeLike { void Draw( ); class Line implements ShapeLike { void Draw(); class Rect implements ShapeLike { void Draw(); void Display( ShapeLike s ) { s.draw( ); Display( new Rect() ); Display( new Line() ); Manager csoport Assign( ) Employee név, fizetés Set( ) TempMan Temporary idő SetTime( ) Manager csoport Assign( ) Employee név, fizetés Set( ) Temporary idő SetTime( ) TempMan idő SetTime( ) TempLike SetTime( ) Interface megvalósítás TempMan class Employee { class Manager extends Employee { interface TempLike { int GetTime( ); void SetTime( int t ); class Temporary extends Employee implements TempLike { int emp_time; Temporary( String nam, long sal, int time ) { super(nam, sal); // for base class constructor emp_time = time; public void Show( ) { super.show( ); System.out.print( Until "+String.valueOf(emp_time)); public int GetTime( ) { return emp_time; public void SetTime( int t ) { emp_time = t; class TempMan extends Manager implements TempLike { int emp_time; TempMan( String nam, long sal, int time, int level ) { super(nam, sal, level); //for base class constructor emp_time = time; public void Show( ) { super.show( ); System.out.print( Until "+String.valueOf(emp_time)); public int GetTime( ) { return emp_time; public void SetTime( int t ) { emp_time = t; Az ősök őse: Object Példa: heterogén tömb public class Object { public Object( ) { protected Object clone( ) { // copy constructor, ha nem definiáljuk át // csak belülről működik protected void finalize( ) { // destruktor, protected public boolean equals( Object o ) { // összehasonlítás public final Class getclass( ) { // melyik osztályból definiáltuk ezt: végleges public String tostring( ) { // konverzió string-re (kiíráshoz) public class MyArray { protected Object[] elements; MyArray(int size) { elements = new Object[size]; Object getitem(int idx) { return elements[idx]; void putitem( int idx, Object o ) { elements[idx] = o; 9
Öröklődés: Klónozható tömb public class MyCloneableArray extends MyArray { MyCloneableArray(int size) { super(size); // Őstípus konstruktora, először ezt kell hívni public Object clone() { MyCloneableArray newarray = new MyCloneableArray(elements.length); for (int i = 0; i < elements.length; i++) newarray.elements[i] = elements[i]; return newarray; Besorolás a klónozhatók csoportjába // public interface Cloneable { // public Object clone(); // ; public class MyCloneableArray extends MyArray implements Cloneable { MyCloneableArray(int size) { public Object clone() { MyCloneableArray newarray = new MyCloneableArray(elements.length); Import, package-ek Fontos beépített package-ek Package: Java osztályok és al-package-ek halmaza package graphics; public class Circle { Package vagy class importálása: import graphics.*; import java.lang.*; import java.applet.applet; CLASSPATH graphics/ Circle.class Azonos packageben levő osztályokat nem kell importálni java.applet Az Applet osztály és egyéb, appletekkel kapcsolatos eszközök java.awt (Abstract Windowing Toolkit) GUI osztályok: ablakok, ablak elemek java.awt.event Eseménykezeléssel kapcsolatos osztályok és interface-ek java.awt.image Képek megjelenítése, feldolgozása java.io File és más adatfolyamok kezelése Fontos beépített package-ek II. java.lang Egyszerű adattípusok osztály megfelelői (Integer) Szálak (Thread) kezelése Stringek kezelése (String és StringBuffer) java.net Hálózatkezelés: Socket, URL, HTTP kapcsolat, stb. java.rmi (Remote Method Invocation) Távoli eljárások hívása (CORBA-szerű) java.util Kollekciók, naptár, helyi információk, stb. És még nagyon sokan mások 10