Pokročilé programování na platformě Java Úvod
O předmětu Petr Hnětynka hnetynka@d3s.mff.cuni.cz http://d3s.mff.cuni.cz/teaching/vsjava/ pokračování "Javy (NPRG013)" předpokládá se základní znalost Javy (v rozsahu NPRG013) 0/2 Z
Zápočet napsání zápočtového programu domluvit si zadání do pátku 17. května 2013 poslat mailem přiměřeně složité téma netriviálním způsobem využívat některou z technologií probíraných v předmětu odevzdat nejlépe do konce června nejpozději do září pátek 27. září 2013 12:00 (poledne) odevzdání buď emailem nebo osobně (pokud to bude nutné)
Osnova předmětu hlubší pohled do jazyka Java přehled a historie platformy Java tipy a triky s Java type systém reflection API Java 5 - generické typy, anotace,... class loaders, security distribuované technologie: RMI,... komponentový model JavaBeans JEE: EJB, Servlets, JSP, Spring JME: CLDC, MIDP, JavaCard další technologie založené na platformě Java: Java APIs for XML, JDBC, JMX,... Android
Literatura, odkazy vše o Javě http://www.oracle.com/technetwork/java/ (http://java.sun.com/) Java tutorial http://download.oracle.com/javase/tutorial/index.html (http://java.sun.com/docs/books/tutorial/index.html) Java Language Specification http://java.sun.com/docs/books/jls/ Thinking in Java http://www.mindview.net/books/tij/
Java Základní přehled, historie,...
Java objektově orientovaný vše (téměř) je objekt výjimka primitivní typy interpretovaný zdrojový kód (.java) překlad do tzv. bytecode bytecode (.class) interpretován v tzv. virtual machine nezávislý na architektuře programy běží ve virtual machine
Historie JDK 1.0 1996 JDK 1.1 1997 Vnitřní třídy Java 2 platform 2000 JDK 1.2, 1.3 změny pouze v knihovnách JDK 1.4 2002 Assert JDK 5.0 2004 změny v jazyce generické typy (~ šablony) anotace... JDK 6 2006 JDK 7 2011 malé změny v jazyce JDK 8 2013... velké změny v jazyce
Java platform JSE standard edition JEE enterprise edition JME micro edition
"Výkon" původně (~ JDK 1.1, 1998) Java programy 6x pomalejší než C nyní: Just-In-Time (JIT) compilation v rámci spuštění se program přeloží provádí se nativní kód pomalý start, pak rychlé výkon ~ srovnatelný s normálními aplikacemi velká "spotřeba" paměti
Implementace Javy Oracle (Sun Microsystems) "oficiální" implementace Windows, Solaris, Linux Blackdown (do 1.5) open-source implementace JVM pro Linux založená na kódu Sun JVM IBM IBM JDK Jikes Jikes překladač open-source rychlý striktní kompatibila s Javou (do 1.5) Jikes RVM
Implementace Javy Jikes RVM Research Virtual Machine open-source pro testování různých rozšíření napsáno v Javě "self-hosting" nepotřebuje k běhu jinou JVM boot-image writer Java program, spustí se pod existující JVM boot-image loader program v C++ nepodporuje celé Java API
Implementace Javy OpenJDK http://openjdk.java.net/ open-source podporováno Oracle (Sun Microsystems) oficiální implementace z OpenJDK
Další... (spíše už historické ) GNU classpath implementace základních Java knihoven Guavac překladač Kaffe virtual machine Apache Harmony open source Java SE...
Android zdroj: http://developer.android.com/
Bck2brwsr http://wiki.apidesign.org/wiki/bck2brwsr Java běžící v prohlížeči Cíle projektu Create small Java capable to boot fast and run in 100% of modern browsers including those that have no special support for Java. Demonstrate that Java has benefits over JavaScript when creating larger HTML5 applications...
Popularita zdroj: http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
Popularita zdroj: http://www.tiobe.com/index.php/content/paperinfo/tpci/index.html
JAVA Typový systém, vlákna,...
Typový systém silně typovaný jazyk třídy (class) primitivní typy (int, boolean, char,...) "vše" je v nějaké třídě neexistují globální proměnné, funkce,... obdoba jsou static metody a atributy
Test public class InitTest { static int i = 1; { i+=2; }; static { i++; }; public static void main(string argv[]) { System.out.println(i); System.out.println(new InitTest().i); }; }; Program vypíše: a) 2 4 b) 1 3 c) 3 5 d) 4 4 e) nelze přeložit
Řešení testu správně je a) 2 4 {... } v definici třídy inicializátor provádí se při vytváření nové instance používá se pro inicializaci anonymních vnitřních tříd static {... } statický inicializátor provádí se při "natažení" třídy do VM může pracovat pouze se static prvky třídy
Test 2 public class InitTest { static int i = 1; { i+=2; }; public InitTest() { System.out.println(i++); } static { i++; }; public static void main(string argv[]) { System.out.println(i); System.out.println(new InitTest().i); }; }; Výsledek: a) 1 3 5 b) 2 3 5 c) 2 4 5
Řešení testu 2 správně je C) 2 4 5 inicializátor se provádí před konstruktorem nejdříve se inicializuje předek inicializátory a konstruktor
Výjimky a inicializátory inicializátory mohou "vyhazovat" pouze výjimky, které jsou definovány v konstruktorech musí být definován alespoň jeden konstruktor inicializátory anonymních tříd mohou vyhazovat jakékoliv výjimky třída se vytváří pouze jednou není problém výjimku odchytit / deklarovat
Statické inicializátory musí skončit normálně jinak nelze přeložit prováděny v pořadí podle výskytu ve zdrojovém souboru nemohou obsahovat return nelze přeložit
Pole pole ~ objekt proměnná ~ reference do typu Object lze přiřadit jakoukoliv referenci Object a1[] = new Object[10]; Object a2[] = new Object[5]; a1[0]=a2; a2[0]=a1;
Vlákna Java Language Specification definuje "memory model" určuje možná chování programu (ve vztahu k vláknům) pro daný program a průběh výpočtu určí, zda průběh výpočtu je legální volatile atributy tříd vždy v konzistentním stavu vlákna můžou mít zkopírované ne-volatile atributy do svojí paměti důvod = rychlost změny ne-volatile atributů nemusejí být ihned vidět z jiných vláken přiřazení (i čtení) do primitivních typů <= 32 bitů atomické tj. long a double nejsou ale pokud jsou volatile, tak ano přiřazení (čtení) referencí - atomické
Vlákna balík java.util.concurrent.atomic třídy typu AtomicInteger AtomicIntegerArray AtomicLong poskytují atomický přístup metodu compareandset()...
Synchronizace "monitor" zámek a fronta čekajících vláken asociované s každou instancí zámek a fronta čekajících vláken asociované s každou třídou příkaz/modifikátor synchronized příkaz synchronized (Výraz) Blok výraz se musí vyhodnotit na referenci na objekt než se začne Blok vykonávat, vlákno musí získat pro sebe zámek na objektu určeném pomocí Výrazu po skončení Bloku se zámek uvolní
Synchronizace modifikátor metody synchronized v hlavičce metody chová se stejně jako příkaz synchronized vlákno než začne vykonávat metodu musí získat zámek na objektu po skončení metodu se zámek uvolní static synchronized metody získává se zámek asociovaný se třídou vzájemně vyloučeny jsou jen synchronized metody a bloky nějaké vlákno má zámek na objektu ostatní vlákna mohou používat atributy objektu i volat ne-synchronized metody
wait & notify wait, notify, notifyall definovány na java.lang.object void wait() lze volat jen pokud volající vlákno drží zámek na daném objektu (tj. v synchronized sekci) jinak výjimka IllegalMonitorStateException vloží vlákno do fronty čekajících vláken uvolní zámek na objektu jiná vlakna mohou získat zámek, tj. začít provádět synchronized blok
wait & notify po wait je vlákno ve frontě čekajících vláken dokud někdo nezavolá notify nebo notifyall void notify() "probudí" jedno (nějaké) vlákno z fronty čekajících (pokud není prázdná) lze volat jen ze synchronized sekcí jinak výjimka IllegalMonitorStateException probuzené vlákno pokračuje ve výpočtu až získá zámek (tj. vlákno, co drželo zámek (a zavolalo notify) opustí synchonized sekci) void notifyall() probudí všechna vlákna ve frontě vlákna budou pokračovat, až získají zámek
wait & notify tři varianty wait void wait() void wait(int milis) void wait(int milis, int nanos) čekají ve frontě, dokud někdo neprobudí, maximálně však zadanou dobu čekání ve wait lze přerušit (metoda interrupt()) vyhodí InterruptedException wait, notify i notifyall jsou final metoda sleep() neuvolňuje zámek
Synchronizace java.util.concurrent semafory zámky synchronizované fronty atomické operace...
Viditelnost ve třídách lze změnit viditelnost elementů v potomcích? např. class A { public void foo() {} } class B extends { private void foo() {} } viditelnost lze zmírnit ale nelze zpřísnit proč pokud by bylo class A { public void foo() {} } class B extends { private void foo() {} } pak by šlo následující A a = new B(); a.foo();
Změny v jazyce od Java 5 static import auto-boxing a auto-unboxing nový for cyklus generické typy výčtový typ enum metody s proměnným počtem parametrů (printf) anotace (metadata)
Java 7, 8 Java 6 změny pouze v knihovnách Java 7 2011 mírné změny v jazyce Java 8 pravděpodobně léto 2013 větší změny v jazyce Java 8 will be revolution, not evolution Mark Reinhold, konference JavaOne, říjen 2011 ale září 2012 zrušení plánů na modularizaci
Java 7 změny změny v syntaxi podpora dynamických jazyků (nová instrukce v bytekódu) změny v NIO Nimbus (Swing LaF) nová verze JDBC...
Java 7 změny v syntaxi zápis konstant binární konstanty 0b010101 oddělení řádu v konstantách pomocí podtržítek 1_000_000 String v switch příkazu String month;... switch (month) { case "January": case "February":... }
Java 7 změny v syntaxi operátor <> zjednodušená vytváření generických typů typ u new se automaticky odvodí př. List<String> list = new ArrayList<>(); List<List<String>> list = new ArrayList<>(); List<List<List<String>>> list = new ArrayList<>(); Map<String, Collection<String>> map = new LinkedHashMap<>(); otázka Proč není new bez <>? Tj. např. List<String> list = new ArrayList();
Java 7 změny v syntaxi interface AutoClosable a rozšířený try př: class Foo implements AutoClosable {... public void close() { } } try ( Foo f1 = new Foo(); Foo f2 = new Foo() ) {... } catch ( ) {... } finaly {... } při ukončení try (normálně nebo výjimkou) se vždy zavolá close() na objekty z deklarace v try volá se v opačném pořadí než deklarováno
Java 7 změny v syntaxi rozšíření catch na více výjimek př: try {... } catch (Exception1 Exception2 ex) {... } lepší typová kontrola výjimek při re-throw
Je tento kód správně private void foo(int i) throws Ex1, Ex2 { try { if (i < 0) { throw new Ex1(); } else { throw new Ex1(); } } catch (Exception ex) { throw ex; } } v Java 7 ano v Java 6 ne kompilátor vypíše chybu zde
Co bude v 8 Lambda expressions (Closures, anonymní metody) příklady (int x, int y) -> x + y (x, y) -> x - y () -> 42 (String s) -> System.out.println(s) x -> 2 * x c -> { int s = c.size(); c.clear(); return s; }
Lambda použití interface Consumer<T> { void accept(t t); } současný kód pointlist.foreach(new Consumer() { public void accept(point p) { p.move(p.y, p.x); } }); s lambda výrazy pointlist.foreach(p -> p.move(p.y, p.x));
Lambda lambda výraz je instance funkcionálního interface interface s jednou metodou public interface Runnable { void run(); } public interface ActionListener { void actionperformed(actionevent e); } public interface Comparator<T> { int compare(t o1, T o2); boolean equals(object obj); } lambda výraz neobsahuje informaci o tom, který funkční interface implementuje lambda výrazy jsou objekty Runnable r = () -> {}; Object o = r;
Co nebude v 8 Moduly