Örebro universitet
Institutionen för teknik
Thomas Padron-McCarthy (Thomas.Padron-McCarthy@tech.oru.se)








Ordinarie tentamen i

Programmering i Java

för Dataingenjörsprogrammet

torsdag 18 december 2003 kl 14:00 - 19:00








Hjälpmedel: Inga hjälpmedel.
Poängkrav: Maximal poäng är 40.
För betyget 3 krävs 20 poäng.
För betyget 4 krävs 27 poäng.
För betyget 5 krävs 33 poäng.
Resultat och lösningar: Meddelas på kursens hemsida senast torsdag 1 januari 2004.
Visning: Onsdag 7 januari 2004 kl 13:00-13:30 i mitt rum (T2220).
Efter visningen kan tentor hämtas på expeditionen.
Examinator och jourhavande: Thomas Padron-McCarthy, telefon 070-7347013.



LYCKA TILL!

Skriv inte svaren till uppgifterna direkt här, utan skriv på lösa blad och lämna in.

Uppgift 1 (5p)

a (1p)

Hur skiljer sig det sätt som ett Java-program kompileras och körs från hur de flesta andra "vanliga" programspråk, som till exempel C++, brukar fungera?

b (2p)

Vilka fördelar har felhantering med hjälp av undantag (exceptions), som i Java, jämfört med felhantering med hjälp av returnerade felkoder, som i C?

c (2p)

I Java finns det en del likheter mellan abstrakta klasser (abstract class) och gränssnitt (interface). Visa med tydliga exempel vilka likheter och vilka skillnader som finns.

Uppgift 2 (5p)

Programmet UndersökArgument ska gå igenom de kommandoradsargument som ges när programmet startas, och skriva ut hur många av dem som är tillåtna heltal samt deras summa. Körexempel:
prompt> javac UndersökArgument.java
prompt> java UndersökArgument hej 7 hopp -17 4711
3 tillåtna heltal.
Summan är 4701.
prompt> 
Följande försök att förverkliga detta program innehåller inte mindre än femton fel, som måste åtgärdas innan programmet går att kompilera och köra med önskat resultat. Ange vilka fel det är, och rätta dem!

Programmet finns även på sista sidan i tentan. Du kan göra rättelserna på den sidan, och sedan riva loss den och lämna in den tillsammans med dina övriga lösningar, så slipper du skriva av programkoden.

public class UndersökArgument {
    int summan = 0;
    public int Main(Strings[] args) {
        private int antalHeltal = 0;
        for (i = 0; i < args.length(); ++i);
        {
            try {                                /* Om argumentet inte 
                int talet =                       * är ett heltal kastas
                  Int.parseInt(args[i]);          * NumberFormatException,
                  antalHeltal = antalHeltal++;    * och antalHeltal
            }                                     * räknas inte upp.
            catch (NumberFormatException) {       */

            }
            summan += talet;
        } // for
        System.out.println(antalHeltal
                           " tillåtna heltal.");
        System.out.println("Summan är " + summan + ".");
    } // main
} // class UndersökArgument

Uppgift 3 (5p)

Skriv en Java-applet som är en enkel miniräknare. Man ska kunna mata in två tal i två rutor, och sen ska det finnas fyra knappar som man kan trycka på för att addera, subtrahera, multiplicera eller dividera de två talen med varandra. Resultatet ska presenteras i en separat ruta. Använd textfält (JTextField) för inmatningen och presentationen.

Appleten kan se ut så här, men det är inget krav att den ska vara exakt likadan. Den behöver inte vara vacker, bara alla knapparna och textfälten finns med.

Division
Om något av de inmatade talen inte är ett tillåtet tal, ska svaret ERROR presenteras:
Felaktig inmatning
Några tips:

Knappklassen heter JButton, och den har en metod som heter addActionListener, vilken som argument tar ett objekt som uppfyller gränssnittet ActionListener. Gränssnittet ActionListener innehåller metoden actionPerformed, som tar ett argument av typen ActionEvent.

Klassen JTextField har metoderna getText och setText.

Uppgift 4 (10p)

Totalförsvarets forskningsinstitut, FOI, har byggt ett system för automatiska UFO-observationer. UFO betyder unidentified flying object, dvs oidentifierat flygande föremål. Dygnet runt spanar FOI:s radar efter mystiska flygande föremål, och alla observationer lagras i ett Java-program. Det som behöver lagras för varje observation är tid (mätt i sekunder sedan midnatt) och plats (bestående av en x- och en y-koordinat enligt något meterindelat kartsystem). Alla dessa lagras som flyttal med dubbel precision (datatypen double).

a (3p)

Skapa klassen UFOobservation, med lämpliga variabler. Den ska ha en konstruktor som tar tre flyttal som argument, vilka representerar tidpunkt, x-koordinat och y-koordinat.

Skriv också en equals-metod för klassen. Två UFO-observationer som har samma värden på variablerna, dvs tiden och x- och y-koordinaterna, räknas som lika.

b (2p)

Ibland hakar FOI:s radar upp sig, och samma UFO registreras flera gånger. Därför vill man kunna jämföra två observationer för att se om de liknar varandra.

Skriv en static-deklarerad metod som heter liknande, som tar två UFO-observationer som argument, och som returnerar värdet true om observationerna är åtminstone ungefär lika. I annat fall ska värdet false returneras.

