Erfarenheter från biljardprojektet
Gästföreläsningen Synpunkter?
Sanningen bakom ordet implements Det underlättar överenskommelser mellan olika programmerare, och gör att java kan se till att de inte bryts!
Exempel Jag är systemprogrammerare. Jag skriver metoden addactionlistener() i javabiblioteket. public void addactionlistener(...) Metoden tar en parameter: ett lyssnarobjekt. Av vilken typ? public void addactionlistener(??? thelistener)
Exempel Kräver endast att det finns en actionperformed() public void addactionlistener(??? thelistener) thelistener ska kunna komma från många olika klasser! Det addactionlistener() gör är att se till att ActionEvents triggar anrop till parameterns metod actionperformed(). Så det kräver att parametern faktiskt har en sådan metod! Annars är jag kokt.
Du gör en tillämpning och vill använda min fina addactionlistener(). Du importerar biblioteket där den ligger och anropar den med ett hemsnickrat objekt som parameter. class MyApplication {... MyApplication() {... addactionlistener(this); Måste komma ihåg att skriva en actionperformed() Detta objekt har förhoppningsvis en metod actionperformed(). Annars är vi kokta
Interface är ett sätt att formulera sådana garantier och kolla att de uppfylls.
Ett interface innehåller metodhuvuden, dvs namn, typ och parametertyp(er) för metoden. Obs: Det innehåller inga metodkroppar inget { interface ActionListener { public void actionperformed(actionevent e); Javatradition: Namn på interface liksom namn på klasser börjar med Stor bokstav Betyder: den som är en ActionListener har åtminstone metoden actionperformed()
interface ActionListener { public void actionperformed(actionevent e);.. Definierar vad det innebär att vara en ActionListener public void addactionlistener(actionlistener thelistener) {.. (koden för addactionlistener) Kräver att parametern är. en ActionListener Systemprogrammerarens kod Användarens kod class MyApplication implements ActionListener {.. public void actionperformed(actionevent e) {.. Gör en utfästelse att klassens objekt ska bli ActionListeners uppfyller utfästelsen... addactionlistener(new MyApplication())...
Sanningen bakom ordet implements 2. Det möjliggör så kallad polymorfi: en metod kan ta parametrar av flera olika klasser
Exempel: bubblesort Vi har skrivit en metod bubblesort() som sorterar en array av heltal: void bubblesort(int[] data) {... Men samma metod skulle i princip kunna användas för att sortera - en array av double - en ArrayList av alla slags tal... Måste jag skriva en ny bubblesort för varje sådant fall?
bubblesort() tar en parameter, data. Vad är det jag ovillkorligen måste veta om den parametern? Jo, - jag måste kunna jämföra två intilligande tal - jag måste kunna byta plats på två intilliggande tal - jag måste kunna få reda på längden På alla datastrukturer som uppfyller detta kan jag göra bubblesort!
Formulera kravet Kravet formuleras som ett interface. Det ska alltså vara tre metoder, en för jämförelse mellan position i och i+1, en för platsbyte mellan position i och i+1, och en för längden interface Bubblesortable { public boolean compare(int i); public void swap (int i); public int length();
Använd kravet när du gör bubblesort boolean bytintill(bubblesortable data) { boolean bytt = false; for (int i = 0; i < data.length() - 1; i++) { if (!data.compare(i)) { data.swap(i); bytt = true; return bytt; void bubblesort(bubblesortable data) { while (bytintill(data)) { interface Bubblesortable { public boolean compare(int i); public void swap (int i); public int length();
Uppfyll kravet för att använda bubblesort class MyStructure implements Bubblesortable { int[] data;... public boolean compare(int i) { return data[i] < data[i + 1]; public void swap(int i) { int temp = data[i]; data[i] = data[i + 1]; data[i + 1] = temp; public int length() { return data.length; interface Bubblesortable { public boolean compare(int i); public void swap (int i); public int length();
Eller så här class MyStructure implements Bubblesortable { double[] data;... public boolean compare(int i) { return data[i] < data[i + 1]; public void swap(int i) { double temp = data[i]; data[i] = data[i + 1]; data[i + 1] = temp; public int length() { return data.length; interface Bubblesortable { public boolean compare(int i); public void swap (int i); public int length();
Eller såhär class MyStructure2 implements Bubblesortable { ArrayList<Integer> data; public boolean compare(int i) { return data.get(i) < data.get(i + 1); public void swap(int i) { int temp = data.get(i); data.set(i, data.get(i + 1)); data.set(i + 1, temp); public int length() { return data.size(); interface Bubblesortable { public boolean compare(int i); public void swap (int i); public int length();
Fördel: Du definierar bubblesort en enda gång Du kan använda den på många olika klasser, nämligen på alla som implementerar interfacet Bubblesortable
OBS Användning av interface göra att java kollar att rätt metoder är definierade och har rätt typ av parametrar. java kollar inte att metoderna faktiskt gör det som är tänkt!
Exceptions http://download.oracle.com/javase/tutorial/essential/exceptions/ Division med 0 Array index out of bounds File not found onormal I/O-händelse Null reference...
try - catch Python Java try: a = 1/b except: a = 0 try { a = 1/b; catch (Exception e) { a = 0; except i Python heter catch i Java. Inga kolon, men krullparanteser. Man måste alltid ange vilka exceptions som avses inom parantes efter catch.
try statement try block catch block aka catch clause aka exception handler try { a = 1/b; catch (Exception e) { a = 0; Grundidé: Börja köra try block. Om ett fel inträffar avbryt, och kör catch block
try { c1; c2; catch (Exception e) { c3; c4; c5; Allt OK c1 c2 Exception inträffar c3 c4 c5
Exception classes Detta är bara en liten del! Jfr Horstmann s339 En stor hierarki av klasser.
Varje klass svarar mot en typ av exception. Klasserna är ordnade hierarkiskt och underklasserna ärver överklasserna på vanligt sätt. Exempel: Exception är en klass för alla slags exception. IOException är en underklass för en del exceptions, nämligen de som orsakas av IO. I varje catch ska man alltid deklarera vilken typ av exception som man ska fånga. Till ett try can finnas flera catch för att fånga olika typer av exception.
try { Exempel Ett kodblock som kan ge upphov till många olika exception catch (IndexOutOfBoundsException e) { Kodblock som hanterar indexeringsfel catch (IOException e) { Kodblock som hanterar IO-fel Beroende på vilket slags exception som inträffar i try blocket kommer man till rätt catch block. Try blocket måste ha minst ett catch block
Exception objects När exception inträffar skapar Java ett objekt: en instans av exception-klassen. Objektet innehåller information om vad som hänt. Objektet kan man komma åt i motsvarande catch.
Typexempel: Exception object catch (IndexOutOfBoundsException e) { System.out.println( Exception + e.getmessage() ) Använd exception object för att få felmeddelande Till exempel har ett sådant objekt ett meddelande som nås med metoden getmessage()
catch (IndexOutOfBoundsException e) { System.out.println( Exception + e.getmessage() ) Objektets namn skrivs efter klassnamnet inom paranteserna efter catch. Det ser alltså lite ut som en deklaration. Objektnamnet räknas som en lokal variabel med scope som är resten av denna catch clause
finally Efter alla catch block får det finnas (men måste inte finnas) ett finally block. Det utförs hur try blocket än avslutas - vare sig någon exception inträffat eller ej. Även om try blocket avslutas med en return eller break. Användning: för att säkerställa att reserverade resurser (tex filer) släpps.
Grundmönster för IO try { Ett kodblock som öppnar en fil/enhet och försöker läsa/skriva catch (IOException e) { Kod som upplyser användaren om att något gick fel finally { Kod som stänger filen/enheten
Checked exceptions Terminologi: exception inträffar = exception kastas, exception is thrown En del exception classes kallas checked De som programmeraren borde förutse och ta hand om Typexempel: IOException En metod som kan kasta ett sådant måste antingen själv ta hand om det i en catch eller tydligt deklarera att anroparen måste ta hand om det
En metod som läser fil och hanterar eventuella exception själv: void readfile() { try { Ett kodblock som öppnar en fil och försöker läsa kan kasta ett IOException catch (IOException e) { Kod som upplyser om att något gick fel vid läsning finally { Kod som stänger filen
En metod som läser fil och låter anroparen hantera exceptions Ny deklaration i metodhuvudet void readfile() throws IOException { Ett kodblock som öppnar en fil och försöker läsa Notera: ingen try - catch här Med ordet throws följt av exceptiontyp deklareras att metoden kan kasta sådana exceptions utan att själv fånga dem. De bör fångas av anroparen try { readfile() catch (IOException e) {...
Sammanfattning try {... catch (Exception e) {... finally {... Får finnas flera catch Varje måste ange felklass lokal variabel e är ett exceptionobjekt finally är bra för att släppa resurser En metod som kan åstadkomma IOException måste antingen fånga dem själv eller deklareras med throws IOException
Franska Guyana 4 juni 1996
Exception vs Event Var skapas objektet? Vart i koden kommer man? Hur kommer man åt objektet? Vad händer om det inte tas om hand?
Javas IOsystem http://download.oracle.com/javase/tutorial/essential/io/ Uppbyggt runt så kallade strömmar (stream) En ström: enkelriktad överföring av data Input stream: från något externt till programmet Output stream: från programmet till något externt Externt : ex annan enhet, fil, url, annan dator import java.io.*;
Lokal användare System.in Javaprogram Filer Andra datorer via internet xxx xxxxxx xx xx xxxxxxx xxxx xxxxxxxxx xxxxxxxxx xxxxxxxxxxxx xxxxx xxxxxx xxx xxxxxx xx xx xxxxxxx xxxx xxxxxxxxx xxxxxxxxx xxxxxxxxxxxx xxxxx xxxxxx xxx xxxxxx xx xx xxxxxxx xxxx xxxxxxxxx xxxxxxxxx xxxxxxxxxxxx xxxxx xxxxxx
Strömtyper Olika slags strömmar för att överföra olika slags saker Byte stream Character stream Data stream Object stream
Strömtyper = klasser ObjectOutputStream DataInputStream FileReader... Som alltid: omöjligt att lära sig allt. Lär dig ett exempel som funkar och var du ska slå upp information
Strömmar = objekt Instansiera en klass för att få en ström Typiskt: konstruktorn har en parameter som talar om vart strömmen leder. ex: new FileReader("words.txt") Detta returnerar en inputström från filen words.txt Den bör bindas till en variabel så att vi kan använda den, ex wordsinput = new FileReader("words.txt") Sådana variabler ska förstås deklareras som alla andra. Ofta ligger viktiga strömmar i instansvariabler.
read / write Inputströmobjekt har metoder för att läsa från strömmen. Typiskt heter de något med read. Exakt vad och vilken signatur beror på strömmen. Ex: readobject() På samma sätt har outputströmmar metoder för att skriva till strömmen. Alla metoder för att skapa, skriva till eller läsa från strömmar kan kasta IOException, och måste ha exception handlers
Exempel: filkopiering FileReader inputstream = null; FileWriter outputstream = null; Skapar strömmar try { till och från filer inputstream = new FileReader("xanadu.txt"); outputstream = new FileWriter("characteroutput.txt"); int c; while ((c = inputstream.read())!= -1) { outputstream.write(c); catch (IOException e) { System.out.println( Error: +e.getmessage()); finally { if (inputstream!= null) inputstream.close(); if (outputstream!= null) outputstream.close(); inputstream.read() läser ett tecken i form av heltal. Dito för outputstream.write() Exception kan kastas när vi skapar, läser eller skriver Se till att stänga filerna när vi är klara
Exempel: ObjectStream Den mest generella strömmen Kan transportera objekt av skilda slag ObjectOutputStream och ObjectInputStream Wrapping: Konstruktorn tar en parameter som är en dataström. Returnerar en objektström som använder denna
Javaprogram myobjectstream mystream xxx xxxxxx xx xx xxxxxxx xxxx xxxxxxxxx xxxxxxxxx xxxxxxxxxxxx xxxxx xxxxxx xxx xxxxxx xx xx xxxxxxx xxxx xxxxxxxxx xxxxxxxxx xxxxxxxxxxxx xxxxx xxxxxx xxx xxxxxx xx xx xxxxxxx xxxx xxxxxxxxx xxxxxxxxx xxxxxxxxxxxx xxxxx xxxxxx ObjectInputStream myobjectstream = new ObjectInputStream(myStream)
ObjectOutputStream har en metod writeobject() Den är void och tar en parameter: det objekt som ska skrivas. parametern måste implementera det speciella interfacet Serializable. Interfacet är tomt men talar om för Java att finna ett sätt att överföra objekten De flesta enkla klasser som String implementerar detta. Vill du att objekten i en egen klass ska kunna skickas skriv implements Serializable i klasshuvudet.
ObjectInputStream har en metod readobject() Den har inga parametrar och returnerar något av typ Object. Object är Javas översta klass i klasshierarkin: alla klasser är underklasser till Object. Använd casting för att specifiera objektet närmare Exempel: läs en String message = (String)myObjectStream.readObject(); Downcasting till String. Gör så att högerledet anses ha typ String. Om det i själva verket har annan typ kastas ett exception
Idiom try { String message = (String)myObjectStream.readObject(); process the message as a String catch (ClassNotFoundException e) { System.out.println("Unknown object received");
class MyData implements Serializable { int a; String name;..... Exempel: Lagra ett objekt på en fil MyData dataitem =... ; ObjectOutputStream output;... try { output = new ObjectOutputStream( new FileOutputStream( myfile )); catch (IOException e) { System.out.println ( Error opening file );... try { output.writeobject(dataitem); catch (IOException e) { System.out.println ( Error writing to file );
class MyData implements Serializable { int a; String name;... MyData dataitem; ObjectInputStream input;... try { Exempel: Läs ett objekt från en fil input = new ObjectInputStream( new FileInputStream( myfile )); catch (IOException e) { System.out.println ( Error opening file );... try { dataitem = (MyData)input.readObject(); catch (ClassNotFoundException e) { System.out.println ( Incorrect object on file ); catch (IOException e) { System.out.println ( Error reading from file );
Nätverksprogrammering http://download.oracle.com/javase/tutorial/networking/sockets/ Hur man skickar data mellan datorer via internet
Internet Protokoll: Serie konventioner för hur kommunikation ska gå till IP: Internet Protocol, ett protokoll som används vid internet. Vanligast nu är IPv4. Paketorienterat (jfr skicka avgränsade paket) TCP: Transmission Control Protocol, använder sig av IP. Förbindelseorieterat (jfr ett telefonsamtal) Sockets: ett programmeringsgränssnitt för att använda TCP. Java har olika Socketklasser. import java.net.*;
Lite historia 1960-talet: datorer kan kommunicera 1969: två första noderna i ARPANET (mellan UCLA och SRI) 1971: ARPANET har 15 noder 1974: ordet Internet används 1981: CSNET finansieras av NSF 1982 TCP/IP standardiseras mitten 1990-talet: genombrott i hemmen. Java börjar spridas.
IP-adresser Varje internetansluten dator har en IP-adress. Kan jämföras med telefonnummer. För att kontakta datorn måste man ange dess IP-adress. En IP-adress består av 4 bytes separerade av punkt. Varje byte är ett tal mellan 0 och 255. Exempel: min IP just nu är 130.238.11.198 IP-adressen ändras när datorn rör sig fysiskt mellan olika nät (till skillnad från tex telefonnummer). Den speciella adressen localhost leder alltid tillbaka till samma dator. Bra när man testar.
Vad är min IP? InetAddress.getLocalHost().getHostAddress() Returnerar en String som representerar IPadressen. OBS: Den kastar IOException try { title = "I am at IP "+InetAddress.getLocalHost().getHostAddress(); catch (IOException e) { title = "Unable to determine IP";
Portar Varje dator har 216 = 65536 stycken portar Portarna har ingen fysisk motsvarighet. Kan anses vara lokala anknytningar inom datorn. Varje tillämpning har en specifik port den kan bli kontaktad på. För din egen tillämpning: välj ett portnummer. Helst inte ett som redan är i bruk. Undvik nummer mindre än 1024.
Sockets Ett sätt att etablera TCP-förbindelse mellan två datorer. Uppkopplingsfasen är asymmetrisk. Den ena, Client, kopplar upp aktivt mot ett visst IP och viss port. Den andra, Server, lyssnar efter uppkopplingsförsök vid en viss port. När förbindelsen väl är igång är situationen symmetrisk: Båda datorerna har en inputstream och en outputstream. Jfr telefonsamtal. Den ena ringer och den andra blir uppringd, men sedan är samtalet symmetriskt
Klassen Socket Objekt av klassen Socket svarar mot existerande uppkopplingar mot andra datorer. De har metoder bl.a. för att ta fram strömmarna och för att stänga sig. OutputStream getoutputstream() InputStream getinputstream() För att skicka data, ta fram Outputströmmen och skriv på den. Samma för input. void close()
Uppkoppling Asymmetrisk. Det finns en Client sida och en Server sida. Client skapar sin socket genom att helt enkelt använda konstruktorn Socket(). Den tar två parametrar: 1. IP-numret att koppla upp sig mot (String) 2. Portnumret för tillämpningen (int) mysocket = new Socket( 130.238.11.198, 12345)
OBS: Kastar IOException om uppkopplingen misslyckades. try { mysocket = new Socket( 130.238.11.198, 12345) catch (IOException e) { System.out.println( Could not connect to server )
Servern använder klassen ServerSocket. Konstruktorn har en parameter: portnumret den ska betjäna (int) Den skapar ett ServerSocket - objekt. Detta objekt har en metod accept() som väntar på anslutningar från en client När en sådan kommer returnerar accept() en Socket. myserver = new ServerSocket(12345); mysocket = myserver.accept(); OBS: detta kastar också IOException och bör omslutas av try-catch.
Kommunikation Symmetrisk. En förbindelse mellan två datorer använder en socket i vardera datorn, och kan ta fram input och outputströmmar myinput = mysocket.getinputstream() myoutput = mysocket.getoutputstream()
Client mysocket = new Socket(ipNumber, port) Server myserver = new ServerSocket(port); mysocket = myserver.accept(); Uppkoppling klar myoutput = mysocket.getoutputstream() myinput = mysocket.getinputstream() myoutput = mysocket.getoutputstream() myinput = mysocket.getinputstream() objectoutput = new ObjectOutputStream(myOutput) objectoutput = new ObjectOutputStream(myOutput) objectinput = new ObjectInputStream(myInput) Strömmar klara objectinput = new ObjectInputStream(myInput) objectoutput.writeobject( Hello ) m = (String)objectInput.read() m = (String)objectInput.readObject() objectoutput.writeobject( Hi )
Superviktigt Allt måste omslutas av en try-catch med ett finally block. Finally blocket måste göra close() på alla strömmar och sockets. I annat fall kan en port forsätta vara reserverad efter att programmet slutat. Om det händer, logga ut och logga in
class MainClass { public static void main(string[] parameters) { new Chat(); Chat: Client och Server är olika class Chat { bara i uppkopplingen Chat() { dialog för att välja Server eller Client if (valt Client) { dialog för att välja ip och port Socket socket = new Socket(ip,port); new ChatParticipant(socket); else { dialog för att välja port ServerSocket server = new ServerSocket(port); Socket socket = server.accept(); new ChatParticipant(socket); Samma! OBS: Ett skelett - det saknas tex exception handlers
ChatParticipant socket ChatParticipant socket dataströmmar constructorn GUI /Jframe med paneler, textfält, knappar etc)
Vilka händelser kan inträffa som måste tas om hand? Vilka aktiviteter ska kunna göras? meddelande från annan användare ChatParticipant socket meddelande till annan användare meddelande från min användare dataströmmar GUI Visa text i textarean klick på slutaknappen Avsluta allt