f1pt F4 Läsanvisning: kap 6+7, vänta med 7.7, 7.8 · Metoder, parameteröverföring · synbarhet (scope), överlagring (overloading) · Fält Nästa gång: Nästa föreläsning handlar om ett exempel där vi använder det vi lärt oss hittills och ser på att att tolka felutskrifter från kompilatorn. Näst-nästa gång: Rekursion kap 8 F5 1 import java.util.Scanner; public class Interest4 { p s void main(String[] args) { // ##### read input ##### Scanner sc = new Scanner(System.in); System.out.print("input amount: "); double amount = sc.nextDouble(); S.o.print("input interest in %: "); double interest = sc.nextDouble(); S.o.print("input nbr of years: "); int years = sc.nextInt(); // simple error handling of input if (amount <= 0 || interest < 0 || years < 1) { S.o.p("One of amount<=0, interst<0, year<1 "); } else { // compute interst TODO: method interest = interest/100 + 1; double result = amount; for (int i = 1; i<=years; i++) { result = result * interest; } // print result //formating TODO System.out.println(result); } } } // end Interest F5 2 Metoder - en funktion: medel metodhuvud, funktionshuvud, signatur modifierare formella resultatvärdets typ parametrar metodens namn public static double medel(int v1, int v2){ return (v1+v2)/2.0; } // end medel metodens resultat metodkropp metodens resultat kan vara av vilken typ som helst, även en klass. Anrop tex: double medel1 = medel(5, 10); aktuella parametrar F5 3 Ett program med metoder public class EnkelMatematik1 { public static double medel(double v1,double v2){ return (v1 + v2)/2.0; } // end medel; //--------------------p s v main(String[] args){ // tal1 och tal2 får värden // på något sätt double tal1 = 2.0; double tal2 = 3.0; double c = 5.3; // exempel på anrop mv = medel(tal1, 4.0) + c; mv = medel(tal1+4, tal2); mv = medel(tal1, tal2); S.o.print("Medelvärdet är: "); S.o.println(mv); //ett alternativ till sista raden S.o.println(medel(tal1, tal2)); } // end main } // end EnkelMatematik F5 4 Antag tilldelning av 2.0 och 3.0 som ovan mv = medel(tal1, tal1+1.0); <=> mv = medel(2.0, 3.0)); <=> mv = 2.5; 2.0 3.0 medel mv = medel(tal1, tal1+1.0); <=> mv = 2.5; F5 5 Parameteröverföring I Java överförs alltid parametrarna via värdeanrop dvs värdet av den aktuella parametern kopieras över till den formella parametern. public static int sqr(int x) { ... detaljer ointressanta } int tal = 5; int resultat; resultat = sqr(tal); aktuell parameter 5 tal formell parameter 5 x värdet av tal beräknas och kopieras till x tal och x är olika fysiska objekt Det spelar ingen roll om dom har samma namn, det är ändå två olika variabler: public int sqr(int tal) {... osv} int tal = 5; int resultat; resultat = sqr(tal); F5 6 Synbarhet (Scope) Regel: En variabel “syns” från det den deklareras tills dess att blocket den deklarerats i tar slut. int global = 4; if (<villkor>) { int drömMoms = 3; // här finns drömMoms och global .... } else { // här finns inte drömMoms // men global finns ... } // här finns inte drömMoms // men global finns -----------------------------static double sqr(double x){ double tmp = x*x; return tmp; } // end sqr; // här finns inte tmp och inte x F5 7 Overloading (Överlagring) Två eller flera metoder kan ha samma namn om dom skiljer sig åt i sina parametrar. public static int max (int a, int b) { if (a>b) { return a; } else { return b; } } public static int max (int a, int b, int c) { if (a>b) {... } public static double max (double a, double b) { if (a>b) {... } F5 8 Metoder = funktioner och procedurer ”Använd en funktion om du kan en procedur om du måste” Skall göra en sak bra. Funktioner beräknar värden. De utvidgar uttrycksdelen av språket. Ett funktionsanrop · är ett uttryck · och har en (retur)typ ≠ void · beräknas till ett värde som returneras tal1 = ...; tal2 = ... mv = medel(tal1, tal2); Procedurer utför åtgärder De utvidgar satsdelen av språket Ett proceduranrop • är en sats • returnerar inget värde (returtyp = void) System.out.print("Störst är: "); F5 9 Vårt program med en metod – struktur import java.util.Scanner; public class Interest6 { /** // Javadoc om metoden * InterestOnInterest ... */ p s double interestOnInterest (double amount, double interest, int years) { ... } // end interestOnInterest // ----------------------------p s v main(String[] args) { // ##### read input ##### ... // ##### compute interest ##### double result = interestOnInterest( amount, interest, years); // ##### print result ##### System.out.println(result); } } // end Interest Skall felhanteringen flytta med till metoden? Ja troligen. F5 10 /** * InterestOnInterest computes the interest * on the given amount during "years". * @param amount to compute interest on * @param interest in percentage * @param years number of years * @return The amount after “years” years. * @author Erland Holmström */ p s double interestOnInterest throws IllegalArgumentException( double amount, double interest, int years) { // error handling if (amount <= 0 || interest < 0 || years < 1) { throw new IllegalArgumentException( "One of amount<=0, interest<0, years<1"); } else { interest = interest/100 + 1; for (int i = 1; i<=years; i++) { amount = amount * interest; } return amount; } } // end interestOnInterest F5 11 Att kasta en exception throw new IllegalArgumentException("text"); Vanliga fördefinierade som du kan använda: IllegalArgumentException, ArithmeticException, IndexOutOfBoundsException, NumberFormatException, InputMismatchException Att fånga en exception: (aldrig där den kastas) try { … satser som kan kasta en exception } catch(NumberFormatException e ) { - åtgärda och fortsätt som vanligt - e.printStackTrace(); - System.out.println(e.getMessage()); - throw e; - throw new <Exnamn>(“<felmedd.>”); - System.exit(1); } F5 12 Fält, vektorer, matriser, arrays · Har numrerade komponenter. · Komponenterna selekteras med index av diskret typ, indexeras från noll till length-1 · Alla komponenter är av samma typ. · Komponenterna kan vara objekt. 0 1 2 3 4 5 temp temp[2] Skapa fält: Deklarera ett fält med 6 reella variabler: double[] temp = new double[6]; Deklaration och “Snabbtilldelning” med ”Array initializer” int[] tmp = {0,1,2,3,4,5}; Fungerar bara vid deklarationen dvs tmp ={0,1,2,3,4,5}; GÅR INTE F5 13 Tilldela och läsa fältvärden antag: int[] tmp = {0, 1, 2, 3, 4, 5}; Tilldelning av *ett* fältvärde tmp[1] = 8; //{0,8,2,3,4,5} Tilldelning av *hela* fältet i en loop for(int i = 0; i < tmp.length; i++) { tmp[i] = 1; } läsa ett fältvärde int value = tmp[1]; • fältet ändras inte vid läsning • Fältets längd = tmp.length (är ingen metod) • Index kan vara ett (heltals-)uttryck • Fältet initialiseras automatiskt till 0 • Längden på ett fält kan inte ändras F5 14 Bearbeta fältets värden antag: double[] tmp = new double[5]; Mönster: for( int i = 0; i < tmp.length; i++ ) { // bearbeta enskilda fältvärden här } Multiplicera index med 2 respektive Multiplicera innehållet med 2 for(int i = 0; i<tmp.length; i++){ tmp[i] = 2*i; tmp[i] = 2*tmp[i]; } //{0,2,4,6,8} mult. index*2 //{0,4,8,12,16} mult. innehåll*2 Räkna alla element < 10 // i, j är vanliga namn på loop-index int antal = 0; for (int i = 0; i < tmp.length; i++) { if (tmp[i] < 10) { antal = antal + 1; } } <- Här innehåller antal antalet element < 10 F5 15 Fält och metoder Summera innehållet i ett fält double sum = 0.0; for (int i = 0; i < tmp.length; i++){ sum = sum + tmp[i]; } System.out.println(sum); Summera innehållet i fältet i en metod p s double sumArray(double[] arr) { double sum = 0.0; for (int i = 0; i<arr.length; i++){ sum = sum + arr[i]; } return sum; } Skapa fält genom att anropa en metod p s double[] fillArray(int size) { double[] tmp = new double[size]; for (int i = 0; i<tmp.length; i++){ tmp[i] = 1.0; // eller nåt } return tmp; } OBS Tester på tomma fält utelämnade. Loopar som dessa måste man kunna skriva i sömnen! F5 16 Kopiera ett fält int[] f1 = {0,1,2,3,4,5}; int[] f2 = new int[6]; f2 = f1; // blir INTE som du tänkt Du måste kopiera element för element: for (int i = 0; i<f1.length; i++){ f2[i] = f1[i]; } Ofta gör man detta i en metod: static int[] copyArray(int[] arr) { int[] tmp = new int[arr.length]; for (int i=0; i<arr.length; i++){ --> tmp[i] = arr[i]; --> } return tmp; } Anrop f2 = copyArray(f1); Parameteröverföring igen: Vad händer om vi gör arr[i] = 5; inuti loopen? (Före resp. efter tilldelningen) F5 17 Parameteröverföring Regeln var: ”Värdet av den aktuella parametern kopieras över till den formella parametern.” int[] f1 = {1,5,3,7,4,5,....}; int[] f2 = null; int[] copyArray(int[] arr) { int[] tmp = new int[arr.length]; ...kopiera ... return tmp; } f2 = copyArray(f1); aktuell f1 17B27 • värdet av f1 formell param. beräknas och kopieras arr till arr 17B27 • f1 och arr pekar ut samma minnesplats lokal param. f2 1A23 tmp 1A23 • Innehållet i arr kopieras till tmp • tmp och f2 refererar till samma fysiska objekt • tmp och arr tas bort, f1, f2 finns kvar F5 18 Vanligaste felen med fält “null pointer exception” int[] f1 = {0,1,2,3,4,5}; int[] f2; for (i = 0; i < f1.length; i++){ f2[i] = f1[i]; } Test.java:10: variable f2 might not have been initialized f2[i] = f1[i]; ^ 1 error f2 = f1; // funkar men ... F5 19 Vanligaste felen med fält 2 mer “null pointer exception” p s double sumArray(double[] arr) { if( arr == null //kolla alltid || arr.length == 0){ //beror på exception (“arr not initialized”) } else { double sum = 0.0; for (int i = 0; i<arr.length; i++){ ... bearbeta fältet } “array index out of bounds” double sum = 0.0; for (i = 0; i <= f1.length; i++){ sum = sum + f1[i]; } eller int[] f1 = {0,1,2,3,4,5}; for (i = 0; i <= 6; i++){... F5 20 Flerdimensionella fält (matriser) Är fält med fält som värden Raderna behöver inte vara lika långa int[][] m = new int[3][6]; for( int i=0; i< m.length; i++ ) { for( int j=0; j < m[i].length; j++ ) { m[i][j] = 0; } } m innehåller nu 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 man kan även göra int[][] m2 = { {1, 2, 3, 4, 5, 6}, {1, 1, 1, 1}, {6, 5, 4, 3, 2, 1} }; F5 21 Att formatera utskrifter 1 I PrintStream finns en metod som kan formatera utskrifterna bättre: ”printf” printf(String format, Object args) % [flags] [width] [.precision] conversion-char ( square brackets denote optional parameters ) % start på format string width - det minimala antalet tecken precision - antalet decimaler conversion-character: d : decimal integer [byte, short, int, long] f : floating-point number [float, double] e : scientific notation c : character s : String (det finns fler) System.out.printf ("Calling isPrime() %.0e times,", max ); System.out.printf("%4d %8d\n", r, r*r) @see PrintStream @see sök på ”Java printf( ) method” @see java.util.Formatter (An interpreter for printf-style format strings.) F5 22 Att formatera utskrifter 2 String class format( ) method: ”You can build a formatted String and assign it to a variable using the static format method in the String class. The use of a format string and argument list is identical to its use in the printf method. The format method returns a reference to a String.” Example: String grandTotal = String.format ("Grand Total: %-10.2f", dblTotal); @see java.lang.String class, method format @see java.util.Formatter class F5 23 ** Att formatera utskrifter 3 @see java.text.Format: Format is an abstract base class for formatting locale-sensitive information such as dates, messages, and numbers. @see java.text.NumberFormat: NumberFormat is the abstract base class for all number formats @see java.text.DecimalFormat: DecimalFormat is a concrete subclass of NumberFormat that formats decimal numbers. import java.util.*; import java.text.DecimalFormat; public class FormateraTest { ps... void main(String[] args) { double dollarKurs = 8.14; double kr = new Double(args[0]).doubleValue(); DecimalFormat f = new DecimalFormat("0.00"); String dollars = f.format(kr/dollarKurs); ...print(kr + " motsvarar "); ...println(dollars + " dollar"); } } F5 24 ** Utvecklingen av printf From Cay Horstmann's Home Page The March of Progress 1980: C printf("%10.2f", x); 1988: C++ cout <<setw(10) <<setprecision(2) <<showpoint <<x; 1996: Java java.text.NumberFormat formatter = java.text.NumberFormat.getNumberInstance(); formatter.setMinimumFractionDigits(2); formatter.setMaximumFractionDigits(2); String s = formatter.format(x); for (int i = s.length(); i < 10; i++) System.out.print(' '); System.out.print(s); 2004: Java System.out.printf("%10.2f", x); 2008: Scala and Groovy printf("%10.2f", x) (Thanks to Will Iverson for the update. He writes: “Note the lack of semi-colon. Improvement!”) F5 25 Ordlistan växer... metoder (funktioner, procedurer), parameteröverföring, metodhuvud, funktionshuvud, signatur, formell/aktuell parameter. uttrycksdel, satsdel, värdeanrop, synbarhet, scope, overloading, överlagring, Fält, vektorer, matriser, arrays, deklarera, index av diskret typ, initialisera, F5 26