Göm menyn

Labb 1: Intro till Java utan objekt

Att göra: Labbanmälan (senast 140121)

I labb 1–4 delar vi upp oss i 8 "storgrupper", A–H, med omkring 15–20 studenter i varje. Inom storgruppen arbetar alla enskilt.

  1. Kontrollera i webschemat vilken storgrupp som skulle passa dig bäst.

  2. Anmäl dig i WebReg3 i en lämplig grupp. Är det fullt i den gruppen får du välja en annan. Om det är fullt i alla grupper, kontakta examinatorn.

    Vid tekniska problem, prova gamla WebReg2.

Syfte: Java, utvecklingsmiljö

Den första labben har två syften:

  1. Att ni ska börja utforska Java så tidigt som möjligt. Vi börjar med enkla uppgifter i Java utan objektorientering, för att ge en stabil grund i det som skiljer sig från t.ex. Python. Detta är önskemål från tidigare studenter.

  2. Att introducera utvecklingsmiljön. För att se till att ni verkligen testar funktionalitet som tidigare studenter har haft mycket nytta av, "styr" vi er ganska detaljerat i vissa delar.

Info: Textlådor

Studenter har efterlyst en tydligare uppdelning mellan syfte, diskussioner och uppgifter. I år försöker vi uppnå detta via olikfärgade lådor.

Info: Om schemalagda labbtider

  1. Gå alltid till den labb och den sal som är tilldelad din "storgrupp". Då kan din egen handledare lära känna dig bättre.

  2. I mån av tid och plats kan man även gå till andra tillfällen och/eller ställa frågor till andra handledare. Man ska dock redovisa för sin egen handledare.

  3. Arbeta vid behov även utanför schemalagd labbtid!

  4. Handledarna ska vara närvarande vid schemalagda labbar men kan ta en kort paus. Vid sjukdom täcker övriga handledare upp så gott det går.

Info: Deadlines och krav

  1. Labb 1 examineras via redovisning utan kodinlämning.

  2. Labb 1 ska redovisas senast 140205.
    Därefter ges en ny chans vid projektdemo i maj/augusti.

Utvecklingsmiljö: IntelliJ IDEA

Syfte: Mindre tråkigt, mer lärorikt!

Programmering kan innehålla många rutinmässiga steg som vi helst vill undvika. Därför är det ofta extremt smidigt att använda en integrerad utvecklingsmiljö (IDE). Moderna miljöer gör ju långt mer än att "hålla reda på filerna": De analyserar och indexerar automatiskt koden allteftersom den skrivs, visar omedelbart syntaxfel och andra fel, indikerar möjliga problem i koden, ger möjlighet till avancerad navigering och kodanalys (vem anropar den här metoden?), och tar hand om många tråkiga uppgifter när du vill omstrukturera din kod. Kodvarningar är ofta en bra hjälp till att lära sig programmera bättre!

Bakgrund: Installera och starta IDEA

I de tre första labbarna används alltid IntelliJ IDEA, som finns både i kommersiell variant (Ultimate Edition) och som gratis open source-version (Community Edition) som kan användas på egen dator. Från labb 4 får man själv välja miljö.

Använd gärna referenskortet till hjälp.

Att göra: Installera och starta IDEA

Innan vi börjar använda IDEA måste en del nödvändiga konfigurationsfiler installeras. Kör därför först följande kommando:

   ~TDDD78/bin/installidea.sh

IDEA startas sedan med följande kommando:

   ~TDDD78/bin/idea.sh

Info: Vad händer?

Det är möjligt att IDEA genererar varningar i terminalfönstret medan det startas. Ni kan oftast ignorera dessa.

Efter en stund kommer IDEAs startup-skärm att visas. Den ser ungefär ut så här (lite beroende på operativsystem och version):

Att göra: Skapa IDEA-projekt

