732G14
Programmering 2
HT 2008
Inledning
Denna kurs består av tre föreläsningar och en laborationskurs. Laborationskursen utgör hela examinationen av kursen och består av två
laborationer.
Den första laborationen är avsedd att kort repetera det du lärt dig i
tidigare programmeringskurser, och sedan öva på nya begrepp som införs
under föreläsningarna. Denna laboration är därför lämplig att påbörja
innan första föreläsningen.
Den andra laborationen är ett litet projekt där du får tillämpa dina
kunskaper på ett verkligt statistikrelaterat problem.
Komma igång med Eclipse
Eclipse är ett utvecklingsverktyg som nns tillgängligt gratis för de esta
olika operativsystemen. En av nackdelarna med eclipse är att det har
ganska många funktioner, och kan därför vara lite förvirrande i början.
Här nns därför en steg-för-steg guide till hur man skapar sitt första
projekt i Eclipse. För dig som känner att du behärskar grunderna nns
avsnitt, där introduceras några mycket användbara men inte nödvändiga
tips.
Starta eclipse
1. Starta Eclipse, om du sitter vid en Windows-maskin välj
Program → Eclipse → Eclipse 2.4.2.
Start →
Sitter du vid en sun-maskin så måste du öppna en terminal, Högerklicka på skrivbordsytan och välj Terminal. Kör följande kommandon:
module
add
module
initadd
prog / e c l i p s e
prog / e c l i p s e
eclipse
Vänta tålmodigt, det tar ett tag att starta Eclipse.
2. Om detta är första gången du öppnar Eclipse så får du välja var
din
workspace
ska ligga. Workspace är helt enkelt var Eclipse ska
spara dina projekt. Vi föreslår att du använder standardmappen.
3. Om du får en skärmbild med ett antal bilder på så ska du klicka på
den böjda pilen.
Skapa ett projekt
1. Skapa ett nytt projekt. Detta gör du genom att högerklicka i den
Package Explorer
efter välja New → Java Project.
vänstra panelen
2
eller i menyn välja File och där-
2. Du borde nu ha fått upp ett fönster som heter
New Java Project.
Ange ett bra projektnamn, detta kommer även att bli namnet på
den underkatalog i din workspace där projektet lagras och det namn
som visas i Package Explorer. Vi föreslår att du döper projekten
efter övningsnamnen (Repetition, Objektorientering och så vidare).
3. Du kan även ange lite andra inställningar, men lämna dessa som
de är tills vidare.
4. Tryck
Finish
för att skapa ditt projekt.
Skapa en klass
1. Högerklicka på projektnamnet i i
välj
Package Explorer
till vänster och
New → Class. Strunta i de tre översta fälten. Skriv ditt klass-
namn på fjärde raden (klassnamn skrivs med inledande versal).
2. Kryssa sedan eventuellt i att du vill generera public static void
main (String[] args). Detta kommer att göra klassen du skapar
körbar. Du vill normalt ha en sådan klass per projekt, men du kan
ha er om du vill.
3. Klicka
Finish, och du har skapat en klass.
Kör en klass
1. I verktygsraden, klicka på den lilla svarta nedåtriktade pilen till
höger om den stora gröna cirkeln med en vit play-symbol i. Välj
Run Congurations.
2. Dubbelklicka på rätt typ av applikation, detta är normalt sett Java
Application. Listan uppdateras nu och du borde se alla klasser
som matchar den valda applikationstypen. Markera den klass du
vill köra. och klicka på
Run.
Laboration 1, Introduktion till Java
Denna del innehåller en snabb repetition av den tidigare programmeringskursen. Om du känner att du redan behärskar det som behandlas så
är det bara att hoppa över de delarna.
Hello world
Denna klassiska uppgift är till för att du ska komma igång med utvecklingsverktyget eclipse. Du får även bekanta dig med utmatning av text
till terminalfönstret.
3
Uppgift 2
Skapa ett nytt projekt, ett lämpligt namn är Repetition. Skapa en
klass som du kallar för HelloWorld, denna klass skall vara körbar.
Ändra i klassen HelloWorld så att den ser ut som i kodexempel 1.
Kör nu din klass.
1 public class HelloWorld {
2
3
public static void main ( String [] args ) {
4
System . out . println (" Hello world " );
5
}
6
7 }
Kodexempel 1: HelloWorld.java
När du kör din klass ifrån eclipse så kommer den text som normalt skulle
ha skrivits till terminalfönstret att skrivas till iken som heter Console,
den ligger i nederdelen av Eclipse-fönstret. I det här fallet rör det sig
alltså om texten Hello World som borde ha skrivits ut.
Indata
För inläsning av data kan man använda sig av
showInputDialog()
för
att få en dialogruta. Denna funktion beskrivs i kapitel 1.12 i Skansholm.
Uppgift 3
Eftersom det är lite tråkigt med program som gör samma sak varje
gång de körs så ska du nu ändra i Hello world så att det frågar
efter användarens namn och sedan säger Hej Peter (om du nu heter
Peter).
Villkor och reguljära uttryck
Villkorssatser, eller if-satser, används för att avgöra vad som ska hända i
ett program baserat på något godtyckligt villkor. För att enkelt jämföra
strängar nns i java något som kallas reguljära uttryck. If-satser behandlas i kapitel 1.10 i Skansholm. För mer information om reguljära uttryck,
se http://java.sun.com/j2se/1.5.0/docs/api/java/util/regex/Pattern.html.
Uppgift 4
Se till att Hello world programmet hälsar lite extra hövligt på folk som
4
har just ditt underbara namn. Både personer med samma förnamn
och personer med samma efternamn. Använd reguljära uttryck.
Arrayer och loopar
Arrayer, eller
fält
som man ibland säger på svenska, är ett antal objekt
av samma typ. De behandlas närmare i kapitel 9.3 i Skansholm. De olika
repetitionssatserna nns i kapitel 1.12 och frammåt. En lämplig funktion
för att göra utskrifterna är
format,
och beskrivs i kapitel 5.3.
Uppgift 5
Lägg till en array av heltal i din HelloWorld klass. Skriv sedan ut
den, snyggt formaterad med hjälp av två loopar. Entalssirorna ska
vara justerade ovanför varandra i de olika raderna. Du får anta att
alla talen i arrayen innehåller högst tre siror. Nedan nns ett förslag
på hur utskriften kan se ut.
1
123
13
23
3
1
14
14
5
Eclipse-tips
Här bjuds på kraftfulla men enkla Eclipse-tips som alla rekomenderas
läsa och som kommer att spara tid för de esta, men som inte behövs för
att klara kursen.
Öppna/stänga ett projekt
Detta är speciellt användbart om du har fel/varningar från era projekt.
Inga fel/varningar visas nämligen från stängda projekt.
Högerklicka på projektnamnet i i
Open Project
Project Explorer
till vänster och välj
eller emphClose Project.
Visa utskriftsmarginal
Window → Preferences → General → Editors →
Text-editors → Show Print Margin
I huvudmenyn, välj
Kör senaste konguration
Detta kommandot kör den senast körda javalen, det verkar dock inte
fungera på SUN-maskinerna. Tryck
Ctrl + F11
5
Kommentera / avkommentera rad
Markera den text du vill kommentera eller avkommentera. Observera
att om du väljer era rader och vissa inte är kommenterade så kommer
verktyget att kommentera alla raderna igen. Tryck
Ctrl + 7
Automatisk indentering
Markera den text du vill indentera och tryck
Ctrl + i
Få kodförslag
Som de esta andra utvecklingsmiljöer kan även Eclipse ge kodförslag.
Skriv något och tryck
Ctrl + Space.
Eclipse har också ett antal förde-
nierade genvägar som är väldigt användbara, i många fall fyller Eclipse
själv i delar av exempelvis loop-konstruktionerna utifrån den omgivande
koden.
genväg
syso
if
for
foreach
resultat
System.out.println();
if (condition) {
}
for (int i = 0; i < array.length; i++) {
}
for (type element : iterable) {
}
Quick x
Om du har ett fel i din kod så kan Eclipse föreslå en lösning. Klicka
där felet nns och tryck
Ctrl + 1
(etta). Eclipse föreslår då vad du
kan göra för att lösa problemet. Observera dock att detta inte ersätter
hjärnaktivitet, du måste fortfarande veta vad du vill göra, Eclipse gör
bara vägen dit lite kortare.
Generera åtkomstmetoder
Eclpse kan autogenerera get-/setmetoder. Markera de instansvariabler
du vill generera för, Högerklicka i koden och välj
Getters and Setters. . .
Ob jektorientering
Objektorientering beskrivs i kapitel 2 i Skansholm.
6
Source → Generate
Wrapper
Klassen
Wrapper
är en mycket enkel klass son bara har en enda uppgift,
att innehålla ett heltal. Trots att detta är en mycket simpel klass så illustrerar den många bra programmeringsvanor. Mer om Wrapper klasser
kan ni hitta i Skansholm, kapitel 3.7.
1 public class Wrapper {
2
3
private int value ;
4
5
public Wrapper (){
6
value = 0;
7
}
8
9
public int getValue (){
10
return value ;
11
}
12
13
public void setValue ( int value ){
14
this . value = value ;
15
}
16
17 }
Kodexempel 2: Wrapper.java
Datagömning och inkapsling
Heltalet
value är deklarerat som en privat
instansvariabel, vilket betyder
att den bara kan användas innuti klassen där den deklarerats. Så varför är
detta bra? Jo, i och med att man separerar implementationen (hur man
gör något) från gränssnittet (hur man använder något) så bibehåller man
möjligheten att ändra implementationen utan att påverka gränssnittet.
Man skulle till exempel kunna välja att lagra värde utifrån hur mycket
större än 10 det är (varför i hela världen man nu skulle vilja det). Du
skulle då tvingas ändra i
getValue och setValue, men de som använder
din klass skulle inte märka något. Man skulle också kunna lagra värdet
som en annan datatyp, till exempel
få ändra lite i
getValue.
double,
även här kommer man att
Kapitel 3.2 i Skansholm handlar om datagömning
Uppgift 6
Prova att utföra ändringarna ovan (lagra
datatyp för
value)
7
value − 10,
samt att byta
Konstruktor
Wrapper är inte riktigt som alla andra funktioner, exempelvis
saknar den en returtyp. Wrapper är en konstruktor, och har därför exakt
Funktionen
samma namn som klassen i fråga. En konstruktor får inte ha någon returtyp och körs automatiskt när man skapar en ny instans av en klass.
Det kan nnas era
överlagrade
konstruktorer som då måste ha olika pa-
rameterlistor, eller signaturer som man brukar säga. Alla konstruktorer
i en klass har dock samma namn.
Skansholm kapitel 2.10 handlar om konstruktorer och 2.11 handlar
om överlagring.
Uppgift 7
Skapa en ny konstruktor där man får ange vilket heltal
Wrapper
ska
innehålla när man skapar det. Behåll den gamla konstruktorn.
Referenser
Alla objekt i java är referenser, medan alla inbyggda typer (exempelvis
int) inte är det. Detta betyder att man måste tänka lite extra ibland.
Exempel på tillfållen när man ska vara extra noga är vid tilldelning och
vid jämförelse. Kapitel 2.5 och 2.6 i Skansholm handlar om referenser
respektive tilldelningar.
Uppgift 8
Skapa en ny körbar klass. Den ska innehålla två
int och två Wrapper.
Ge dem bra namn så att man kan skilja dem åt. Du ska initiera
ett av heltalen och ett av
Wrapper-objekten
till 3, övriga ska vara
oinitierade.
Tilldela nu heltal två värdet av heltal ett och motsvarande för
Wrapper-objekten. Använd =-operatorn. Vad innehåller de olika variablerna?
Wrapper-objekt ett till 0. Använd
setValue() för Wrapper-objektet. Vad
Ändra nu värdet på heltal och
=-operatorn
för heltalet och
innehåler variablerna nu? Varför?
Generiska klasser
Klassen wrapper är ju uppenbarligen inte så enormt exibel. Den innehåller ett heltal. Vill man ha en
Wrapper
för andra objekttyper så får
man vackert skapa en ny klass. Det måste dock inte vara så. Man kan
nämligen göra en klass
generisk
eller
parametriserad .
Det betyder att
man för vissa variabler inte förutbestämmer någon typ, utan anger den
som en
parameter
när man instantierar klassen.
8
Kapitel 17.11 i Skansholm handlar om generiska klasser.
Uppgift 9
Wrapper parametriserad. Kom ihåg att du måste ändra typ för
value såväl som för din nya konstruktor och get-/setfunktionerna.
Gör
Arv
En klass kan
ärva
egenskaper från en annan. Objekt av den nya klassen
kommer att kunna behandlas som om den vore en instans av den gamla,
men kan ha nya metoder och variabler. Den nya klassen kan alltså ha
funktionalitet som den gamla saknade. Man brukar säga att den nya
klassen är mer specialicerad än den gamla.
Kapitel 10 i Skansholm handlar om arv.
Uppgift 10
PrintableWrapper till Wrapper. Subklassen ska
ha en funktion som heter print() och skriver ut innehållet på något
Skapa en subklass
vackert sätt.
Listan
I denna laboration ska du få skapa en lite mer avancerad datatyp, listan.
En lista består av 0n noder och varje nod innehåller ett heltal. Varje
nod i listan har referenser till noden före och efter, listan är en så kallad
dubbellänkad
lista. Man kan lägga till saker i listan och man kan ta bort
saker, men bara med hjälp av en
iterator. Iteratorn är en hjälpklass som
har går igenom noderna en efter en och kommer ihåg vilken nod den är
på under tiden.
Klassen NiceList
Den här listklassen ska använda sig av något som kallas för sentinel.
Principen är att man istället för att göra en rak lista, gör en cirkulär.
NiceList ska innehålla en referens till en Node som alltså är vår så kallade
sentinel. Denna nod ska alltid existera och skapas således i konstruktorn.
Till att börja med så pekar dess före- och efterreferenser på sig själv.
Man ska kunna lägga till ett nytt tal i listan.
en funktion som heter
NiceNode-objekt
add(int value).
NiceList behöver därför
Funktionen ska skapa ett nytt
som innehåller det aktuella värdet, och sätta denna
noden sist i listan genom att göra följande.
1. sätt den nya nodens förra objekt till sentinelens förra
9
2. sätt nya nodens förras nästa till den nya noden
3. sätt nya nodens nästa till sentinelen
4. sätt sentinelens förra till den nya noden
Klassen lista ska implementera gränssnittet
funktion som heter
iterator()
som returnerar
Iterable. Lägg till en
ett nytt NiceIterator-
objekt för den aktuella listan.
Klassen NiceNode
Detta är en intern klass i
NiceList.
Den innehåller referenser till två
andra noder (noden före och efter). Dessa noder bör vara privata, och
använda get/set metoder. I övrigt fungerar den precis som den ursprungliga
Wrapper
klassen.
Klassen NiceIterator
Detta är en intern klass i
NiceList, den implementerar interfacet Iterator<int>
och innehåller tre funktioner. Men till att börja med så måste den ha en
referens till en
nuvarande NiceNode
för att kunna hålla reda på var i
listan den benner sig. Låt noden börja referera till listans sentinel.
Funktionen
boolean hasNext()
talar om ifall det nns er noder i
listan. Detta är ekvivalent med att nuvarande nods nästa inte är sentinel.
Funktionen
int next()
returnerar nästa värde i listan, eller ger fel
om inget nästa värde nns. Nuvarande ska självfallet uppdateras så att
den pekar rätt.
void delete() tar bort det senast returnerade värdet.
sådant värde nns (next() har aldrig körts eller om värdet
Funktionen
Om inget
redan har tagits bort) så ska ett fel skapas.
1. om nuvarande är sentinel eller om nuvarandes föregående är null,
ge fel
2. sätt nuvarandes föregåendes nästa till nuvarandes nästa
3. sätt nuvarandes nästas föregående till nuvarandes föregående
4. sätt nuvarandes föregående till null
Uppgift 11
Skapa klasserna enligt specikationen ovan. Se därefter till att allting
fungerar.
10