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