[[oktatas:programozás:java|< Java]] ====== Java nyelv jellemzők ====== * **Szerző:** Sallai András * Copyright (c) 2009, Sallai András * Szerkesztve: 2009-2023 * Licenc: [[https://creativecommons.org/licenses/by-sa/4.0/|CC BY-SA 4.0]] * Web: https://szit.hu ===== JVM utasítások ===== Néhol Java Virtual Machine Language néven említik, de ez nem terjedt el. Java alacsony szintű nyelv vagy bájtkód. Az operációs rendszeren közvetlenül nem futtatható kód. A Java Runtime Environment fordítja futtatható kóddá. ===== A változók élettartalma ===== === Példány változó === Egyed, példány, instance változó. Egy példányosított osztály egy változója. Az osztály tulajdonságainak vagy mezőinek is szokás nevezni. A példányváltozót egy osztályban hozunk létre, de metóduson kívül. Amikor helyet foglalunk egy objektumnak az osztály összes változója számára megtörténik a helyfoglalás a halomterületen. Hozzáférés-módosítókat használhatunk ezeken a változókon. A példányváltozók az osztály összes metódusa számára hozzáférhető. Ajánlott private elérésűként megadni. A példányváltozóknak van kezdő értékük. Számok esetén ez 0, boolean esetén ez false, objektumhivatkozás null értéket vesz fel. objektumHivatkozas.valtozoNev === Statikus változó === Statikus, osztály vagy static változó. Példányosítás nélkül használható változó. A változó helyett néha statikus mező, esetleg osztályváltozó néven is használjuk. A static módosítóval hozzuk létre, osztályon belül, de metóduson kívül. A váltózóból mindig csak egy másolat jön létre. Általában állandóként szoktuk használni. Az állandót public/private, final és static módosítókkal szoktuk megadni. A static változókat a statikus memóriaterületen tároljuk. Akkor jönnek létre, amikor elindul a program. A program befejezésével együtt megszűnnek. Alapértelmezett értékei mint a példányváltozók. Ha egy statikus tagot final-ként adunk meg, akkor a nevét nagybetűvel szokás írni. === Lokális változó === Egy metódusban -- esetleg konstruktorban vagy blokkban -- létrehozott változó. Csak az adott metódusban él, annak végrehajtása után már nem hivatkozhatunk a változóira. Maga a változó a memóriában is csak akkor jön létre amikor belépünk a metódusba. A lokális változót nem illetjük mező elnevezéssel. Hasonló szerepe van még a paraméterváltozóknak is. A hozzáférés-módosítók nem alkalmazhatók. Mindig a veremben (stack) kerül lefoglalásra. Ha példányosítunk lokálisan egy osztályt, a változó szintén a veremben jön létre, de a hozzátartozó tagok, a halom (heap) terülten lesznek tárolva. A lokális változóknak alapértelmezésként nem kapnak kezdőértéket, ezért az első felhasználás előtt elő kell készíteni azokat. === Paraméter változó === Emlékezzünk vissza, hogy a main metódus aláírása public static void main(String[] args). Az args a paraméterváltozó. ==== Változók élettartalma a gyakorlatban ==== === Instance változók === class Szemely { String Nev; int Kor; } class Valotozok { public static void main(String[] args) { Szemely Joska = new Szemely(); Joska.nev = "Nagy József"; Joska.kor = 25; System.out.println(Joska.Nev); System.out.println(Joska.Kor); } } === Static változók === class Szemely { static String nev; static int kor; } class Valotozok { public static void main(String[] args) { Szemely.Nev = "Nagy József"; Szemely.Kor = 25; System.out.println(Szemely.Nev); System.out.println(Szemely.Kor); } } === Local változó === class Valotozok { public static void main(String[] args) { String Nev; int Kor; Nev = "Nagy József"; Kor = 25; System.out.println(Nev); System.out.println(Kor); } } ===== A csomagolóosztályokról ===== A csomagoló osztály típussal létrehozott változók az értéket példány vagy osztályváltozókban tárolják, és rendelkeznek metódusokkal. A primitív típusok nem rendelkeznek metódusokkal. A csomagolóosztály-típusokat bárhol használhatunk, de néhány helyen kötelező. Ilyenek a vermek (stack), vektorok (vector), object I/O, szerializáció, stb. import java.util.Stack; class Program01 { public static void main(String [] args) { Stack verem = new Stack(); int a = 5; verem.push(a); } } Az int primitív típus itt nem használható például a Stack adatszerkezet használata esetén (lásd később): Stack verem = new Stack();. A burkoló vagy csomagoló osztályokat angolul (wrapper [ˈræpə]). ===== Az instanceof operátor ===== Az operátorok fejezetben az instanceof operátort az Integer változóval mutattuk be, aminek nem sok értelme van, mert más típust nem is írhatunk az instanceof jobboldalára. Annál több értelme lehet ha egy általunk létrehozott osztályon vizsgáljuk, vagy annak egy származtatott változatán. A következő példában megnézhetjük, hogy a joska objektum melyik osztályból lett származtatva: class Dolgozo { String nev; int kor; } class Mernok extends Dolgozo { String diploma; } class Program01 { public static void main(String[] args) { Dolgozo joska = new Dolgozo(); System.out.println(joska instanceof Mernok); } } ===== Az Extra csomag ===== Sokan használják **Angster Erzsébet** által létrehozott **Extra** nevű csomagot, amely kényelmesebbé teszi a bekéréseket. Az extra csomag azonban nem a JDK részre, ne felejtsük el. Azt telepíteni kell vagy csak egyszerűen a használt programunk mellet létrehozni egy extra könyvtárat, majd abba menteni Console.java néven. /* * javalib könyvtár * Csomag: extra * Console.java * * Angster Erzsébet: OO tervezés és programozás, Java 1. kötet * 2002.09.01. * * Beolvasás a konzolról: * * String readLine() * String readLine(String str) * char readChar() * char readChar(String str) * int readInt() * int readInt(String str) * int readLong() * int readLong(String str) * double readDouble() * double readDouble(String str) * void pressEnter() */ package extra; import java.io.*; public class Console { // Az osztályból nem lehet példányt létrehozni: private Console() { } /* Pufferező karakterfolyam, melynek forráshelye a konzol. * A readLine metódus használja. */ private static BufferedReader be = new BufferedReader(new InputStreamReader(System.in)); // --------------------------------------------------------- // String beolvasása sor végéig: public static String readLine() { String beString = ""; try { beString = be.readLine(); } catch (IOException e) { } return beString; } // --------------------------------------------------------- // String beolvasása sor végéig, előtte prompt: public static String readLine(String str) { System.out.print(str); return readLine(); } // --------------------------------------------------------- // Karakter beolvasása: public static char readChar() { while(true) { try { return readLine().charAt(0); } catch(IndexOutOfBoundsException e) { System.out.println("Nem karakter! Ujra!"); } } } // --------------------------------------------------------- // Karakter beolvasása, előtte prompt: public static char readChar(String str) { System.out.print(str); return readChar(); } // --------------------------------------------------------- // Egész (int) beolvasása: public static int readInt() { while(true) { try { return Integer.parseInt(readLine().trim()); } catch(NumberFormatException e) { System.out.println("Nem egesz! Ujra!"); } } } // --------------------------------------------------------- // Egész (int) beolvasása, előtte prompt: public static int readInt(String str) { while(true) { System.out.print(str); try { return Integer.parseInt(readLine().trim()); } catch(NumberFormatException e) { System.out.println("Nem egesz! Ujra!"); } } } // --------------------------------------------------------- // Egész (long) beolvasása: public static long readLong() { while(true) { try { return Long.parseLong(readLine().trim()); } catch(NumberFormatException e) { System.out.println("Nem egesz! Ujra!"); } } } // --------------------------------------------------------- // Egész (long) beolvasása, előtte prompt: public static long readLong(String str) { while(true) { System.out.print(str); try { return Long.parseLong(readLine().trim()); } catch(NumberFormatException e) { System.out.println("Nem egesz! Ujra!"); } } } // --------------------------------------------------------- // Valós (double) beolvasása: public static double readDouble() { while(true) { try { return Double.parseDouble(readLine().trim()); } catch(NumberFormatException e) { System.out.println("Nem valos! Ujra!"); } } } // --------------------------------------------------------- // Valós (double) beolvasása, előtte prompt: public static double readDouble(String str) { while(true) { System.out.print(str); try { return Double.parseDouble(readLine().trim()); } catch(NumberFormatException e) { System.out.println("Nem valos! Ujra!"); } } } // --------------------------------------------------------- // Várás az ENTER lenyomására: public static void pressEnter() { System.out.print(""); readLine(); } } ===== Várakozás egy billentyűnyomásra ===== Az alábbi példa bemutatja hogyan várakozhatunk egy billentyűlenyomásra. A "billentyűlenyomás" nem teljes kifejezés, mert csak az "Enter" billentyűt nyomhatjuk le. import java.io.IOException; import java.util.Scanner; class Program01 { public static void main(String args[]) throws IOException { Scanner bevitel = new Scanner(System.in); System.out.print("Egész szám: "); int a = bevitel.nextInt(); System.out.println(a); System.in.read(); } } class Program01 { public static void main(String args[]) { System.out.println("A folytatashoz nyomjon egy Entert"); System.console().readLine(); } } ===== Unicode karakterek kiíratása ===== class Program01 { private static void tabla2() { for(int i=0x0021;i<=0x01ff; i++) System.out.printf("| %x %c |", i, (char) i); } public static void main(String[] args) { tabla2(); } } Ezek után képernyőre küldhető: System.out.println("\u0171"); System.out.println((char)0x63A5); ===== Garbage Collector ===== A Java Garbage Collector vagy röviden csak GC, egy szemétgyűjtő. A nem használt objektumok számára lefoglalt memóriaterületet felszabadítja. A GC időnként lefut magától, ha kevés a memória vagy túl sok nem használt objektum van. A GC futását kérhetjük a JVM-től a következő utasítással: System.gc(); Ami persze nem ajánlott, bízzuk ezt a JVM-re. A GC-t a JVM magától futtatja, ha kevés a memória vagy sok a felhalmozodott objektum. Van aki szerint a fokozott biztonsági igényű vezérlést nem szabad Java-ban írni, mert a GC is lefagyhat, előfordulhat hiba. A C nyelv esetén nekünk kell mindenről gondoskodni. Több információ a memóriakezelésről: * [[http://www.oracle.com/technetwork/java/javase/memorymanagement-whitepaper-150215.pdf|Memory Management in the Java HotSpot™ Virtual Machine]] (2021) ===== VisualVM ===== VisualVM segítségével megnézhetjük hogyan használja egy Java program a gépet, a processzort, a memóriát, stb. Linux alatt a telepítése egyszerű: apt install visualvm Indítása: jvisualvm A program maga egy Java alapú program, amely letölthető innen: * https://visualvm.github.io/ (2021) ===== Változó hosszúságú argumentumok ===== A típus után, három darab ponttal jelezhetjük, hogy az adott típusból akár több is megadható. Az alábbi példában több double típust is megadhatunk a csinal() függvény hívásakor. Az eredmény egy kollekció lesz, amit bejárunk for() utasítással. public class Program01 { public static void csinal(double... szamok) { for(double szam : szamok) { System.out.printf("%20f\n", szam); } } public static void main (String args[]) { csinal(4, 5); } } Ugyanez String típussal: public class Program01 { public static void csinal(String... szavak) { for(String szo : szavak) { System.out.printf("%20s\n", szo); } } public static void main (String args[]) { csinal("alma", "szilva"); } } ===== Számliterálisok a Java SE 7-től ===== A Java SE 7 verzióban fejlesztették a számliterálisok megadási lehetőségeit. A 102-őt korábban így adhattuk meg: int x = Integer.parseInt("1100110", 2); Ezen túl megadható így is: int x = 0b1100110; class Program01 { public static void main(String[] args) { int a = 0b1100110; System.out.println(a); long b = 2_143_234L; System.out.printf("%d\n", b); int c = 0b0001_1100_0111_0011; System.out.println(c); } } ===== Fok jel ===== W7 alatt a ° karakter nem jelenik meg a konzolos felületen. Ezért használjuk a következők valamelyikét: System.out.println((char)345); System.out.println("\u0159"); A 345 egy decimális szám. Ugyanaz a szám hexadecimálisan: 159. ===== A Java verzió kiíratása ===== Minden Java verzióval működik: System.out.println(System.getProperty("java.specification.version")); 9-s verziótól: System.out.println(System.getProperty("java.version"));