Nu skall vi skapa ett första IDEA-projekt som ska innehålla filerna för labb 1.

  1. Välj "Create New Project" som öppnar följande dialog:

  2. Se till att "Java" är valt i listan till vänster.

  3. Ge projektet ett namn vid Project name, t.ex. "TDDD78-lab1".

  4. Tala om för IDEA var projektfilerna skall lagras vid Project location (alla kodfiler kommer att hamna här). Den plats som IDEA föreslår är en katalog som heter "IdeaProjects" i hemkatalogen vilket kanske inte är optimalt om du redan har en katalog för TDDD78.

  5. IDEA behöver veta vilken SDK, Software Development Kit, som skall användas. I nuläget finns ingen Java SDK konfigurerad så välj "New..." och sedan "JDK". Därefter behöver du navigera till mappen /usr/jdk/instances/jdk1.7.0 för att slutligen lägga till SDKn. Använd inte den närliggande /usr/jdk/jdk1.7.0_xx!

    Tryck sedan på OK.

  6. Expandera "More Settings" och ändra Project format till ".ipr (file based)".

  7. Ett IDEA-projekt består av en eller flera moduler, där varje modul kan användas av flera projekt. Vi kommer enbart att ha en modul per projekt. Ändra Module name till "lab1". Behåll resten av inställningarna som de är.

  8. Tryck på "Next" och sedan på "Finish".

Info: Vad händer?

Nu har ett IDEA-projekt skapats. Det tar en stund för IDEA att starta upp eftersom den första gången behöver indexera alla JDK-filer. Indexeringen kan ta runt en minut och sker i bakgrunden. Under tiden kan man börja arbeta med de flesta av IDEAs funktioner.

Projektvyn kan vara dold när IDEA startas. Då öppnas den med Alt+1, genom att trycka på "1: Project" uppe till vänster, eller genom att välja View | Tool Windows | Project. Du kan expandera vyn över ditt projekt för att se alla relevanta mappar och filer inklusive externa bibliotek, för närvarande bara JDK.

Övning 1: Ett första program

Syfte: Komma igång!

Syftet med denna övning är att så snabbt som möjligt skriva och köra ett första Java-program. Vi börjar därför med en enkel "Hello World".

Bakgrund: Skapa paket och klass

Hela labb 1 kommer att fokusera på procedurell programmering, där vi inte skapar egna objekt. Eftersom Java är objektorienterat måste man dock alltid "kapsla in" sin kod i en klass. Vi vill därför börja med att skapa klassen Exercise1.

Men var ska klassen skapas? Java använder hierarkiska paket, på engelska packages, för att organisera klasser i större enheter och för att undvika namnkollisioner. Alla klasser i den här labben ska läggas i paketet se.liu.ida.dinadress.tddd78.lab1, där dinadress är din e-postadress (noone123).

En katalogstruktur matchande paketnamnet kommer att skapas, där varje punkt i namnet anger en ny katalognivå. IDEA kan dock visa paket ihoptryckta så att "tomma mellannivåer" göms i projektvyn. Detta och andra inställningar sköts via kugghjulet överst i vyn.

Att göra: Skapa paket och klass

Skapa ett paket genom att högerklicka på src som ligger under modulen lab1 i projektbrowserns hierarki. Att src är blå indikerar att den är en källkodsmapp. Välj därefter New | Package och skapa paketet se.liu.ida.dinadress.tddd78.lab1.

Skapa sedan klassen Exercise1 genom att högerklicka på paketet (lab1) och välja New | Java Class för att skapa klassen. Det fulla namnet för klassen blir se.liu.ida.dinadress.tddd78.lab1.Exercise1, och klassen skapas med attributet public vilket betyder att alla kan komma åt den. Mer info om åtkomsträttigheter kommer under föreläsningarna.

Bakgrund: Skapa huvudmetod

I ett enkelt "Hello World"-program behöver vi inga objekt, men vi behöver veta vilken kod som körs när ett visst program startas. Python kör all kod som är på "toppnivå" i den Python-fil man anger. I Java anger man istället en klass, och en speciell main-metod (funktion) i den klassen startas. Metoden måste ha en specifik signatur (parametrar, returvärden, ...).

Att göra: Skapa huvudmetod

Skriv in koden för ett litet Hello World-exempel enligt bilden nedan.

