JAVA Tutoriál Ing. Lumír Návrat, A1018 Tel: +420 59 732 3252 Email: lumir.navrat@vsb.cz ICQ: 64100582 Materiály vycházejí z podkladů doc. Ing. Miroslava Beneše , Ph.D. (28.5.2005)
Doporučená literatura Učebnice Eckel, B.: Myslíme v jazyce Java. Grada, 2000. http://www.eckelobjects.com/ Herout, P.: Učebnice jazyka Java. KOPP, 2000. Pecinovský R.: Myslíme objektově v jazyku Java 5.0 Internet Studijní materiály k tutoriálu http://www.cs.vsb.cz/navrat/vyuka/esf/ Slidy z předchozích kurzů výuky jazyka JAVA na katedře http://www.cs.vsb.cz/java/
Programové vybavení http://java.sun.com Java SE Development Kit + dokumentace http://ant.apache.org Nástroj pro správu projektů Vývojová prostředí: Netbeans IDE, Eclipse, Borland JBuilder,Intelli JIdea... Editory: JEdit, PSPad, TextPad, gvim, ..., Notepad
Vznik jazyka Motivace: Jazyk pro tvorbu programového vybavení pro spotřební elektroniku – pračky, diáře, mikrovlnné trouby, ... Požadavky: nezávislost na procesoru, spolehlivost, jednoduchost, robustnost. 1990 - James Gosling, Sun – jazyk Oak 1993 – Internet + WWW = nové aplikace Sun HotJava – prohlížeč s applety 23. 1. 1996 – JDK 1.0 – první implementace 2004 – JDK 1.5 -> JDK 5 Tiger – nové prvky jazyka prosinec 2006 – JDK 6 – aktuální verze
Překlad a spuštění programu Test.java zdrojový program zpětný překlad javac Test.java Test.class javap Test *.html java Test javadoc Test.java výsledky JIT dokumentace JIT – Just-In-Time překlad
Program Ant Implementován v prostředí Java Možnost rozšiřování implementace akcí v jazyce Java definované rozhraní Činnost se řídí souborem v XML build.xml Integrován do vývojových prostředí Eclipse, Netbeans, …
Struktura řídicího souboru project 1 1 n n name default basedir description property target name value location name depends if unless description 1 n task
Struktura řídicího souboru <?xml version="1.0"?> <project name="Test" default="all" basedir="."> <property name="src" location="src"/> <property name="build" location="classes"/> <target name="all" depends="init,compile,run"/> <target name="init"> <mkdir dir=“${build}”/> </target> <!-- … --> </project>
Spuštění programu ant ant compile ant –buildfile test.xml řídicí soubor build.xml provedení implicitního cíle ant compile provedení zadaného cíle ant –buildfile test.xml použití zadaného řídicího souboru ant –Dbuild.compiler=jikes nastavení hodnoty vlastnosti ant –logfile build.log uložení logu do souboru
Základní úlohy Práce se soubory <mkdir dir="${dist}/lib"/> <delete dir="lib"/> <delete> <fileset dir="." includes="**/*.bak"/> </delete> <copy file="myfile.txt" tofile="mycopy.txt"/> <move file="file.orig" todir="${dist}/lib"/>
Základní úlohy Překlad <javac srcdir="${src}" destdir="${build}" classpath="xyz.jar" debug="on" /> <javac srcdir="${src}" destdir="${build}"> <classpath> <pathelement path="${classpath}"/> <pathelement location="lib/helper.jar"/> </classpath> </javac>
Základní úlohy Spuštění programu <java classname="test.Main" > <arg value="-h"/> <classpath> <pathelement location="dist/test.jar"/> <pathelement path="${java.class.path}"/> </classpath> </java>
Zdrojový program package Priklady; // soubor Priklady/Test.java public class Test { public static void main(String args[]) System.out.println(“Ahoj!”); }
Cílový program public class Priklady.Test extends java.lang.Object { public Priklady.Test(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Ahoj! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return }
Datové typy Primitivní datové typy Referenční datové typy boolean False, True char ‘A’, ‘\n’ int, long 123, 5L float, double 3.14f, 6.67e-19 Referenční datové typy String “abc”, “ab\tcd” pole String[ ], int[ ] [ ] Objekty Boolean, Integer, Float, … objektové obálky primitivních typů. Od verze 5.0 existuje automatická konverze
Operátory Aritmetické Relační Logické Přiřazení x+y, x-y, x*y, x/y, x%y, -x Relační x == y, x != y, x < y, x <= y, x > y, x >= y Logické x && y, x || y, !x Přiřazení x = y x += y, …, x++, x--
Příkazy Podmíněný příkaz Cyklus if ( podmínka ) příkaz - Podmíněný příkaz if ( podmínka ) příkaz if ( podmínka ) příkaz else příkaz Cyklus while( podmínka ) příkaz do příkaz while ( podmínka ) + - + + -
Příkazy for( inicializace; podmínka; krok ) příkaz break, continue for( int i = 0; i < 10; i++ ) { System.println(“i=“ + i); } for( Item i : kolekce) { System.println(“i=“ + i.toString()); } //Od verze JAVA 5.0 break, continue for( int i = 0; i < 10; i++ ) { if( a[i] == x ) break; - +
Program public class VypisParametru { public static void main(String[] args) { for( int i = 0; i < args.length; i++ ) { System.out.println(i + ”: “ + args[i]); } }
Praktické cvičení – cviceni1.zip Úloha 1 - Překlad a spuštění ukázkové třídy Rozbalte v pracovním adresáři soubor priklad1.zip. Prostudujte soubor Pokus.java. Spusťte program ant, jenž vytvoří soubor Pokus.class a spustí jej. Úloha 2 - Vytvoření vlastního programu Na základě ukázkového programu vytvořte program pro řešení kvadratické rovnice, který z hodnot proměnných a, b, c typu double vypočítá hodnoty kořenů rovnice ax^2+bx+c=0. Hodnoty proměnných a, b, c nastavte přímo v programu. Pro výpočet druhé odmocniny použijte volání funkce Math.sqrt(x).
Řešení: Kvadratická rovnice static void kr(double a,double b,double c) { double d = b * b – 4 * a * c; if( d < 0 ) System.out.println(“Nemá reálné kořeny”); else if( d == 0 ) { double x = - b / (2*a); System.out.println("x=" + x); } else { double x1 = (-b + Math.sqrt(d)) / (2*a); double x2 = (-b – Math.sqrt(d)) / (2*a); System.out.println("x1=" + x1); System.out.println("x2=" + x2); } }
Praktické cvičení – cviceni2.zip Úloha 1 – Prostudování práce s parametry příkazového řádku Rozbalte v pracovním adresáři soubor priklad2.zip. Prostudujte a vyzkoušejte způsob práce s parametry příkazové řádky, včetně chybové vstupu (Priklad1.java) Úloha 2 – Seřazení obsahu pole Vytvořte program, který vytiskne seřazené pole celočíselných hodnot zadaných jako parametry. (Priklad2.java) Úloha 3 – Práce se standardním vstupem Prostudujte práci se standardním vstupem Upravte program pro výpočet kvadratické rovnice, aby načítal data ze vstupu.
Dotazy
Třídy a objekty T C E O
Co mají společného? Vlastnosti (stav) Operace (chování) Vztahy souřadnice středu x, y barva obsah, obvod Operace (chování) přesunutí na jinou pozici n-násobné zvětšení a zmenšení vykreslení na obrazovku Vztahy sousedí, překrývají se, ...
V čem se liší? Druh obrazce Specifické vlastnosti Hodnoty vlastností čtverec, trojúhelník, elipsa Specifické vlastnosti délka strany čtverce velikosti poloos elipsy Hodnoty vlastností konkrétní souřadnice, barva, ... Způsob provedení operací vykreslení na obrazovku
Grafická reprezentace třídy Jméno třídy Zlomek Vlastnosti čitatel jmenovatel Zlomek přičti(Zlomek jinýZlomek) Zlomek násob(Zlomek jinýZlomek) void normalizuj() Operace
Objekt = instance třídy Zlomek čitatel jmenovatel z1 : Zlomek čitatel = 2 jmenovatel = 3 Zlomek přičti(Zlomek jinýZlomek) Zlomek násob(Zlomek jinýZlomek) void normalizuj() z3 : Zlomek z2 : Zlomek čitatel = 1 jmenovatel = 2 čitatel = -6 jmenovatel = 4
Třídy v jazyce Java class Zlomek { // instanční proměnné int citatel; int jmenovatel; // metody Zlomek nasob(Zlomek jiny) { citatel *= jiny.citatel; jmenovatel *= jiny.jmenovatel; } }
Vytvoření instance třídy public static void main(String[] args) { Zlomek z = new Zlomek(); // nastavení instančních proměnných z.citatel = 2; z.jmenovatel = 3; // volání metody z.nasob(z); // z *= z } reference
Jak se instance zruší? Pascal, C, C++ – je třeba volat speciální operaci, která uvolní paměť: Pascal: Dispose(ptr) C: free(ptr); C++: delete ptr; Java, .NET – automatická správa paměti (garbage collector) paměť se uvolní automaticky, pokud na ni neexistuje žádný odkaz
Inicializace objektu Zajištění definovaného stavu objektu po jeho vytvoření všechny proměnné objektu se nastaví na nulu je-li uvedena inicializace, provede se nastavení class Test { int x; // poč. hodnota je 0 int y = 10; // poč. hodnota je 10 int m() { int z; // POZOR! zde to neplatí! return z + 1; // chyba – neinicializovaná } // proměnná ‘z’ }
Konstruktor Zajištění inicializace objektu po vytvoření public class Zlomek { Zlomek(int citatel, int jmenovatel) { this.citatel = citatel; this.jmenovatel = jmenovatel; } … Zlomek z1 = new Zlomek(3, 4); // ¾ Zlomek z2 = z1.pricti(new Zlomek(1,2)); není typ výsledku! odkaz na aktuální objekt
Příklad public class Citac { int hodnota = 0; Citac(int pocatek) { hodnota = pocatek; } void krok() { hodnota++; } public static void main(String args[]) { Citac c = new Citac(10); c.krok(); System.out.println(c.hodnota); // 11 }
Jak si hlídat svá data? public class Citac { // veřejné metody public void nastavHodnotu(int nova) { hodnota = nova; } public int vratHodnotu() { return hodnota; public void krok() { hodnota++; } // soukromá proměnná private int hodnota = 0; ...
Jak si hlídat svá data? public class Test { public static void main(String args[]) { Citac c = new Citac(); // c.hodnota = 10; -- není přípustné c.nastavHodnotu(10); c.krok(); System.out.println(c.vratHodnotu()); }
Statické členy třídy Instanční proměnné a metody jsou vázané vždy na nějaký objekt obj.proměnná, obj.metoda() Proměnné a metody třídy společné pro všechny instance Třída.proměnná, Třída.metoda() označují se klíčovým slovem static static int počet; static void main(String[] args) {…}
Příklad public class Test { private static int pocet = 0; // vrátí počet vytvořených instancí třídy public static int pocetInstanci() { return pocet; } public Test() { pocet++; } ...
Příklad - pokračování ... public static void main(String args[]) { System.out.println(“Počet instanci = “ + Test.pocetInstanci()); Test t2 = new Test(); }
Dědičnost Obrazec int x int y presun(x1, y1) Čtverec Elipsa int a int b
Dědičnost class Obrazec { int x, y; void presun(int x, int y) { this.x = x; this.y = y; } } class Ctverec extends Obrazec { int a; }
Dědičnost Je-li něco čtverec, pak je to i obrazec Je-li něco obrazec, nemusí to být čtverec Ctverec c = new Ctverec(); c.presun(10, 20); // dědí metodu presun() Obrazec o = c; // lze přiřadit Obrazec o = new Ctverec(); // o.a = 5; // nepřípustné // Ctverec c = o; // nepřípustné
Dědičnost Není-li uvedena bázová třída, použije se java.lang.Object String toString() převod objektu na textovou reprezentaci boolean equals(Object obj) porovnání s jiným objektem int hashcode() číselný kód objektu Object clone() vytvoření kopie objektu
Zapouzdření prvků třídy Soukromé proměnné/metody – private přístupné pouze z vlastních metod Chráněné proměnné/metody – protected přístupné i z metod zděděných tříd Veřejné proměnné/metody – public přístupné i z metod jiných objektů
Konstruktory a dědičnost Konstruktor musí nejprve zavolat zděděný konstruktor – zajištění správné inicializace class Obrazec { public Obrazec(int x, int y) { this.x = x; this.y = y; } protected int x, y; } class Ctverec extends Obrazec { public Ctverec(int x, int y, int a) { super(x, y); this.a = a; } protected int a; }
Konstruktory a dědičnost Není-li zděděný konstruktor zavolán, zajistí se volání implicitního konstruktoru class Citac { public Citac() { hodnota = 10; } protected int hodnota; } public class CitacSKrokem extends Citac { public CitacSKrokem(int krok) { // super() -- zavolá se automaticky this.krok = krok; } protected int krok; public void volitelnyKrok() { nastavHodnotu(vratHodnotu()+krok); } }
Příklad class Test { public static void main(String[] args) { CitacSKrokem lepsiCitac = new CitacSKrokem(5); lepsiCitac.volitelnyKrok(); System.out.println(lepsiCitac.vratHodnotu()); lepsiCitac.krok(); }
Konstruktory a dědičnost Neexistuje-li žádný konstruktor, vytvoří se prázdný implicitní konstruktor class Citac { // public Citac() {} -- vytvoří se protected int pocet; } Jak zajistit, aby nebylo možné vytvořit instanci třídy voláním operátoru new? class Citac { private Citac() {} ... }
Evidence osob public class Osoba { public String login; public String jmeno; public String prijmeni; } Problémy? Osoba os = new Osoba(); System.out.println(os); os.login = “bon007”;
1. problém - inicializace class Osoba { public Osoba(String l,String jm,String p) { login = l; jmeno = j; prijmeni = p; } … } Osoba os = new Osoba(“aaa000”, “Johnny”, “Walker”);
2. problém - zobrazení System.out.println(os); Osoba@2ae3645f class Osoba { … public String toString() { return jmeno + " " + prijmeni; } } System.out.println("os = " + os); os = Johnny Walker Kdo je to?
3. problém - zapouzdření public class Osoba { … private String login; public String getLogin() { return login; } public void setLogin(String login) { // tady by měla být kontrola this.login = login; } … }
4. problém - identita Osoba o1 = new Osoba(“007”,“James”,“Bond”); Platí o1 == o2 ? public boolean equals(Object obj) { if( obj instanceof Osoba ) return login.equals(((Osoba)obj).login); return false; } Ne! Různé objekty
Příklad - Dědičnost class Student extends Osoba { public Student(String login, String jmeno, String prijmeni, String obor) { super(login, jmeno, prijmeni); this.obor = obor; } public String getObor() { return obor; } public void setObor(String ob) { obor = ob; } private String obor; }
Praktické cvičení – cviceni3.zip Úloha 1 – Práce s třídami a objekty Rozbalte v pracovním adresáři soubor cviceni3.zip. Prostudujte a vyzkoušejte způsob práce s třídou Zlomek (Priklad1.java) Vytvořte třídu Complex, která bude reprezentovat komplexní číslo s operacemi sčítání, odčítání a násobení Upravte řešení kvadratické rovnice tak, aby pracovalo s typem Complex
Příklad - Obrazce Obrazec obvod() obsah() Kruh Obdélník r a, b Čtverec
Definice třídy Obrazec class Obrazec { double obvod() { return 0.0; } double obsah() { Jak vypadá Obrazec? Je to ABSTRAKCE!
Abstraktní třídy abstract class Obrazec { public abstract double obvod(); public abstract double obsah(); } class Kruh extends Obrazec { Kruh(double r) { this.r = r; } double obvod() { return 6.28 * r; } double obsah() { return 3.14 * r * r; } double r; } new Obrazec()
Abstraktní třídy class Obdelnik extends Obrazec { Obdelnik(double a, double b) { this.a = a; this.b = b; } double obvod() { return 2*(a+b); } double obsah() { return a*b; } } class Ctverec extends Obdelnik { Ctverec(double a) { super(a, a); } }
Rozhraní interface Obrazec { double obvod(); double obsah(); } class Kruh implements Obrazec { Kruh(double r) { this.r = r; } double obvod() { return 6.28 * r; } double obsah() { return 3.14 * r * r; } double r;
Rozdíly Abstraktní třída Rozhraní může obsahovat instanční proměnné může obsahovat konkrétní metody lze rozšiřovat pouze jednu třídu Rozhraní nesmí obsahovat proměnné všechny metody jsou public abstract lze implementovat více rozhraní
Pozdní vazba Včasná vazba Pozdní vazba static boolean vetsi(Obrazec o1, Obrazec o2) { return o1.plocha() > o2.plocha(); } Která metoda plocha() se volá? Včasná vazba výběr volané metody v době překladu podle typu reference, přes kterou metodu voláme Pozdní vazba výběr volané metody v době běhu podle typu objektu, na který reference ukazuje
Příklad použití pozdní vazby void print(Object obj) { print obj.toString(); } class Object { public String toString() {…} Osoba@24f32e } class Osoba extends Object { public String toString() {…} Johnny Walker }
Přetěžování operací Public class Citac { int hodnota = 0; void krok() { n++; } void krok(int d) { hodnota += d; } } přetížená operace 1 + 1 2.5 + 3.14 “abcd” + “efgh” přetížený operátor +
Praktické cvičení – cviceni3.zip Úloha 3 – Rozšíření schopností třídy Complex Upravte třídu Complex tak aby implementovala zde uvedené přetížené metody class Complex { public Complex() { … } public Complex(double r) { … } public Complex(double r, double i) { … } public add(Complex c) { … } public add(double r) { … } public add(double r, double i) { … } … }
Prostory jmen – motivace spolupráce více programátorů na jednom projektu class MojeTrida ??? možnost distribuce knihoven tříd použití implementací z různých zdrojů v jedné aplikaci new Seznam() ???
Prostory jmen Jak zajistit jednoznačnost názvů? konvence pro pojmenování class MB_Trida centrální přidělování nerealizovatelné využití existujících jednoznačných názvů jméno domény organizace cs.vsb.cz, sun.com, ...
Jména balíků tříd (packages) java.lang . String . substring() jméno balíku jméno třídy jméno metody cz.vsb.cs.katis . Student . getLogin() jméno balíku jméno třídy jméno metody
Vyhledávání balíků umístění přeložených tříd soubory .class archivy .jar (odpovídá formátu .zip) nastavení cest pro vyhledávání set CLASSPATH=.;c:/java/lib;c:/java/lib/mylib.jar java –classpath ./classes vyuka.java.Priklad1 struktura adresáře odpovídá jménu balíku ./classes/vyuka/java/Priklad1.class
Definice příslušnosti k balíku package cz.vsb.cs.katis; public class Student { String login; public String getLogin() { return login; } ... }
Příklad package mujbalicek; public class Citac { ...
Přístup k prvkům balíku Plně kvalifikované jméno Příkaz import – dovoz jedné třídy Příkaz import – dovoz celého balíku Příkaz import – statický import (nově JAVA 5.0) java.util.Date = new java.util.Date(); import java.util.Date; … Date = new Date(); import java.util.*; … Date = new Date(); import static java.math.PI; double r = cos(Math.PI * theta); double r = cos(PI * theta);
Zapouzdření prvků v balíku Třídy a rozhraní označené public přístupné ze všech balíků v souboru .java může být pouze jeden prvek označený public; jméno se musí shodovat se jménem zdrojového souboru Třídy a rozhraní bez označení public přístupné pouze ze stejného balíku v souboru .java jich může být libovolný počet
Zapouzdření prvků ve třídě private dostupné pouze v rámci těla třídy protected dostupné v rámci stejného balíku + třídám, které z aktuální třídy dědí public dostupné z libovolné třídy libovolného balíku bez označení dostupné z libovolné třídy téhož balíku
Kolize ve jménech Odkaz musí být jednoznačný Pozn.: Co když chybí příkaz package? implicitní balík – vše funguje i bez public! import cz.vsb.cs.util.*; import java.util.*; … Date today = new Date(); java.util.Date today = new java.util.Date();
Standardní balíky JDK java.lang nepotřebuje příkaz import, doveze se automaticky základní třídy (Object, Class, String, System, Math, Integer, Thread, ...), rozhraní (Comparable, ...) a výjimky (Exception, ...) System.exit(1); System.out.println( str.toLowerCase() ); int val = Integer.parseInt(str); double rnd = Math.random(); if( Character.isDigit(c) ) …
Standardní balíky JDK java.util pomocné třídy (Currency, Calendar, Date, Random), rozhraní a implementace abstraktních datových typů (List, Set, Map, LinkedList, TreeSet, TreeMap) import java.util.*; System.out.println(new Date()); Arrays.sort(arr);
Standardní balíky JDK java.io java.net java.rmi práce s datovými proudy (soubory, bloky paměti, řetězce, roury, ...) java.net podpora síťových aplikací (třídy URL, Socket, ...) java.rmi vzdálené volání metod (rozhraní Remote)
Standardní balíky JDK java.applet java.awt javax.swing podpora appletů – aplikací běžících v prohlížeči na straně klienta (IE, Netscape, ...) java.awt jednoduchá knihovna komponent grafického uživatelského rozhraní javax.swing pokročilá knihovna komponent grafického uživatelského rozhraní
Standardní balíky JDK java.sql, javax.sql jednotný přístup k SQL databázím javax.xml.parsers, javax.xml.transform analýza XML souborů a jejich transformace java.security, javax.security kryptografie a bezpečnost aplikací
Řešení příkladu ze cvičení package cviceni3; public class Complex { private double re; private double im; public double getRe() { return re; } public double getIm() { return im; } public double abs() { return Math.sqrt(re * re + im * im); }
Řešení příkladu ze cvičení public Complex() {} public Complex(double re) { this.re = re; this.im = 0.0; } public Complex(double re, double im) { this.re = re; this.im = im;
Řešení příkladu ze cvičení public void add(Complex c) { re += c.re; im += c.im; } public static Complex add(Complex c1, Complex c2) { double re = c1.re + c2.re; double im = c1.im + c2.im; return new Complex(re, im);
Řešení příkladu ze cvičení public String toString() { return im == 0.0 ? Double.toString(re); : re == 0.0 ? im + “i” : re + (im < 0.0 ? "" : "+“) + im + "i"; } public boolean equals(Object obj) { if( obj instanceof Complex ) { Complex c = (Complex)obj; return re == c.re && im == c.im; } return false; } }
Praktické cvičení – cviceni4.zip Úloha 1 – Práce s rozhraními Rozbalte v pracovním adresáři soubor cviceni4.zip. Prostudujte jakým způsobem je zajištěno třídění bulbinkovou metodou objektů typu Zlomek(Priklad.java) Rozšiřte třídu Complex o implementaci rozhraní Porovnatelny Úloha 2 – Práce s rozhraními Comparable, Comparator Prostudujte v JAVA API tyto dvě rozhraní Upravte třídy v baličku cviceni4 tak, aby používaly dané rozhraní.