Forelæsning 7.1 – repetition Diagramtyper (3 statiske / 2 dynamiske) ArrayLists (én-til-mange relation) Programløkker (for-each for- og while) Mini Java Style Guide BlueJ debugger FindEn og FindAlle (algoritmeskabeloner) Primitive typer (forfremmelse og begrænsning) Identitet mellem objekter (sammenligning af strenge) Klassevariabler og klassemetoder Levetid og virkefeltsregler Forprogrammerede metoder (Collections og Comparables) dIntProg, E14
Statisk versus dynamisk syn Klassediagram (specifikation) hvad JavaDoc (specifikation) Java-kode (implementation) hvordan Objektdiagram objektrelationer (referencer) Sekvensdiagram Objektinteraktion (metodekald) Statisk struktur rum for hvad der generelt kan ske Dynamik scenarie for hvad der vil ske i en konkret situation dIntProg, E14
Klassediagram (BlueJ vs. UML) TestDriver run() 1 ClockDisplay NumberDisplay int getValue() String getDisplayValue() void setValue(int val) void increment() timeTick() setTime(int h, int m) getTime() void updateDisplay() 2 dIntProg, E14
JavaDOC dIntProg, E14
Java-kode dIntProg, E14
Objektdiagram :ClockDisplay hours minutes displayString :NumberDisplay 24 :NumberDisplay limit value “00:00” 60 :NumberDisplay limit value public ClockDisplay() { hours= new NumberDisplay(24); minutes= new NumberDisplay(60); updateDisplay(); } public NumberDisplay(int rollOverLimit) { limit= rollOverLimit; value= 0; } dIntProg, E14
Sekvensdiagram timeTick minutes :NumberDisplay hours :NumberDisplay 23:00 22:59 :ClockDisplay timeTick() increment() getValue() increment() updateDisplay() getDisplayValue() getDisplayValue() public void timeTick() { minutes.increment(); if(minutes.getValue() == 0) { hours.increment(); } updateDisplay(); private void updateDisplay() { displayString = hours.getDisplayValue() + ":” + minutes.getDisplayValue(); }
* ≈ én-til-mange relation Brug af ArrayLists Player void add(PlayList p) List<PlayList> find(String q) void print() * Playlist PlayList String getName() void addTrack(Track t) void print() Track shortestTrack() Track longestTrack() List<Track> search(String q) List<Track> longerThan(int r) void shuffle() * Track * ≈ én-til-mange relation Vilkårligt mange objekter af den pågældende type Track String getName() String getArtist() int getTime() dIntProg, E14
Collections – Samlinger af objekter Objektreferencer for at holde fast i et objekt skal der bruges en objektreference (en variabel) for at holde fast i 10.000 objekter skal der bruges 10.000 objektreferencer... Collections en særlig slags objekter, der kan opbevare (referencer til) objekter f.eks. ArrayList java.util en pakke, der bl.a. indeholder klasserne i Javas såkaldte collection framework dIntProg, E14
Eksempel: Liste af personer public void testMethod() { Person person; ArrayList<Person> persons = new ArrayList<Person>(); // add some persons person = new Person( "Jeppe", "89425665", 33 ); persons.add(person); person = new Person( "Ole", "32789878", 28 ); person = new Person( "Linda", "90023234", 21 ); } dIntProg, E14
Objektmodel for personeksempel persons: ArrayList<Person> 0 1 2 size() = 3 name: number: age: 33 ”Jeppe” ”89425665” name: number: age: 28 ”Ole” ”32789878” name: number: age: 21 ”Linda” ”90023234” person: dIntProg, E14
Realisering af en-til-mange - Kode For at realisere en en-til-mange relation i koden skal man gøre 3 ting: Importere klassen ArrayList import java.util.ArrayList; Erklære en feltvariablen af typen ArrayList<…> private ArrayList<Person> persons; Initialisere feltvariablen i konstruktøren public AddressBook(){ persons = new ArrayList<Person>(); } dIntProg, E14
Collection – parametriseret type ArrayList<E> lister (sekvenser) af objekter af typen E public class ArrayList<E> { boolean add(E e){…} void add(int index, E element){…} E get(int index){…} boolean contains (Object o){…} boolean isEmpty(){…} Iterator<E> iterator(){…} boolean remove(Object o){…} int size(){…} ... } Se JavaDoc... dIntProg, E14
Gennemløb med Javas for-each-løkke public void testMethod() { Person person; ArrayList<Person> persons = new ArrayList<Person>(); // add some persons person = new Person( ”Jeppe”, ”89525665”, 33 ); persons.add(person); ... // for each person print for ( Person person : persons ) { System.out.println(person); } dIntProg, E14
Implementation af ageSum /** * return the sum of the age of the people in the * address book */ private int ageSum() { int result= 0; for (Person person : persons) { result += person.getAge(); } return result; dIntProg, E14
Eksempler på iteration (gentagelse) for ( int i= 0; i<4; i++ ) { c.move(length); c.turn(90); } int i= 0; while ( i<4 ) { c.move(length); c.turn(90); i++; } dIntProg, E14
Mini Java Style Guide Navngivning Indrykning Klasser: med stort CamelCase eks.: Person, String, NumberDisplay, Variabler og metoder: med lille camelCase eks.: firstName, trackName, displayString Indrykning Alt mellem {} rykkes ét ’hak’ ind For hvert ekstra niveau af {} rykkes endnu et ’hak’ ind., eks.: public class Person { private int age; public Person() { age = 32; } Husk at bruge editorens Auto-layout BlueJ styleguide: http://www.bluej.org/objects-first/styleguide.html dIntProg, E14
BlueJ debugger (afluser = fejlfinder) Nyttig når man skal tjekke den detaljerede opførsel af noget Java kode Breakpoints indsættes (og fjernes) ved at klikke i venstre margin Under kørslen vil debuggeren stoppe, når et breakpoint nås, og vise positionen med en sort pil Herefter kan man ”steppe” gennem koden statement for statement dIntProg, E14
Metodekald Når man skal til at udføre et metodekald er der to muligheder: Udfører hele metodekaldet uden at man ser detaljerne Starter metode-kaldet, men stopper ved første statement i den kaldte metode dIntProg, E14
Metodekald Parat til at udføre første statement i den kaldte metode Andre knapper: Fortsætter kørslen frem til næste breakpoint Stopper kørslen Nødstop (uendelig while-løkke eller lignende) dIntProg, E14
Undervejs kan man inspicere Igangværende metodekald Feltvariables værdier Lokale variables værdier dIntProg, E14
findEn = Find et element i en liste Algoritmeskabelon Gennemsøger en liste og returnerer ét element, der opfylder en specificeret betingelse Hvis ingen elementer opfylder betingelsen returneres null dIntProg, E14
findAlle = Find alle elementer i en liste Algoritmeskabelon Gennemsøger en liste og returnerer en liste med alle elementer, der opfylder en specificeret betingelse Hvis ingen elementer opfylder betingelsen er listen tom Video 4.2 fra BlueJ bogen handler om findAlle dIntProg, E14
Primitive typer byte ≤ short ≤ int ≤ long ≤ float ≤ double char Ved assignments skal typerne være ”sammenlignelige” Det samme gælder for aktuelle/formelle parametre double d; //real int i; //heltal d = 3.14; i = 7; d = i // ok i = d // ej ok! byte ≤ short ≤ int ≤ long ≤ float ≤ double 8 bit 16 bit 32 bit 64 bit heltal reals Lidt anderledes end subklasser og superklasser. char boolean ≤ 1 bit 16 bit dIntProg, E14
Forfremmelse og begrænsning En værdi af en subtype kan ved en implicit typekonvertering (automatisk) forfremmes til en værdi af en supertype Begrænsning () En værdi af en supertype kan ved en eksplicit typekonvertering (et såkaldt ”type cast”) begrænses til en værdi af en subtype Eksempel: 9 + (int) ((6 * 2) / 2.5) 9 + (int) ( 12 / 2.5) 9 + (int) ( 12.0 / 2.5) 9 + (int) 4.8 9 + 4 13 Hvad bliver resultatet hvis vi fjerner (int)? dIntProg, E14
Forfremmelse og begrænsning Javas subtyperelation: char ≤ int ≤ double Forfremmelse ( ) sker automatisk hvis nødvendigt 2 + 1.5 evaluerer til 3.5 '2' + 1 evaluerer til 51 !!! Begrænsning () sker kun ved eksplicitte cast (int) (2 + 1.5) evaluerer til 3 (char) ('2' + 1) evaluerer til '3' !!! Bemærk Tegn (char) behandles som heltal: '2' + 1 = 51 = '3' Strenge (String) konkateneres: "24" + 1 = "241" dIntProg, E14
Identitet versus lighed I det virkelige liv skelner vi mellem objekter der er identiske og objekter der er af magen til hinanden To personer er ikke identiske selvom de hedder det same og er født samme dag (har samme attributværdier). Hvis et barn siger, at det vil have den Pizza, som står på nabobordet, kommer tjeneren med en ”magen til”. Java modellerer == identitet ≈ ”samme som” equals() lighed ≈ ”magen til” dIntProg, E14
Identitet mellem objekter “Fred” person1 :Person “Jill” person2 :Person “Fred” person1 :Person “Fred” person2 :Person :Person :Person person1 == person2 person1 == person2 evaluerer til false evaluerer til false “Fred” person1 :Person “Jill” person2 :Person :Person person1 == person2 evaluerer til true dIntProg, E14
Sammenligning af strenge “bye” input :String “bye” :String Strenge skal altid sammenlignes med equals() :Person == tester identitet String input = reader.getInput(); if( input == "bye" ) { ... } evaluerer til false equals tester lighed String input = reader.getInput(); if( input.equals("bye") ) { ... } evaluerer til true dIntProg, E14
Klassevariabler og klassemetoder Instansvariabler og instansmetoder Ethvert objekt har sin egen version af feltvariabler Kald af en metode er en besked sendt til et objekt (non-static) Det er imidlertid muligt at erklære feltvariabler og metoder som tilhører klassen Klassevariabler og klassemetoder erklæres med keywordet static Klassevariabler bruges til at modellere egenskaber for klassen, f.eks.: myndighedsalder for personer, fælles rentesats for alle konti Klassemetoder bruges til at modellere operationer der er uafhængige af objekters tilstande Hvor har I mødt klassemetoder? dIntProg, E14
Eksempler fra java.lang.Math public class Math { public static final double PI = 3.141592653589793 ... /** 0.0 ≤ random() < 1.0 */ public static double random() {...} /** sqrt(a) == a */ public static double sqrt(double a) {...} /** pow(a,b) == ab */ public static double pow(double a, double b) {...} } konstant (kan ikke ændres) dIntProg, E14
interestRate ændres for alle konti Kald af klassemetoder Klassemetoder kaldes via klassen Math.PI; Math.random(); Account.setInterestRate(1.10); Kan kaldes via objekt, men det er dårlig stil Math mathObject = new Math(); double d = mathObject.random(); Kald via objekt kan være yderst forvirrende Account myAccount = new Account(...); myAccount.setInterestRate(1.10); interestRate ændres for alle konti dIntProg, E14
Levetid for variabler og parametre Feltvariabler modellerer tilstand for objekter levetid er den samme som objektets Lokale variabler hjælpevariabler i en metode/konstruktør levetid er metodekaldet Parametre parametrisering af metode/konstruktør lokale variabler hvor startværdien leveres af kalderen Klassevariabler programudførelsen dIntProg, E14
Virkefeltsregler (fortolkning af navne) Et navn fortolkes i en kontekst og konteksten er med til at definere navnets betydning. Eks: Brian spillede blændende i søndags! Skolen ligger i Viby Ring til Kirsten og sig at ... Beskeden “Ring til Kirsten og sig at ...” fortolkes vidt forskelligt på arbejde og hjemme! I Java (og andre programme- ringssprog) er der præcise utvetydige regler for fortolkning af navne int i; int j; int k; i = i+j; Sequence s; String s; dIntProg, E14
Tre slags variabler Feltvariabler Parametre Lokale variabler public class Date { private int day; private int month; private int year; public void addDays(int d) { for ( int i=0; i<d; i++ ) { setToNextDate(); } private int daysInMonth() { int[] daysInMonth = {0,31,28,31,…}; int res; res = daysInMonth[month]; // handle leap year if (month == 2 && isInLeapYear()) { res++; return res; Samme navn for metode og lokal variabel dIntProg, E14
Feltvariabler public class Scope { public Scope() { i = 0; } public void addTwo() { addOne(); addOne(); private int i; public void addOne() { i = i + 1; public int getValue() { return i; Style-guide: Feltvariabler bør erklæres i begyndelsen af klassen En klasse definerer et navnerum hvor alle navne erklæret i klassen er tilgængelige overalt i klassen dIntProg, E14
Metoder public class Scope { public Scope() { i = 0; } public void addTwo() { addOne(); addOne(); private int i; public void addOne() { i = i + 1; public int getValue() { return i; En klasse definerer et navnerum hvor alle navne erklæret i klassen er tilgængelige overalt i klassen dIntProg, E14
Parametre public void addDays( int d ) { for ( int i=0; i<d; i++ ) { setToNextDate(); } En metode definerer et navnerum hvor parametre til metoden er tilgængelige overalt i metoden dIntProg, E14
Lokale variabler public void pip() { x = x++; int x = 0; x++; } Fejl(medmindre der er en feltvariabel x) I en metode definerer en blok {...} et navnerum hvor alle navne erklæret i blokken er tilgængelige fra og med erklæringen og indtil blokkens afslutning. dIntProg, E14
Indre blokke I en blok kan man erklære indre blokke { ... { ... } ... } Reglen for indre blokke er den samme som reglen for blokke i metoder (forrige slide), dvs. lokale variabler er tilgængelig fra og med erklæringen og indtil afslutningen på den indre blok public void pip() { int i = 0; { i++; System.out.println(i); int x = 0; x = i; x++; System.out.println(x); } dIntProg, E14
Et navn virker også inde i indre blokke public void pip() { int i = x; int x = 0; ... { i++; System.out.println(i); x++; System.out.println(x); } Fejl(medmindre der er en feltvariabel x) dIntProg, E14
Et navn kan “skygge” for et andet public class Scope { private int i; public Scope() { i = 0; } public void pip() { i++; { i++; System.out.println(i); int i = 0; public static void testMethod() { Scope s = new Scope(); s.pip(); Gør livet lettere for jer selv og andre: Brug forskellige navne !!! 2 1 Hvad sker der når vi oversætter (og afvikler) Scope.testMethod() i ovenstående program? dIntProg, E14
Virkefeltsregler i Java En variabel erklæret i en klasse virker overalt i klassen med undtagelse af virkefeltet for eventuelle ens-benævnte variabler erklæret i (blokke i) klassens metoder. En variabel erklæret i en blok virker overalt i blokken med undtagelse af den del af blokken der går forud for erklæringen virkefeltet for eventuelle ens-benævnte variabler erklæret i indre blokke i blokken. dIntProg, E14
Kontrolvariabel i for-løkke Konstruktionen for ( int j=0 ; j<4; j++) { System.out.println(j); } svarer til { int j; for (j=0; j<4; j++) { System.out.println(j); } dIntProg, E14
Hvilken variabel? Antagelse: Feltvariabler er erklæret øverst i klasse (jvf style-guide) Metode: Gå op og ud indtil en erklæring nås (spring indre blokke over) public class Scope { private int i = 0; public Scope ( int i ) { i = i + 1; System.out.println("a " + i ); } public void foo() { System.out.println("b " + i ); for ( int i = 0; i < 3; i ++){ System.out.println("c " + i ); System.out.println("d " + i ); new Scope(1).foo(); dIntProg, E14
Forprogrammerede metoder i Java Library Klassen Collections indeholder en række metoder Metoderne kan bruges på objekter af mange forskellige typer Typen skal være en subtype af (interfacet) Collection Det er f.eks. tilfældet for ArrayList T min(Collection<T> c) //returnerer mindste element T max(Collection<T> c) //returnerer største element void sort(List<T> l) //sorterer listen void reverse(List<T> l) //vender listen om void shuffle(List<T> l) //blander listen void copy(List<T> dest, List<T> src) //kopierering boolean disjoint(Collection<T> c1, Collection<T> c2) int frequency(Collection<T> c, Object o) ... dIntProg, E14
Brug af Collections på ArrayList<String>
Sammenligning kan ske via interfacet Comparable public interface Comparable<T> { /** * @returns whether this object is * smaller (negative integer) * equal (0) * or greater (positive integer) * than object o */ public int compareTo(T o); } Tænk på et interface som en rolle Track-objekter kan spille rollen Comparable Track skal implementere Interfacet public class Track { ... } implements Comparable<Track> { public int compareTo(Track o) { ... } Track skal have en compareTo metode (med den specificerede signatur) dIntProg, E14
Implementation af min metoden i Collections /** Vi antager at ArrayListen list ikke er tom */ public T min( ArrayList<T> list ){ T res = list.get(0); //gemmer hidtil mindste for ( T elem : list ){ if ( elem < res ) { res = elem; } return res; elem.compareTo(res) < 0 ) { dIntProg, E14
<<interface>> Klassediagram Collections T min(Collection<T> c) void sort(List<T> l) ... <<interface>> Comparable int compareTo(T o) uses implements Track Person String … dIntProg, E14