Man kan med fördel använda IDEAs Live Template-funktion genom att ställa markören i klassen (inom måsvingarna), välja Code | Insert Live Template: Ctrl-J , och sedan välja main() method declaration. Ett ännu snabbare alternativ är att skriva psvm och trycka Ctrl-J . Det samma gäller System.out.println(); som kan fås via sout och Ctrl-J .

Bakgrund: Köra programmet

Vi ska nu köra programmet. Från kommandoraden hade vi behövt kompilera filen och sedan köra "java se.liu.ida.dinadress.tddd78.lab1.Exercise1". Inifrån IDEA är det enklare, dels för att kompilering sker automatiskt, dels för att man slipper ange paketnamn manuellt.

Att göra: Köra programmet

Högerklicka någonstans i den öppna filen och välj Run Lab1.main(). Detta kompilerar automatiskt alla okompilerade filer, verifierar att inga kompileringsfel uppstod, och startar det program vi högerklickade. Du bör se utskriften i IDEAs körfönster:

Sammanfattning

Vi har nu sett hur man skapar nya paket, skapar nya klasser, skriver ett enkelt program, och startar det. Du behöver inte demonstrera förrän hela labb 1 är klar, men prata gärna med handledaren om du har frågor eller funderingar.

Övning 2: Multiplikationstabell

Syfte: Återskapa, testa kontrollstrukturer!

Syftet med denna övning är dels att testa en första kontrollstruktur i Java, dels att återskapa något ni redan gjort i Python för att på det sättet tydligt se kontrasterna mellan språken. Den uppgift vi väljer är multiplikationstabellen (övning 102).

Bakgrund: Skapa ny klass

I labb 1 skapar vi oftast en ny klass för varje uppgift.

Att göra: Skapa ny klass

Skapa klassen Exercise2 i det paket ni skapade. Klassen kan skapas (a) på samma sätt som förut eller (b) genom att ställa markören på klassnamnet Exercise1, trycka F5 (clone) och svara på frågorna.

I det senare fallet behöver man också ta bort onödig kod i den nya klassen – eller kommentera bort den. IDEA underlättar att kommentera bort kodavsnitt genom att man markerar dem och trycker CTRL-/ .

Bakgrund: Välja multiplikationstabell

Vi vill vänta lite med att titta på hur man hämtar input från användaren. Vi börjar därför med att skapa ett program som skriver ut multiplikationstabellen för ett "hårdkodat" (fixerat) tal, t.ex. 5.

Istället för att bara använda en konstant som 5 "rakt av" är det dock oftast bättre att ge den ett symboliskt namn, t.ex. genom att deklarera en konstant tabellnummer med värdet 5. Detta underlättar både kodförståelse ("tabellnummer" är lättare att förstå än "5") och senare ändringar (lättare att ändra den enda deklarationen än att ändra värdet "5" på massor av platser i koden).

Att göra: Välja multiplikationstabell

Deklarera en konstant som anger vilken multiplikationstabell vi skall skriva ut. Denna skall vara synlig endast i klassen och bör deklareras som följer, på toppnivå i klassen:

   private final static int tabell = 5;

Förklaringar till "final" och "static" kommer under föreläsningarna.

Info: Kodkomplettering och analys

När ni skriver kod i IDEA kommer ni att märka flera saker.

IDEA kommer att föreslå fortsättning på ord, något ni kan använda för att snabbt fylla i långa namn. Man väljer det alternativ som passar, t.ex. genom att skriva tills man lätt kan markera rätt namn och sedan trycka på TAB

IDEA kommer också att föreslå och markera fel eller andra otydligheter i koden. Genom sin indexering vet IDEA alltid vad ett namn står för. På så vis kan den välja olika färgmarkeringar (syntax highlighting) för att indikera vad som är en klass, en statisk funktion mm. vilket underlättar läsning av kod.

Bakgrund: Utskrift

Nu är det dags att programmera iterationen och utskriften. Vi vill visa 1*tabellnummer, 2*tabellnummer, osv. upp till 12*tabellnummer.

