1 Inmatning och utskrift Inmatning från tangentbord och utskrift till skärm sker i java med hjälp av objekten System.out och System.in. Dessa båda objekt är exempel på strömmar. En ström är en typ som kan läsa och skriva data mellan en sändare och en mottagare. Objekten in och out är medlemmar i klassen System. Finessen med strömmar är att vi får ett konsekvent sätt att läsa och skriva data oavsett källan(i deta fall konsollfönstret). in läser text i form av en InputStream, out skriver text som en PrintStream. se http://w3.miun.se/javadocs/java/io/InputStream.html och http://w3.miun.se/javadocs/java/io/PrintStream.html. Vi har tidigare sett exempel på utskrift. Vi kommer i det här avsnittet även ta upp inmatning från tangentbordet så att vi kan skapa program som kommunicerar med en användare istället för att använda värden inskrivna i programkoden. 1.1 Utskrift till skärm För att skriva data till skärmen ( konsolen) används objektet System.out tillsammans med metoden println eller print. System.out.println("Hello"); 1.1.1 Typen String Metoden println tar ett argument av typen String, texttypen (Den kan även ta enstaka värden av andra typer och omvandla dessa till string). Då man slår ihop, konkatenerar, strängar med andra typer måste man vara försiktig System.out.println( 3 + 6 + "Hello"); Vad ska skrivas ut, "36Hello" eller "9Hello" ? Det som skrivs ut är "9Hello" eftersom man utvärderar det sammansatta uttrycket från vänster till höger. Uttrycket (int)+(String) omvandlas automatiskt till ett String resultat. Detsamma gäller för andra taltyper. System.out.println("Hello" + 3 + 6); Vad blir resultatet av detta? Testa genom att foga in satsen i main.. { Blev det det du förväntade dig? 1.2 Inmatning från tangentbordet Inmatning görs med objektet System.in. Objektet är till för att läsa textrader. Eftersom man ofta vill läsa in andra värden än just hela rader av text finns en hjälpklass döpt Scanner för att underlätta inmatning av heltal, flyttal osv. För att ta emot inmatning av ett heltal från tangentbordet kan man skriva: Scanner tgb = new Scanner( System.in ); Detta är första gången då vi haft en anleding att skapa ett objekt. Uttrycket new Scanner( System.in ); innbär att vi skapar ett objekt, eller en instans, av typen Scanner. Scanner är en klass som beskriver metoder att läsa värden från en ström eller annan datakälla. Datakällan vi angivit är System.in som representerar tangentbordet. Terminologi: Konstruerare. new Scanner beskriver en konstruktion av en Scanner-instans, vi anropar en konstruerare hos Scanner. Exempel: import java.util.*; class KeyboardReading { public static void main(String [] arg) { Scanner tgb = new Scanner(System.in); System.out.println("Hur många endollarmynt har du?"); int antalDollar; antalDollar = tgb.nextInt(); System.out.println("Jaså du har "+ antalDollar + " stycken."); } } Glömmer man att lägga till ledtext till inmatningen, eller kanske rentav råkar lägga den efter inmatningen, kommer programmet att vänta på en inmatning från användaren, och användaren kommer i sin tur att inte ha en aning om att programmet väntar tålmodigt på en inmatning. 1.2.1 Klasser och objekt Vi utnyttjar klassen Scanner för att skapa objektet tgb. Vi utnyttjar sedan objektet med hjälp av medlemsväljaren . (punkt). Ett objekt har metoder och attribut dessa båda kallas sammantaget för objektets medlemmar. Tumregeln är att man använder metoder för att använda objektet. Metoderna använder (det ser vi inte) i sin tur attributen för att utföra sin uppgift. Man kan här tänka sig hur Scanner utnyttjar System.in för att läsa från tangentbordet. Det som sker bakom kulisserna är: tgb.nextInt() => läs siffertecken från System.in tills man stöter på ett mellanslag. Omvandla detta till typen int. Ge tillbaka int-värdet. Om vi vänder blicken mot den nu välbekanta satsen System.out.println ser vi att det finns två medlemsväljare. Vi kan läsa ut det som att out är en medlem av System (ett attribut), och println är en medlem av out (en metod). Programmet ovan kan ge resultatet Hur många endollarmynt har du? 7 Jaså du har 7 stycken 1.2.2 Paket Den första satsen i föregående exempel är import java.util.*; Alla klasser i javabiblioteket är uppdelade i paket, för att man enklare ska hitta dom. Om man vill använda någon annan klass än de mest basala, såsom System och String, måste man importera det paket som innehåller klassen ifråga. Scannerklassen ligger i ett paket som heter java.util och satsen import java.util.*; innebär läs in alla klasser ifrån paketet java.util. * är ett sk wildcard, och anger alltså alla klasser i paketet. Alternativt kan vi skriva import java.util.Scanner; för att bara importera just Scanner-klassen. Vilket skrivsätt vi väljer är för närvarande en smaksak. Vid större projekt och nätbaserade applikationer kan skrivsättet komma påverka applikationen, men för vårt vidkommande är det en smaksak. 1.2.3 Exempelprogram Beräkna area och omkrets hos en rektangel. En viktig komponent att skapa ett eget program utfrån en beskrivning är att först tänka sig, göra en modell, hur programmet bör fungera. Man kan till exempel tänka sig att programmet fungerar som Ange bredd: 4 Ange höjd: 2,5 Arean är 10.0, omkretsen är 13.0 Nu kan man se i vilken ordning man vill sätta ihop programsatserna import java.util.*; class KeyboardReading { public static void main(String [] arg) { double bredd, höjd; Scanner tgb = new Scanner(System.in); System.out.println("Ange bredd?"); bredd = tgb.nextDouble(); System.out.println("Ange höjd?"); höjd = tgb.nextDouble(); double omkrets = 2*bredd + 2*höjd; double area = bredd* höjd; System.out.println("Arean är "+area+", omkretsen är "+omkrets); } } 1.2.4 Övning: Skriv ett program som frågar efter hur gammal du är, och därefter berättar hur många dagar du levat. Dela upp lösningen i olika steg. Börja med att fundera på hur du vill att beräkningen ska gå till. Då du vet hur du vill att beräkningen ska fungera tänker du ut hur användardialogen (programkörningen med in och utmatningar) ska se ut. Därefter kan du börja skriva programmet genom att titta på tidigare exempel. Tänk särskilt på vilka variabler du behöver och vilka datatyper dessa variabler bör ha. 2 Mer om operatorer 2.1 Utvärderingsregler Betrakta satsen omkrets = 2*bredd + 2*höjd; Om bredden är 4 och höjden är 2.5 så vill vi att uträkningen ska utföras som 1: 2*4 =8 2: 2*2.5 =5 Därefter 3: (1:+2: ) 8 + 5 = 13 Därefter 4: omkrets = 13 För att åstakomma detta finns 2 parametrar som bestämmer i vilken ordning operatorerna utvärderas 1- Operatorprioritet 2- Utvärderingsriktning Operatorn * har högst prioritet av de inblandade operatorerna och utvärderas därför först, 1: och 2:. Därefter kommer + i prioritetsordning, 3: . Sist kommer =, tilldelningsoperatorn 4: . Utvärderingsriktning är från vänster till höger, alltså den riktning man normalt läser, för alla operatorer utom tilldelningsoperatorerna, som utvärderas från höger till vänster. Utvärderingsriktningen ger att 1: utförs före 2: Att tilldelningsoperatorn har utvärderingsriktning höger till vänster gör att man kan göra sammansatta tilldelningar såsom int i, j; i = j = 5; 1: j = 5, resultatet av denna operation är j, dvs heltalet 5 2: i = j eller om man så vill i = 5 2.2 Exempel Sammansatta satser behöver man lite träning för att tolka på ett riktigt sätt; också naturligtvis för att kunna skriva dem själv. Om en beräkning blir för komplex, delar man gärna upp den på flera mindre delar. double omkrets = 2*bredd + 2*höjd; // kan skrivas om som double omkrets = 2*( bredd + höjd ); // radien av en cirkel int diameter = 3; double radie = (double)diameter / 2; // (double) omvandlar typ på diameter double area = radie*radie* 3.14; // x upphöjt i 2 skrivs som x*x // ytan på en hel cylinder double radie = 2.0; double höjd = 4.0; double cylinderYta = 2*radie*radie*3.14159 + höjd*radie*2*3.14159; // En så pass komplex sats delar man gärna upp double radie = 2.0; double höjd = 4.0; double sidYta = höjd* radie*2*3.14159; double toppYta = radie*radie*3.14159; double cylinderYta = sidYta + 2*toppYta; Operator Precedence postfix operators expr++ expr-- unary operators ++expr --expr +expr -expr ~ ! multiplicative * / % additive + - shift << >> >>> relational < > <= >= instanceof equality == != bitwise AND & bitwise exclusive OR ^ bitwise inclusive OR | logical AND && logical OR || conditional ? : assignment = += -= *= /= %= &= ^= |= <<= >>= >>>= Källa: java.sun.com 3 Alternativ till konsollinmatning Det finns mycket hjälp att få i javas klassbibliotek om man vill skriva en grafisk applikation. För in och utmatningar kan vi enkelt få hjälp av klassen JOptionPane som är en klass som innehåller metoder för att visa olika enkla typer av dialogrutor. Om vi drar oss till minnes det första inmatningsexemplet import java.util.*; class KeyboardReading { public static void main(String [] arg) { Scanner tgb = new Scanner(System.in); System.out.println("Hur många endollarmynt har du?"); int antalDollar; antalDollar = tgb.nextInt(); System.out.println("Jaså du har "+ antalDollar + " stycken."); } } Kan det skrivas om till att använda JOptionPane och dialogrutor som import javax.swing.*; class KeyboardReading { public static void main(String [] arg) { String inmatning = JOptionPane.showInputDialog("Hur många dollar har du?"); double dollars; dollars = Double.parseDouble( inmatning ); JOptionPane.showMessageDialog( null, "Jaså du har $"+ dollars ); } } Radbrytningarna på rad 7 och 13 är gjorda för läsbarhetens skull. JOptionPane befinner sig i grafikpaketet javax.swing och därför ser import-satsen ut som den gör. Inläsningen sker med JOptionPanes medlem showInputDialog som returnerar en text, String. Inmatningen som görs i dialogrutan ges alltså tillbaka på textform. Vi har här ingen möjlighet att direkt läsa in talvärden utan är tvungen att läsa in en text, som vi sedan omvandlar till ett tal. Double är en hjälpklass till den primitiva taltypen double. Double förser oss med hjälpmetoder för att arbeta med tal av typen double, bland annat metoden parseDouble( String s ) som omvandlar strängen s till double. Samtliga enkla typer har en motsvarande komplementerande klass, double-Double, int-Integer, byteByte, char-Character osv. För att sedan presentera resultaten används showMessageDialog( null, String s); Uttrycket null betyder inget objekt. showMessageDialog förväntar sig att ett "föräldrafönster" ska äga dialogrutan, men eftersom vi inte har något föräldrafönster anger vi istället null. Texten s är förstås den text som ska visas i dialogrutan.