Med "åtminstone ungefär lika" menas att inget av värdena (tid, x och y) får skilja mer än 1.0. Det får alltså inte skilja mer än en meter i x- eller y-led, och inte mer än en sekund i tid, mellan observationerna.

c (2p)

Skriv en main-metod, som skapar tre objekt av klassen UFOobservation, och som visar hur metoderna equals och liknande anropas för att göra jämförelser mellan UFOobservation.

d (2p)

Skapa en undantagsklass OmöjligUFOobservationException, som ärver Exception, och skriv om konstruktorn för UFOobservation så att den kastar ett undantag av den typen om man försöker ange ett negativt värde på något av de tre tal som beskriver en UFO-observation.

e (1p)

Visa hur man i main-metoden kan skapa en ny UFOobservation-instans, nu när konstruktorn kan kasta ett undantag, och fånga undantaget så man kan hantera felet som uppstod.

Uppgift 5 (5p)

FOI köper ännu en radar. Den är av en mer avancerad typ, som dessutom kan mäta höjden på de UFO:n den observerar.

a (2p)

Observationerna från både den nya och den gamla radarn ska hanteras av samma datorsystem. Skapa därför en ny klass som ärver från den gamla klassen UFOobservation, och utökar den med en variabel som anger höjden. Klassen ska ha en konstruktor och en equals-metod.

b (3p)

Nu kommer objekt av klassen UFOobservation att blandas med objekt av den nya, utökade klassen. I kursen har vi gått igenom ett problem som kan uppstå när man ska avgöra om sådana objekt är lika. I Java görs det med equals-metoden. Beskriv problemet, med ett tydligt exempel.

Ledtrådar: symmetri, transitivitet.

Uppgift 6 (10p)

Utveckla en serverapplikation som kan lagra en textrad. Klienter ska kunna koppla upp sig mot servern, och kommunikationsprotokollet mellan servern och klienten består därefter av två kommandon, LAGRA och HÄMTA:

Klienten skickar Exempel Servern svarar
LAGRA
textrad
LAGRA
Detta är raden!
OK
HÄMTA HÄMTA Detta är raden!
Allt annat LOGOUT NOK

Den lagrade textraden är gemensam för alla klienter, så om en klient lagrar en textrad med LAGRA-kommandot, kommer alla andra klienter därefter att få den raden som svar på sina HÄMTA-kommandon, tills någon klient lagrar en ny textrad.

För full poäng på uppgiften krävs att servern kan hantera flera samtidiga klienter. En server som bara kan hantera en enda klient åt gången ger maximalt 5 poäng på uppgiften.

Avslutning av programmet och att stänga socketar ordentligt behöver inte vara med i lösningen.

Bilaga: Utdrag ur API-specifikationen

java.net
Class ServerSocket

java.lang.Object
  extended byjava.net.ServerSocket

ServerSocket(int port)
          Creates a server socket, bound to the specified port.

Socket accept()
          Listens for a connection to be made to this socket and accepts it.

void close()
          Closes this socket.




java.net
Class Socket

java.lang.Object
  extended byjava.net.Socket

Socket()
          Creates an unconnected socket, with the system-default type of SocketImpl.

Socket(InetAddress address, int port)
          Creates a stream socket and connects it to the specified port number at the specified IP address.

close()
          Closes this socket.

InputStream getInputStream()
          Returns an input stream for this socket.

OutputStream getOutputStream()
          Returns an output stream for this socket.

java.io
Class BufferedReader

java.lang.Object
  extended byjava.io.Reader
      extended byjava.io.BufferedReader

BufferedReader(Reader in)
          Create a buffering character-input stream that uses a default-sized input buffer.

void close()
          Close the stream.

int read()
          Read a single character.

String readLine()
          Read a line of text.




java.io
Class InputStreamReader

java.lang.Object
  extended byjava.io.Reader
      extended byjava.io.InputStreamReader

InputStreamReader(InputStream in)
          Create an InputStreamReader that uses the default charset.

void close()
          Close the stream.

int read()
          Read a single character.

java.io
Class PrintWriter

java.lang.Object
  extended byjava.io.Writer
      extended byjava.io.PrintWriter

PrintWriter(OutputStream out)
          Create a new PrintWriter, without automatic line flushing, from an existing OutputStream.

PrintWriter(OutputStream out, boolean autoFlush)
          Create a new PrintWriter from an existing OutputStream.

void close()
          Close the stream.

void println()
          Terminate the current line by writing the line separator string.

void println(String x)
          Print a String and then terminate the line.

Lösningsblankett till uppgift 2

Tentamenskod:


public class UndersökArgument {

    int summan = 0;

    public int Main(Strings[] args) {

        private int antalHeltal = 0;

        for (i = 0; i < args.length(); ++i);

        {

            try {                                /* Om argumentet inte 

                int talet =                       * är ett heltal kastas

                  Int.parseInt(args[i]);          * NumberFormatException,

                  antalHeltal = antalHeltal++;    * och antalHeltal

            }                                     * räknas inte upp.

            catch (NumberFormatException) {       */



            }

            summan += talet;

        } // for

        System.out.println(antalHeltal

                           " tillåtna heltal.");

        System.out.println("Summan är " + summan + ".");

    } // main

} // class UndersökArgument