I Java sätts strängar för utskrift samman genom konkatenering via '+'-operatorn. När man försöker "addera" ett tal och en sträng förstår Java automatiskt att talen ska konverteras till strängar. Man kan därför göra en utskrift enligt följande exempel, där i är en loopvariabel:

   System.out.println(i + " * "+tabellnummer +  " = " +
                      i*tabellnummer); 

Att göra: Utskrift

Konstruera en for-loop som skriver ut 5:ans multiplikationstabell.

Testkör sedan programmet på samma sätt som i tidigare övning.

Övning 3: Inmatning

Syfte: Testa inmatning från användaren!

Syftet med denna övning är att testa inmatning av värden från en användare.

Bakgrund: Inmatning

Vi vill nu låta användaren ange vilken multiplikationstabell som ska visas. Vi gör detta genom en utökning i samma klass som tidigare.

Java är inte lika anpassat för enkla kommandoradsprogram som Python. Därför är det faktiskt enklare att läsa in ett värde från en grafisk dialogruta än att ta inmatning från standard input!

Att göra: Inmatning

Utöka programmet från förra övningen för att läsa in ett värde från användaren. Detta måste göras i mainmetoden, innan loopen. Exempel:

   String input = 
     JOptionPane.showInputDialog("Please input a value"); 

IDEA kommer att markera att den inte känner till klassen JOptionPane. Vi måste berätta var denna finns genom att antingen trycka Alt + Enter när IDEA föreslår detta, t.ex. då markören står framför raden, eller genom att trycka på den röda glödlampan som dyker upp efter en stund till vänster på raden och välja Import Class.

Värdet som läses in är en sträng, och måste konverteras till ett heltal (om möjligt). Exempel:

   int tabellnummer = Integer.parseInt(input); 

Den gamla konstanten tabellnummer används nu inte och kan kommenteras bort.

Provkör!

Testa gärna att mata in en icke-numerisk sträng och se vad som händer. Vi lämnar som överkurs att ta hand om felet (den exception som kastas) och låta användaren försöka på nytt.

Övning 4: Felsökning med IDEAs hjälp

Syfte: Hitta syntaxfel

Denna övning syftar till att testa hur en programmeringsmiljö kan hjälpa till att hitta fel i koden.

Bakgrund: Syntaxfärgläggning

Det händer ofta när man skriver kod att något inte blir syntaktiskt korrekt. IDEA och många andra omgivningar hjälper till att lösa dessa problem innan man kompilerar genom syntaxfärgläggning.

Att göra: Syntaxfärgläggning

Börja med att precis som ovan skapa klassen Exercise4. I den, inuti klassdefinitionen (mellan måsvingarna), klistrar du in följande felaktiga kod:

 public static void main(String[] args) {
    for (int i = 0; i < 10; i+1) {
       system.out.println(i + "-fakultet: " + facrotial(i));
    }
 }
    
 /**
  * Calculates f! given f.
  * @param f
  * @return f!
  */
 private factorial(int f) {
    if (f = 0) 
       return 1;
    }
    
    int result = 1
    for (int i = 1; i <= f; i+1) {
       result *= i;
    }
    
    return result
 }		

IDEA kommer helt utan att kompilera koden att känna av och markera en hel del fel. Det finns ett 10-tal fel varav ett är att "static"-kod i detta fall endast kan anropa annan "static"-kod. Din uppgift är att se till att den blir körbar och skriver ut en lista innehållande 0! till och med 10!.

Övning 5: Felsökning med debugger

Syfte: Börja testa debuggern

En debugger (avlusare) kan vara ett extremt användbart verktyg vid programmering. Syftet med denna övning är att introducera debuggern så tidigt som möjligt, för att förhoppningsvis spara mycket tid i senare skeden.

Bakgrund: Primtalsletare

För att även få lite mer programmeringsvana i Java skriver vi ett nytt program att avlusa. Detta program kommer att testa om ett tal är ett primtal.

När vi ska införa en väl avgränsad funktionalitet, som att testa primtal, bör den separeras ut för att förbättra modularitet och läsbarhet. Primtalstestet implementeras därför i en separat metod.

Att göra: Primtalsletare

Skapa en ny klass Exercise5 precis som tidigare.

