AWT och avancerad Java
Johan Larsson
Uppsala Universitet
November 1999
[email protected]
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 … ?
[email protected]
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.
[email protected]
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.
[email protected]
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.
[email protected]
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 {
…
}
[email protected]
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;
[email protected]
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.
[email protected]
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.
[email protected]
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)
[email protected]
10
5
AWT klasshierarki
Object
Component
Button TextComponent Canvas Container Label List Scrollbar
TextField TextArea
Window
Dialog
Panel
Frame
[email protected]
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!
[email protected]
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.
[email protected]
13
Händelser i AWT (3)
• Klassen EventObject definierar en mycket
användbar metod:
Object getSource()
– Returnerar objektet som orsakade händelsen.
[email protected]
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.
[email protected]
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
}
}
[email protected]
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.
[email protected]
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.
[email protected]
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) { ... }
}
[email protected]
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) { … }
}
}
[email protected]
20
10
Z-ordning
[email protected]
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)
[email protected]
22
11
Layout-hantering (2)
• Container-klassernas metoder:
setLayout (LayoutManager)
add (Component), remove (Component)
[email protected]
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”));
[email protected]
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?
[email protected]
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.
[email protected]
26
13
InputStream och
OutputStream
[email protected]
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.
[email protected]
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();
[email protected]
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
[email protected]
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?
[email protected]
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
[email protected]
32
16
Att använda trådar
• Två sätt att skapa trådar:
– SomeProcess implements Runnable
– SomeProcess extends Thread
[email protected]
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)
[email protected]
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
...
[email protected]
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)
[email protected]
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)
[email protected]
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.
[email protected]
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() );
[email protected]
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
[email protected]
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)
[email protected]
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)
[email protected]
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());
}
}
[email protected]
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 );
}
}
[email protected]
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?
[email protected]
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.
[email protected]
46
23