Mer Java jonas.kvarnstrom@liu.se 2015
Fråga kommentera avbryt!
Historia: C, C++ 1960-talet: CPL BCPL B 1969-1973: C skrev om delar av Unix-kärnan 1978: K&R C "The C Programming Language" av Kernighan & Ritchie 1979: C with Classes OO-finesser från Simula (Bjarne Stroustrup) 4 1983: C++ Vidareutveckling "C++": "C = C + 1" 1985: The C++ Programming Language (bok) 1989: C++ 2.0
Historia: Oak 1 1990: Sun Microsystems påbörjade projekt StarSeven Avancerad interaktiv multikontroll : TV, video, satellit, Touchskärm, dra program i listan till en video, Trådlöst nätverk Unix-OS 5
Historia: Oak 2 Ville ha ett objektorienterat programmeringsspråk C++ sågs som problematiskt James Gosling utvecklade sitt eget: "C++ ++ " Omdöpt till "Oak" 1991 1994: Skapa spinoff-företag Bygga, programmera, demonstrera Gå i konkurs 6
Historia: Oak 3 Hitta en annan användning! 1994: WWW på gång Nov 1993: 500 WWW-servrar! Okt 1994: Netscape Mosaic 0.9! 7 Webben var väldigt statisk Interaktivitet? Formulär! JavaScript? Slutet av 1995 Flash? 1996 Oak passade perfekt! Portabelt, plattformsoberoende Bra stöd för nätverkskommunikation Språket döptes om till Java Än idag har vi många arv kvar från C++, C, och till och med B (1969)
Sammansatta tilldelningsoperatorer 9 public class JavaTest { public static void main(string[ ] args) { int sum = 2; sum++; // Förkortning för sum += 1 Våra kodexempel kommer att använda detta "skal" Inkrementering och dekrementering Inkrementering och dekrementering: ++, Kan användas inuti uttryck men man blir lätt förvirrad! int a = 12, b = 12; System.out.println(a++); // Beräkna a, sedan öka: 12 System.out.println(++b); // Öka b, sedan beräkna: 13 System.out.println("After: a = " + a + ", b = " + b); // a=13, b=13 increment, decrement
Villkor med kortslutning: eller 10 public class JavaTest { public static void main(string[ ] args) { int percent = ; if (percent < 0 percent > 100) { error(); Motsvarar "or" i Python: Om första testet är sant, behövs inte andra testet Kortslutande "eller": Räkna till värdet är känt Ekvivalent med: if (percent < 0) { error(); else if (percent > 100) { error(); I detta exempel: Bra för prestanda! kortslutning = short-circuit
Villkor utan kortslutning: eller 11 public class JavaTest { public static void main(string[ ] args) { if (saveifneeded("foo") saveifneeded("bar")) { status.settext("saved at least one file!"); Beräknar alltid båda operanderna Icke kortslutande "eller": Fortsätt evaluera hela uttrycket Motsvarar: boolean save1 = saveifneeded("foo"); boolean save2 = saveifneeded("bar"); if (save1 save2) { status.settext("saved at least one file!"); I detta exempel: Viktigt för korrekthet Skriv hellre om enligt nedre exemplet
Villkor: och 12 public class JavaTest { public static void main(string[ ] args) { if (debugmode &&!slowtestsucceeds()) { Motsvarar "and" i Python: Om första testet är falskt, behövs inte andra testet Kortslutande och": && Ekvivalent med: if (debugmode) { if (!slowtestsucceeds) { I detta exempel: Prestanda
Villkor: och 13 public class JavaTest { public static void main(string[ ] args) { if (askuser("quit?") && askuser( Really?")) { Om användaren säger "nej", fortsätt inte fråga Kortslutande och": && Ekvivalent med: if (askuser("quit")) { if (askuser("really?")) { I detta exempel: Korrekthet
Villkor: If som uttryck 14 Python case1 if condition else case2 sign = "positive" if a > 0 else "non-pos" Java condition? case1 : case2 String sign = (a > 0? "positive" : "non-pos ) Kan förvirra Använd sparsamt!
Vad är sant / falskt? 15 Python: Automatisk konvertering Java: Bara boolean-värden Falska värden: False, None, 0, 0.0,, (), [], {, Sanna värden: Allt annat Falska värden: Sanna värden: Allt annat: false true inte sanningsvärde! längd = 10; if längd: # Om inte 0, (), False, print längd int längd = 10; if (längd) // Fel! if (längd!= 0) { System.out.println(längd); Ofta bekvämt Kan leda till misstag Mer att skriva Ibland tydligare Kan förhindra misstag
Villkor: Enbart boolean 16 Python: Operatorer accepterar alla värden, or / and returnerar ena operanden Python # a får värdet av s, # eller "default" om s är tom a = s or "default # Motsvarar: a = s if s else "default" Java: Booleska operatorer kräver true/false, returnerar true/false Java // Kompileringsfel: String a = s default ; // Fungerar: String a = (!s.isempty()? s : default );
sats = statement
Villkor: if 18 Python if condition: statement1 statement2... Python if condition: statement1 statement2... else: statement1 statement2... Java if (condition) { statement1 statement2... Java if (condition) { statement1 statement2... else { statement1 statement2...
Villkor: if (2) 19 Python if condition: statement1 statement2... elif condition2: statement1 statement2... elif condition3: statement1 statement2... Java if (condition) { statement1 statement2... else if (condition2) { statement1 statement2... else if (condition3) { statement1 statement2...
Test av samma uttrycks värde 20 if (x + y == 0) { System.out.println( Exakt noll"); else if (x + y == 1 x + y == 2) { System.out.println( Ett eller två"); else if (x + y == 3) { System.out.println("Exakt tre"); System.out.println( Fler satser här"); else { System.out.println( Något annat"); Här jämför vi värdet på x+y med några kända konstanter konstanter = constants
Satser: switch 21 switch (x + y) { case 0: System.out.println( Exakt noll"); break; case 1: case 2: System.out.println( Ett eller två"); break; case 3: System.out.println( Exakt tre"); System.out.println( Fler satser här"); break; default: System.out.println( Något annat"); Tydligt att man testar värdet på ett uttryck; skriv uttrycket (x+y) en gång Kan göras med en switch-sats! Fungerar för heltal, strängar och enum-konstanter Klar : Hoppa ur switch-satsen Flera fall (1 och 2) ger samma kod att utföra Frivilligt: Vad händer när inget av fallen passar? Kräver extra "break"
Satser: switch med fallthrough 22 switch (x + y) { case 0: System.out.println( Exakt noll"); break; case 1: case 2: System.out.println( Ett eller två"); case 3: System.out.println( Ett, två eller tre"); break; default: System.out.println( Något annat"); Inget break här, så vi fortsätter in i nästa fall Fallthrough kan förvirra oftast bra att skriva på annat sätt!
Iteration: break, continue 23 int i = 0; while (i++ < 100) { dosomething(i); if (!test(i)) continue; dosomethingelse(i); int i = 0; while (i++ < 100) { dosomething(i); if (!test(i)) break; dosomethingelse(i); System.out.println("After!"); Loopar: break, continue Break avbryter loopen Continue fortsätter med nästa iteration Kan förvirra oftast bra att skriva på annat sätt!
Iteration: break, continue 24 int i = 0; while (i++ < 100) { dosomething(i); if (!test(i)) continue; dosomethingelse(i); int i = 0; while (i++ < 100) { dosomething(i); if (test(i)) { dosomethingelse(i);
Undantag i Python och Java 26 Python Java try: # Kod som kan kasta undantag except ZeroDivisionError: # Här hanterar vi division med noll except (NameError, TypeError): # Hantera NameError och TypeError except: # Här hanterar vi alla andra undantag else: # Om inga undantag kastades finally: # Denna kod körs alltid, oavsett vad # som hänt, för att städa upp efteråt try { // Kod som kan kasta undantag catch (FileNotFoundException e) { // Här hanterar vi saknad fil catch (IOException SQLException e) { // Felhantering catch (Throwable e) { // Här hanterar vi alla andra undantag // (ej rekommenderat!) // Ingen motsvarighet till "else" finally { // Denna kod körs alltid, oavsett vad // som hänt, för att städa upp efteråt Mer om detta en annan gång!
Tecken och strängar Java skiljer på: 28 Enskilda tecken Primitiv datatyp char (16-bitars) Inom apostrofer char middleinitial = 'X'; char digit7 = '7'; Strängar Objekttyp String Inom citattecken String name = Jonas ; Jämförs med == if (middleinitial == Y') { Jämförs med equals() if (name.equals( Java )) {
Funktioner 30 Pythons funktioner på toppnivå kan "emuleras" i Java Använd en public static-funktion Bara till vi har Fil: Newton.java hunnit läsa om objekt! Ange alltid returtyp public class Newton { public static int findroot() { System.out.println("This program tries to find "); System.in.read ; double guess = x/2; for (int i = 1; i < 5; i++) { guess = (guess + x/guess) / 2; return guess; Returnera värde med return public static void main(string[ ] args) { System.out.println(findRoot());
Returtypen void Ange returtyp men om funktionen inte returnerar något? 31 Ange void returnerar inget Fil: Newton.java (Fungerar inte för variabeldekl.!) public class Newton { public static void findroot() { System.out.println("This program tries to find "); System.in.read ; double guess = x/2; for (int i = 1; i < 5; i++) { guess = (guess + x/guess) / 2; System.out.println(guess); public static void main(string[ ] args) { findroot();
Variabler, värden och typer jonas.kvarnstrom@liu.se 2015
Variabler En variabel används för att lagra ett värde, och består av: En lagringsplats i minnet, där ett värde kan placeras Ett symboliskt namn på lagringsplatsen, som används i koden Python längd = 10 höjd = 5 hälsning = "hello" färger = [red, green] Programkod längd höjd hälsning färger Minne vid körning 10 5 "Hello" [red, green] 33 En "låda" för ett värde: Värdet kan bytas ut (längd = 22), men det är fortfarande samma variabel
Värdetyper 34 Varje värde har en typ Även i Python (men man behöver sällan skriva typnamnet i koden) Programkod Minne vid körning print(längd) print(10) heltalsutskrift Symboliskt namn (används i koden) längd Lagringsplats för ett värde 10 Heltal print(färger) print([red,green]) listutskrift höjd hälsning 5 "Hello" Heltal Sträng färger + 2 fel! färger [red, green] Lista
Variabeltyper 35 I många språk har även variabeln en typ Gäller Java, C, C++, Pascal, Ada, : Men inte Python Programkod Minne vid körning Symboliskt namn (används i koden) Lagringsplats för ett värde Heltal längd 10 Heltal Heltal höjd 5 Heltal Sträng hälsning "Hello" Sträng Lista färger [red, green] Lista
Variabeltyper 36 Java: Manifest typsystem (även variabeln har en typ, och denna anges explicit i koden) Python: Latent typsystem (bara värdet har en typ) int längd = 10; längd är en heltalsvariabel som innehåller ett heltal längd = 10; längd är en vad-som-helst-variabel som innehåller ett heltal Varför ska man ha variabeltyper, och ange dem explicit? latent typing manifest typing
Kunskap om värdetyp Latent typsystem: Vi vet mindre innan programmet körs Python def send(x): # Kommer x att vara heltal här? Flyttal? Sträng, lista,? # Ingen aning förrän programmet körs får kontrolleras dynamiskt 37 Manifest typsystem: Java public void send(int x) { // Här är x ett heltal, och det vet vi vid kompilering statiskt Gäller kompilatorn (kan optimera mer effektivare) Gäller oss (typerna är dokumentation)
Konsekvenser: Typkontroll 38 Python: Dynamisk typkontroll def dosomething(x): y = x + 10 Är x numeriskt? Kolla värdetyp vid körning Om inte numeriskt: Signalera typfel Java: Statisk typkontroll void dosomething(int x) { int y = x + 10; Är x numeriskt? Kolla variabeltyp vid kompilering Om inte numeriskt: Signalera typfel dynamic type checking static type checking
Konsekvenser: Typkontroll Python: Värdetypen kontrolleras verkligen vid körning Dynamisk typkontroll är inte samma som "svag typning" Python 39 >>> langd=10 >>> halsning="hello" >>> halsning+langd Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: cannot concatenate 'str' and 'int' objects Men i Java hade detta upptäckts vid kompilering Tidigare upptäckt av problem effektivare programmering Typkontroll tidigare effektivare körning
Konsekvenser: Typkontroll Kontroller sker bara för den kod som faktiskt körs 40 Python def sortera(): if (antal element > 1000000): # Använd metod 1 med typfel! else: # Använd metod 2 Testar man aldrig med >1000000 element, upptäcks inte buggen förrän koden är levererad I Java hade även detta upptäckts vid kompilering Tidigare effektivare
Konsekvenser: Val av operation 41 Python: Dynamisk typkontroll def dosomething(x): y = x + 10; Måste kolla vid körning: x heltal? Addera 10 direkt Java: Statisk typkontroll void dosomething(int x) { int y = x + 10; x är heltal! Addera direkt x flyttal? Konvertera 10 till 10.0, addera x annat? Signalera fel!
Konsekvenser: Minnesutrymme 42 Python: Dynamisk typkontroll def dosomething(x): y = x + 10; Hur kolla typen hos b:s värde? Måste lagra typen med värdet Java: Statisk typkontroll void dosomething(int x) { int y = x + 10; Hur kolla typen hos b:s värde? Variabelns typ är int, värdet måste ju ha samma typ x heltal 10 int x 10 delvis därför tar ett heltal 24 bytes Ett heltal tar 4 bytes (int), 8 bytes (long)
Brasklapp En brasklapp: Terminologin för typsystem är ofta otydlig och omtvistad Många termer brukar blandas ihop Statisk typning Statisk typkontroll Manifest typning Stark typning Det ni behöver förstå är begreppen och dess konsekvenser 43 Även dynamisk typning har fördelar! Mindre att skriva Mer flexibilitet i vissa fall
Typanalys Måste man skriva typer manuellt för att få dessa fördelar? I vissa språk kan man automatiskt analysera variabeltyper Python def send(x): # Kommer x att vara heltal här? Flyttal? Sträng, lista,? 45 send(100) send(240) send(3) Anropas 3 gånger Alltid heltalsparameter Aldrig flyttal, sträng, lista Hjälper felkontrollen, men fungerar inte som dokumentation
Typanalys: Byta värdetyp Men språk med latent typning tillåter ofta att man byter värdetyp dynamiskt v = 10 v = "hello" v = [1, 2, 3, 4, 5] Python 46 Gör problemet svårare, men inte omöjligt
Typanalys: Omöjligt? Ibland är analys i förväg omöjlig Python def send(x): # Kommer x att vara heltal här? Flyttal? Sträng, lista,? 47 v = random.choice([1, "foo"]) send(v) Ska typanalys alltid vara möjlig: Designa språket så att det förbjuder denna sorts uttryck!
Primitiva (icke sammansatta) typer i Java 49 Heltalstyper lika på alla plattformar! min max byte 8 bitar -128 127 short 16 bitar -32768 32767 int 32 bitar -2147483648 2147483647 Används sällan Vanligast! long 64 bitar -9223372036854775808L 9223372036854775807L Två flyttalstyper skiljer i precision och storlek float 32 bitar ±3.40282347E-45 ±3.40282347E+38 double64 bitar ±4.9406564584124654E-324 ±1.797769313486 E+308 Övrigt boolean false, true char tecken (värden 0..65535)
Stora tal 50 public class JavaTest { public static void main(string[ ] args) { int massor = 131072 * 131072; System.out.println( 128k * 128k är: + massor); Operationer på heltal kan ge overflow "översvämning"! Operander av typ int: [-2147483648, 2147483647] Multiplikation av 32-bitarstal: 0b100000000000000000 * 0b100000000000000000 = 0b10000000000000000000000000000000000 128k * 128k är: 0 32 bitar slutresultat
Overflow 51 public class JavaTest { public static void main(string[ ] args) { int massor = 131072 * 131072; System.out.println( 128k * 128k är: + massor); // Skriver ut 0 Varför overflow i Java, men inte Python? Historia "Så var det ju i C och C++" Effektivitet! Java: 32-bitars multiplikation, klar. Python: 64-bitars multiplikation, testa storlek, allokera minne för resultat,
Använd större datatyp 52 public class JavaTest { public static void main(string[ ] args) { long massor = 131072 * 131072; System.out.println( 128k * 128k är: + massor); Beräkningar använder den största av operandernas typer 131072 är en int (inget "L") 0b100000000000000000 * 0b100000000000000000 = 0b10000000000000000000000000000000000 32 bitar slutresultat Kan verka korkat Sedan expanderas detta till 64 bitar men är mer förutsägbart: 128k * 128k är: 0 Resultat beror bara på operandernas typer
Använd större datatyp (2) 53 public class JavaTest { public static void main(string[ ] args) { long massor = 131072L * 131072; System.out.println( 128k * 128k är: + massor); Beräkningar använder den största av operandernas typer Största operanden är long Expandera den andra "131072" till long Utför 64-bitars multiplikation 128k * 128k is: 17179869184 (2 34 ) Expandering tappar aldrig information sker automatiskt!
Farliga" typkonverteringar 54 public class JavaTest { public static void main(string[ ] args) { int sqrtpi = Math.sqrt(Math.PI); System.out.println( Sqrt(π) är: + sqrtpi); Konstanter och funktioner i Math-klassen Kompileringsfel! Math.sqrt returnerar en double Att konvertera double till int kan tappa information "farligt" Måste uttryckligen be om konvertering!
Typkonvertering: Casting 55 public class JavaTest { public static void main(string[ ] args) { int sqrtpi = (int) Math.sqrt(Math.PI); System.out.println( Sqrt(π) är: + sqrtpi); Konvertera med en cast Beräkning, sedan trunkering (avhuggning) Beräknar värdet: 1,7724538509055160272981674833411 (int) trunkerar detta till: 1 Mer: int i = (int) 271828.1828; // OK i = 271828 (trunkerat) short s = (short) 271828; // OK s = 9684 (lägsta 16 bitarna) 0b1000010010111010100
Utan casting 56 public class JavaTest { public static void main(string[ ] args) { double sqrtpi = Math.sqrt(Math.PI); System.out.println( Sqrt(π) är: + sqrtpi); Byt variabeltyp Beräkningar Beräknar värdet: 1,7724538509055160272981674833411 Skriver ut det
Bakgrund Vissa typer ska bara ha några få fördefinierade värden Day: Monday, Tuesday,, Sunday 58 Suit: Clubs, Diamonds, Hearts, Spades
Background Kan emuleras på många sätt, t.ex. med heltalskonstanter final static int MONDAY = 0, TUESDAY = 1,, SUNDAY = 6; public void setdayofweek(int day) { 59 Inte typsäkert! setdayofweek(42); final static int BOLD = 2; setfont("times", 14, BOLD); setfont("times", BOLD, 14); // Accepteras av kompilatorn // Vilken betyder 14 punkter fetstil? // Vilken betyder 2 pt blinkande? Stödjer nonsensoperationer int blah = TUESDAY * SUNDAY + WEDNESDAY Efter kompilering finns bara heltalen kvar svårare att tolka Värdet är 4 betyder det torsdag eller fredag? Eller kanske grönt, spader eller giraff?
Enumerated Types Java har stöd för uppräkningstyper (enumerated types) Man räknar upp vilka värden som finns 60 public enum Day { MONDAY, TUESDAY,, SUNDAY Sju enumkonstanter Inga matematiska nonsensoperationer tillgängliga Namngivningskonvention: ALL_CAPS för konstanter enum-konstant = enum constant
Enumerated Types Distinkt typ (inte int) typsäkerhet public enum Day { MONDAY, TUESDAY,, SUNDAY 61 public void setdayofweek(day day) { setdayofweek(day.tuesday); System.out.println(Day.THURSDAY) Håller reda på namn: Skriver ut "THURSDAY", inte 4
Jämförelse Sämsta lösningen: Konstanter utan namn if (state == 4) { if (player.hitwall()) state = 1; else ; Gammal lösning: Namngivna heltal final static int STATE_STANDING = 1; final static int STATE_RUNNING = 4; if (state == STATE_RUNNING) { if (player.hitwall()) state = STATE_STANDING; Bäst, vid fixerat antal värden: Uppräkningsbar typ enum State { RUNNING, STANDING if (state == State.RUNNING) { if (player.hitwall()) state = State.STANDING; 62