Skapa en egen metod, public static boolean isPrime(int number), vars ansvar är att testa om number är ett primtal.

I metoden lägger vi en for-loop som går igenom alla tal 2,3,..., inparameter-1 och ser om någon delar talet. I så fall returneras false, annars true. Här behövs alltså en if-sats innuti for-loopen.

För att avgöra om ett tal delar inparametern använder vi följande felaktiga kod:

   int rest = tal / i;
    if (rest == 0)
    ... 

Bakgrund: Testkörning

Vi måste så klart testa för att se om det blir fel...

Att göra: Testkörning

Vi testkör nu funktionen. Låt main() skriva ut resultatet av isPrime(5). Starta klassen som vanligt. Svaret bör bli true om du har gjort rätt.

Modifiera programmet så att main() skriver ut isPrime(4). Det blir också true vilket ju är fel. Vi har alltså upptäckt ett fel i programmet.

Bakgrund: Påbörja avlusning

Vi kunde nu lägga till utskrifter för att ta reda på vad som egentligen händer i programmet, men det finns ett mer flexibelt sätt: Vi använder debuggern och ser till att programmet automatiskt stannar för inspektion vid en specifik brytpunkt.

Att göra: Påbörja avlusning

Sätt en brytpunkt på raden if (rest == 0) genom att vänsterklicka i listen till vänster om koden eller genom att stå på raden och trycka CTRL-F8. En brytpunkt indikeras genom en röd cirkel i listen samt att raden blir rödmarkerad.

Starta programmet i debuggern genom att högerklicka och välja Debug Exercise5.main() (inte "Run"!). Det ger följande fönster:

Info: Vad har hänt?

Programmet har nu startats, men har automatiskt pausats då brytpunken nåtts. Detta visas genom att raden med brytpunkten får blå färg.

Notera att debug-fönstret visas under kodfönstret. I debug-fönstret finns som standard tre mindre fönster. Det vänstra visar vilken anropskedja som ledde oss till funktionen vi befinner oss i körs – i det här fallet anropades den från main(). Det mittersta visar intressanta variabler och deras värden. Det högra visar Watches som är variabler vi valt att hålla extra koll på (för närvarande inga).

Bakgrund: Fortsätt avlusning

Nu är det dags att se vad som har hänt.

Att göra:

I debuggern ser vi att vi att tal=4 och i=2. Vi ser i koden att vi försökte hitta resten vid division med i, och i debuggern att resten faktiskt blev 2, vilket inte är vad vi förväntat oss. 4 är ju jämnt delbart med 2!

Alltså måste något vara fel på den tidigare raden och mycket riktigt, / borde ju vara %. Ändra detta och testkör för att se att 4 inte längre klassas som ett primtal.

Avsluta debuggningen genom att trcka på den röda stoppknappen till vänster eller genom att trycka Ctrl+F2. Notera att debug-fönstret under koden stannar kvar. Ni kan antingen stänga det eller växla tillbaka till run-fönstret.

Info: Vad har vi uppnått?

Just i detta fallet ser man kanske inte omedelbart poängen. Men för mer komplicerade fel är debuggern enormt användbar, och under kursen kommer ni sannolikt att bekanta er mer med den.

En stor fördel är att ni omedelbart kan se värden på alla variabler. Ni kan också inspektera egenskaper hos objekt och följa hierarkier och pekare, något ni kommer att se mer av när vi kommer in på objektorientering. Detta vore mycket jobbigare att uppnå med "print-debuggning"!

Info: Vad mer kan man göra?

Run-menyn visar tillgängliga operationer att göra i debugläget. De vanligaste är:

  • Step Over | F8 som exekverar en rad kod och går till nästa utan att gå in i funktionsanrop.
  • Step Into | F7 som exekverar en rad kod och om raden innehåller ett funktionsanrop så hoppar den in i funktionen.
  • Run to Cursor | Alt+F9 som exekverar tills den kommer till nuvarande markörposition. Detta är samma som att lägga till en brytpunkt, köra till den och sedan ta bort den igen, ett förfarande som ofta används.
  • Run | F9 kör vidare till nästa brytpunkt.

