AWT och avancerad Java Johan Larsson Uppsala Universitet November 1999 jola@csd.uu.se 1 Introduktion • Vad hände egentligen i FaceLab? • Hur ska projektets användargränssnitt programmeras? • Hur ska vi programmera Java så att programenheter (paket, klasser) blir välorganiserade? → hur blir objekt-orienterade program utökningsbara, korrekta, robusta … ? jola@csd.uu.se 2 1 Överblick i Java • Vi använder package för att strukturera klasser. • Vi använder arv för att göra utökningar. • Vi använder interface-arv för att bestämma gränssnitt. (Ersätter multipel-arv och kan göra livet lite enklare.) • Vi använder skyddsmekanismerna public, private or protected för att gömma information. jola@csd.uu.se 3 Package • Ett paket innehåller klasser och svarar mot en ”modul”. I filsystemet är ett paket oftast en katalog (kan dock vara i en speciell JARfil). • Paket hjälper oss att organisera koden. • Undviker namnkonflikter. jola@csd.uu.se 4 2 Arv • Objekt-orienterade språk använder arv (inheritance) för att bilda relationer av typen: ”A är SuperA är SuperSuperA” • Arv innebär utbytbarhet (”principle of substitutability”). En klass kan bytas ut mot en valfri subklass. • Java tillåter en klass att ärva från endast en annan klass till skillnad från Eiffel. jola@csd.uu.se 5 Interface-arv i Java • Ett interface är en klass där alla metoder är abstrakta. En klass kan implementera många interface men ärver endast från en annan klass. interface InterfaceA { void execute (); } class A extends SuperA implements InterfaceA { … } jola@csd.uu.se 6 3 Skyddsmekanism • Private: syns inte utanför programenhetens paket. • Protected: endast synligt för subklasser. Används för att komma åt inre tillstånd på ett lite enklare sätt. • Public:del av programenhetens gränssnitt dvs tillgängliga för alla klienter. • Paketsynlig: om inget av private, protected eller public anges blir programenheten synlig inom paketet. Exempel: private String fInternalToMyself; protected void subclassesMayUseThis; public static void partOfMyInterface; jola@csd.uu.se 7 Klassbiblioteket i Java applet awt io java event image EventObject LayoutManager lang EventListener util Enumeration Observer Klasserna är ordnade i paket (package) enligt ovan. T ex är java.util.EventListener en klass. jola@csd.uu.se 8 4 GUI-komponenter i AWT • En AWT-komponent är något som kan visas på 2D-yta och med vilket användaren kan interagera. • Viktig relation för ett GUI: ”containment” = innehåller någonting • I AWT är detta subklasser till Container. jola@csd.uu.se 9 Component extends Object setSize (int,int) - Ställer in storlek (pixel). getSize() - Returnerar storlek. setVisible (boolean) - Visar eller döljer. setForeground (Color), getForeground() setBackground, getBackground setFont(Font), getFont() repaint() - Schemalägg total omritning. - Rita om komponenten på yta paint (Graphics) addMouseListener (MouseListener) addKeyListener (KeyListener) jola@csd.uu.se 10 5 AWT klasshierarki Object Component Button TextComponent Canvas Container Label List Scrollbar TextField TextArea Window Dialog Panel Frame jola@csd.uu.se 11 Händelser i AWT (1) • Java genererar en händelse (event) varje gång muspekaren förflyttas, en tangent trycks, osv • Händelser är subklasser till EventObject • Det kan finnas många som lyssnar! jola@csd.uu.se 12 6 Händelser i AWT (2) • Ett objekt måste “prenumerera” på händelser av intresse (kallas även en observer-observable relation). • FaceLab använder EventListener • Händelsen kommer från sin källa och når specifika EventListner-subklasser, t ex ActionListener eller AdjustmentListener. jola@csd.uu.se 13 Händelser i AWT (3) • Klassen EventObject definierar en mycket användbar metod: Object getSource() – Returnerar objektet som orsakade händelsen. jola@csd.uu.se 14 7 Händelser i AWT (4) • Utökningsbarhet: hur utfördes FaceLab? • Metoden adjustmentValueChanged() f rån interfacet AdjustmentListener överskrevs. • Det gick inte lika lätt med flera Scrollbar: vi behövde särskilja samma typ av händelser i samma metod. • Vi vill nå en lösning som ger utökningsbar kod. Alltså inte ett ”hemmahack”. • Lösning: Nästade Klasser. jola@csd.uu.se 15 Exempel med händelser public class ColorBar extends Scrollbar implements AdjustmentListener { public ColorBar (Color c) { super (Scrollbar.VERTICAL, 40, 0, 0, 255); setBackground ©; addAdjustmentListener (this); } public void adjustmentValueChanged (AdjustmentEvent e) { // Lyssnar på sig själv } } jola@csd.uu.se 16 8 Nästade Klasser • Klasser kan vara medlemmar i andra klasser! class EnclosingClass { ... class NestedClass { … } } • Nästade klasser löser problem med encapsulation: den nästade klassen kommer åt den yttre klassens medlemmar, även de som är deklarerade som private. jola@csd.uu.se 17 Utan Nästade Klasser // An example with cluttered but valid code public class MyClass implements MouseListener { ... someObject.addMouseListener(this); ... /* Empty method definitions. */ public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } public void mouseClicked(MouseEvent e) { } } • Svårt att utöka och mycket kod att skriva. jola@csd.uu.se 18 9 Exempel med adapterklass • För att minska mängden kod introduceras adapterklasser, t ex MouseAdapter. // Less code but still a not extensible. public class MyClass extends MouseAdapter { ... someObject.addMouseListener(this); ... /* Override certain method definitions. */ public void mousePressed(MouseEvent e) { ... } } jola@csd.uu.se 19 Exempel med nästade klasser • Vi vill ha en inre klass MouseAdapter som vi senare kan utöka. // An example of using an inner class public class MyClass extends Applet { ... someObject.addMouseListener(new MyAdapter()); ... class MyAdapter extends MouseAdapter { public void mouseClicked(MouseEvent e) { … } } } jola@csd.uu.se 20 10 Z-ordning jola@csd.uu.se 21 Layout-hantering (1) • Platformsoberoende placering av Component-objekt i Container-objekt (t ex knapp i fönster). • Ger oberoende skalning av fönster. • Viktigaste LayoutManager-subklasserna: – BorderLayout (kompassriktningar) – GridLayout (lägger komponenter i rutnät) – FlowLayout (vänster-höger eller upp-ner) jola@csd.uu.se 22 11 Layout-hantering (2) • Container-klassernas metoder: setLayout (LayoutManager) add (Component), remove (Component) jola@csd.uu.se 23 BorderLayout Panel P = new Panel(new BorderLayout()); // Notera att konstruktorn till Panel fick LayoutManager som parameter! p.add(“North”, new Label(“En liten rubrik”)); p.add(“South”, new Label(“Kuckeliku”)); jola@csd.uu.se 24 12 GridLayout Panel P = new Panel(); // Skapa rutnät 4x4 med 3 pixel mellan varje ruta p.setLayout(new GridLayout (4,4,3,3)); p.add(new ColorButton(Color.black, ”black”)); p.add(new.ColorButton(Color.blue, ”blue”)); • Vad är Panel för klass? Vad ärver den ifrån? jola@csd.uu.se 25 java.io • Många objektorienterade språk använder abstraktionen ”dataström” (stream) • Java har klasser InputStream och OutputStream i java.io. • En ström är något som kan matas med data eller som man kan hämta data från. jola@csd.uu.se 26 13 InputStream och OutputStream jola@csd.uu.se 27 Persistens i Java • java.io.Serializable - ”taggar klasser” • Persistens = lagra objekt i dataström så att det kan återskapas senare. • Möjliggör att objekt transporteras över Internet, lagras i filer, osv. • Grunden för distribuerade tekniker såsom CORBA, RMI, mm. jola@csd.uu.se 28 14 Enkelt exempel på persistens FileOutputStream out = new FileOutputStream("theTime"); ObjectOutputStream s = new ObjectOutputStream(out); s.writeObject("Today"); s.writeObject(new Date()); s.flush(); jola@csd.uu.se 29 Trådar i Java (1) • Trådar är lättviktsprocesser, dvs processor som kan exekvera parallelt med varandra inom ramen för ett programs normala sekventiella exekvering • java.lang.Thread • Anpassas med metoden run jola@csd.uu.se 30 15 Trådar i Java (2) • Trådar fungerar olika bra beroende på platformens stöd. På vissa platformar måste man använda metoderna sleep och yield för att ge tid åt andra trådar, medan andra plattformar automatiskt delar upp exekveringstiden mellan trådar. • Hur gick det? jola@csd.uu.se 31 Synkronisering av trådar • Trådar måste ofta synkronisera i samband med att delad data uppdateras eller kritiska uppgifter skall utföras. Annars kan vi få mycket konstiga resultat. • java.lang.Object har metoderna wait, notify och notifyAll • Syntaktiskt stöd: synchronized och volatile jola@csd.uu.se 32 16 Att använda trådar • Två sätt att skapa trådar: – SomeProcess implements Runnable – SomeProcess extends Thread jola@csd.uu.se 33 Exempel med Thread • Vi behöver bara överskriva metoden run public class SimpleThread extends Thread { public SimpleThread (String name) { super(name); } public void run () { for (int i = 0; i < 10; i++) { System.out.println(i + ” ” + getName()); try { sleep ((long)(Math.random() * 1000)); } catch (InterruptedException e) {} } System.out.println(”Done with ” + getName());L } n o } (fortsätter på nästa OH) jola@csd.uu.se 34 17 Exempel med Thread public class TwoThreadsTest { public static void main (String[] args) { new SimpleThread (”Jamaica”).start(); new SimpleThread (”Fiji”).start(); } } 0 Jamaica 0 Fiji 1 Fiji 1 Jamaica 2 Jamaica ... jola@csd.uu.se 35 Att använda Runnable 1. Skapa en klass som implementerar interfacet Runnable dvs tillhandahåll metoden run. 2. För att exekvera tråden skriv: new Thread (myRunnableObject) jola@csd.uu.se 36 18 JGL, Collection Framework, STL • JGL innehåller datastrukturer och algoritmer med iteratorer, funktionsobjekt. • Standard Template Library är ett bibliotek för C++. Standardiserat bibliotek från vilket JGL lånar sina idéer. • Java 2 innehåller avancerade datastrukturer liknande dom i JGL (kallas Collection Framework) jola@csd.uu.se 37 Datastrukturer i Java • Inbyggt i Java sedan tidigare versioner: Hashtable, Vector, Stack, BitSet i java.util Notera att Enumeration fungerar som Iterator i JGL. • Nytt för Java 2: Java Collections Framework • Vad ska användas? JGL rekommenderas i uppgiften men det går bra att använda Java 2 Collection Framwork. jola@csd.uu.se 38 19 JGL exempel PriorityQueue queue = new PriorityQueue(); queue.push( new Integer( 5 ) ); Enumeration e = queue.elements(); while ( e.hasMoreElements() ) System.out.println( e.nextElement() ); while ( !queue.isEmpty() ) System.out.println( queue.pop() ); jola@csd.uu.se 39 Iteratorer = generaliserad pekare (exempel från JGL) public class Test { public static void main (String [] args) { Array array = new Array(); array.add( "bat" ); array.add( "cat" ); System.out.println( "array = " + array ); ReverseIterator iterator = new ReverseIterator( array.end() ); while ( iterator.hasMoreElements() ) System.out.print( iterator.nextElement() + ” ” ); } } array = Array( bat, cat ) cat bat jola@csd.uu.se 40 20 OrderedSet i JGL • OrderedSet är en associativ array med hjälp av ett röd-svart träd vilket medför O(lg N) på alla operationer. Metoden remove raderar alla element som matchar en viss nyckel. • Element identifieras med predikatet ”<” skickat som argument till konstruktorn. • a = b ⇔ !(a < b) and !(b < a) jola@csd.uu.se 41 Exempel med Primtal (1) import java.util.*; class Sieve implements Enumeration { private BitSet primes; private int index = 2; // Datastruktur från java.util public Sieve (int n) { primes = new BitSet(n); for (int i = 1; i < n; i++) primes.set(i); // Sätt bitar // Ta bort delbara tal (sålla bort) for (int i = 2; i *i < n; i++) if (primes.get(i)) for (int j = i+i; j <= n; j+= i) primes.clear(j); } (fortsätter på nästa OH) jola@csd.uu.se 42 21 Exempel med Primtal (2) ... public boolean hasMoreElements () { index++; int n = primes.size(); while (! primes.get(index)) if (++index > n) return false; return true; } public Object nextElement() { return new Integer (index); } public static void main (String [] args) { Sieve p = new Sieve (100); while (p.hasMoreElements()) System.out.println(p.nextElement()); } } jola@csd.uu.se 43 Ytterligare exempel från JGL public class CopyingTest { public static void main( String[] args ) { int ints[] = { 2, 6, 3, 7 }; Vector vector = new Vector(); vector.addElement( new Integer( 1 ) ); vector.addElement( new Integer( 4 ) ); // Skapa en IntArray från arrayen ints. IntArray intArray = new IntArray( ints ); VectorArray vectorArray = new VectorArray( vector ); System.out.println( "before copying = " + vector ); Copying.copy( intArray, vectorArray ); System.out.println( "after copying = " + vector ); } } jola@csd.uu.se 44 22 Några diskussionsfrågor • Behövs interface-arv? • Behövs nästade klasser (hur var det innan dom kom till i Java)? • Vad ska man tänka på då man konstruerar lite större Java program enligt denna lektion? jola@csd.uu.se 45 Litteratur • Eckel, Thinking in Java, Prentice Hall, 1998. • Flanaga, Java in a Nutshell. O'Reilly & Associates, 1997. • Horstmann and Cornell, Core Java: Volume I Fundamentals, Prentice Hall 1997. • Horstmann and Cornell, Core Java: Volume II Advanced Features, Prentice Hall 1997. • Budd, Understanding Object-Oriented Progrmaming with Java, Addison-Wesley, 1998. jola@csd.uu.se 46 23