Det finns många avancerade sätt att underlätta debuggning, t.ex. att köra tills ett givet villkor är sant, eller tills en given rad exekverats ett bestämt antal gånger. Ni kan hitta mer information via IDEAs hjälpsida.

Bakgrund: Hitta fler primtal

Vi avslutar den här övningen genom att skriva ut alla primtal under 100.

Att göra:

Gör en for-loop i main() metoden. Iterera över talen från 2 till 100 och skriv ut alla som klassificeras som primtal.

Om ni inte upptäckt det ännu så finns det en fori-mall för att snabbt få till en for-loop. Använd den på samma sätt som psvm och sout.

Övning 6: Kontrollstrukturer

Syfte: Bli bekant med kontrollstrukturer

Java har flera olika kontrollstrukturer för iteration (upprepning). Syftet med denna övning är att bli bekant med samtliga, för att kunna välja rätt variant vid rätt tillfälle. Vi ska även titta på switch, som är ett alternativ till if i vissa fall.

Bakgrund: Summera tal med for-loop

Här börjar vi med en vanlig for-loop.

Att göra: Summera tal med for-loop

  1. Börja med att skapa klassen Exercise6 för övningen.

  2. Skriv en funktion sumFor(int a, int b) som beräknar summan av talen a,a+1,...,b med hjälp av en for-loop.

  3. Skapa en main()-funktion. Den ska anropa JOptionPane.showInputDialog två gånger för att läsa in a och b och konvertera därefter dessa till int precis som i tidigare övning. Den ska därefter anropa sumFor(a,b) och skriva ut resultatet.

  4. Testkör!

Bakgrund: While, do-while

Här går vi vidare med två andra loop-konstruktioner.

Att göra:

  1. Skapa nu funktionen sumWhile(...), som har samma parametrar och returvärden som sumFor() men istället använder en while-loop för att beräkna samma summa.

    Hur måste koden skrivas om? Bland annat kan inte själva while-satsen ge iterationsvariabeln sitt första värde, så detta måste göras före loopen. Titta på föreläsningsanteckningarna om du är osäker!

  2. Testa tidigt och ofta: Ändra main() så den anropar sumWhile() istället, och testkör programmet. Får du samma summor som tidigare givet samma input?

  3. Skapa även funktionen sumDoWhile(...), som använder en do-while-loop.

  4. Testa tidigt och ofta: Ändra main() så den anropar sumDoWhile() istället, och testkör programmet. Får du samma summor som tidigare givet samma input?

Bakgrund: Switch

Vi ska nu testa en alternativ villkorssats: switch. Denna villkorssats testar inte godtyckliga villkor. Istället anger man ett uttryck, och vilken gren man utför beror enbart på detta uttrycks värde.

Switch på strängar fungerar enbart i Java 7 och senare. Vid problem, dubbelkolla språknivån i File / Project Structure / Projects / Project language level. Detta ska sättas till "7.0 - Diamonds, ARM, multi-catch etc.".

Att göra: Switch

  1. Låt main() använda JOptionPane.showInputDialog för att läsa in en textsträng som skall vara "for", "while" eller "do".

    Låt switch-satsen anropa rätt summeringsfunktion beroende på denna input. Glöm inte break!

    Lägg även till en default-etikett i switch-satsen. Denna gren utförs om man inte skrev in något av de acceptabla valen och bör alltså skriva ut ett felmeddelande.

  2. Testa programmet!

Avslutning

Här slutar första laborationen. Visa slutresultatet för din handledare och passa på att fråga om det är något du undrar över. Det går också bra att redovisa ett senare tillfälle om handledaren är upptagen (dock senast 140205).

Gick det snabbt? Det är OK. Vi har dubbla handledningstillfällen i labb 1 för att ge mer tid till de med mindre programmeringsvana.

Vi arbetar hårt på att göra klart labb 2, men är försenade pga flera personers sjukdom. Den kommer dock att kräva kunskaper från kommande Java-föreläsningar.

Labb av Mikael Nilsson, Jonas Kvarnström 2014.


Sidansvarig: Jonas Kvarnström
Senast uppdaterad: 2015-11-09