Föreläsning 10 STRING OCH STRINGBUILDER; VARIABLERS SYNLIGHET Att deklarera och att använda variabler När vi deklarerar en variabel, t ex int x; inför vi en ny variabel med ett namn och en typ. När namnet används någon annanstans i programmet, t ex x = 5; System.out.println(x); slår kompilatorn upp rätt variabel. Denna uppslagning följer vissa regler synlighetsregler. Synlighetsregler (1) Synlighetsregler (2) En parameter är synlig i den metod där den deklarerats. public class BankAccount{ public void deposit(double depositamount){ amount += depositamount; printamount(); public void printamount(){ System.out.println( The amount is + amount); En lokal variabel är synlig från den punkt den deklarerats till blockets { slut. public void calculation(){ int x = 32; if(x > 0){ int y = x*10; System.out.println(x);
Synlighetsregler (3) Synlighetsregler (4) En lokal variabel som deklarerats i en for-sats är endast giltig inom for-satsen. for(int i = 10; i >= 0; i -= 2){ System.out.println( Now the counter is + i); System.out.println( Now the counter is + i); // FEL Den sista raden ger ett kompileringsfel: i cannot be resolved to a variable Attribut och metoder är synliga inom klassen. public class BankAccount{ private double amount; public void deposit(double depositamount){ amount += depositamount; printamount(); public void printamount(){ System.out.println( The amount is + amount); public class Scopes { private int a; public Scopes(int a) { this.a = a; System.out.println(a); public void p1() { double a = 5.3; System.out.println(a); public void p2() { if (6 * 7 == 42) { boolean a = true; System.out.println(a); public void p3() { { a = 9; System.out.println(a); public static void main(string[] args) { Scopes s = new Scopes(29); s.p1(); s.p2(); s.p3(); Varje gång namnet a används söker kompilatorn upp motsvarande deklaration. Börja leta bland föregående satser i det block { där namnet används Sök därefter utåt, från blocket, via metoden, till klassen Den närmsta deklarationen (enligt denna ordning) används Alltså: En deklaration är giltig i det block { där den står En deklaration kan skuggas av en annan (närmare) Parametrar är giltiga i metoden Programmet skriver ut fyra värden. Vilka? String & StringBuilder
Klassen String Slå ihop (konkatenera) strängar Klassen String beskriver en teckensträng (en följd av tecken). String s = "En massa tecken" String empty = ""; s empty en massa tecken String s1 = "En text"; String s2 = "En text till"; String result = s1 + " och " + s2; En text s1 s2 result En text till En text och En text till Längden på en sträng Notera att Längden på en sträng kan man få veta genom att anropa metoden length() String s1 = "Hej"; String s2 = "4%&6"; String s3 = ""; System.out.println(s1.length()); System.out.println(s2.length()); System.out.println(s3.length()); Strängen i sig är alltid ett objekt. Man kan alltså anropa en metod direkt på ett strängvärde. Följande: "Hej".length();..är alltså möjligt, och är samma sak som new String("Hej").length(); (Den andra konstruktionen är faktiskt möjlig för alla objekt, om man inte behöver en referensvariabel till dem.)
Pseudokod: behandla alla tecken i strängen Kod: Behandla alla tecken i strängen String s =...; for (int i = 0; i < s.length(); i++) { // aktuellt tecken nås med // anropet s.charat(i); Exempel. Räkna antal blanktecken i strängen s. int spaces = 0; for (int i = 0; i < s.length(); i++) { if (s.charat(i) == ' ') { spaces++; Viktiga operationer på String (urval) Vad jämförs egentligen här? /* Skapar en tom sträng("") */ String(); /* Ger antalet tecken */ int length(); /* Ger tecknet som ligger på plats pos */ char charat(int pos); /* true om innehållet i aktuell sträng är lika med innehållet i s */ boolean equals(object s); /* jämför aktuell sträng med s */ int compareto(string s); /* index för den första förekomsten av ch, -1 om ch inte finns */ int indexof(char ch); /* ny sträng med tecknen med index [start, end) */ String substring(int start, int end); if (s1 == s2) { System.out.println("Samma objekt"); else { System.out.println("Inte samma objekt"); Här jämförs innehållet i referensvariablerna s1 och s2. Vi kontrollerar alltså om s1 och s2 refererar till samma objekt eller inte. s1 s2 abc abc
Jämföra teckensträngar med equals Vill man jämföra innehållet i teckensträngarna måste man använda equals. Från specifikationen: /* Returnerar true om innehållet i aktuell sträng är lika med innehållet i s. */ boolean equals(object s); if (s1.equals(s2)) { System.out.println("Samma innehåll"); else { System.out.println("Inte samma innehåll"); Jämföra teckensträngar med compareto (bokstavsordning) /** Jämför aktuell sträng med s. Returnerar 0 om teckensträngarna är lika, ett negativt tal om aktuell sträng är mindre än s, ett positivt tal om aktuell sträng är större än s.*/ int compareto(string s); String s1 = "java"; s1.compareto("java") kommer ge ett svar == 0 s1.compareto("javac") kommer ge ett svar < 0 s1.compareto("java") kommer ge ett svar > 0 s1.compareto("jazz") kommer ge ett svar < 0 Klassen StringBuilder Klassen StringBuilder beskriver en följd av tecken som kan läsas av och ändras. StringBuilder b = new StringBuilder("En massa tecken"); b.append('!'); b En massa tecken! Varför StringBuilder? Man kan skapa strängar stegvis med String, men det är inte alltid effektivt. Här skapas en ny sträng (ett nytt objekt) i varje tilldelning. Ibland är det ineffektivt att skapa nya objekt på detta sätt. (Det gör ingen skillnad om man använder +=.) public static String fib(int n) { int f0 = 0; int f1 = 1; int f2 = 1; String result = "1"; for (int i = 2; i <= n; i++) { f2 = f1 + f0; f0 = f1; f1 = f2; result = result + " " + f2; return result;
String vs. StringBuilder Vid omfattande manipulationer av strängar rekommenderas StringBuilder. StringBuilder gör att man dynamiskt och effektivt kan ändra i en och samma sträng. Typiskt används metoderna append och insert. Så länge man hanterar konstanta (oföränderliga) strängar är String både enklare och effektivare. Viktiga operationer på StringBuilder Skapa, ta reda på längd och tecken (som String): /* Skapar en tom strängbuffert */ StringBuilder(); /* Skapa en strängbuffert innehållande en kopia av s * StringBuilder(String s); /* Returnerar antalet tecken i bufferten */ int length(); /* Ger oss tecknet på plats pos */ char charat(int pos); Skapa String-objekt med samma innehåll: /* skapar ett String-objekt med samma innehåll som denna strängbuffert */ String tostring(); Ändra innehållet i StringBuilder-objekt /* ändrar tecknet på plats k till ch */ void setcharat(int k, char ch); /* lägger till s efter tecknen */ StringBuilder append(string s); /* lägger in s på plats k, flyttar tecknen efter*/ StringBuilder insert(int k, String s); /* tar bort tecknet på plats k */ StringBuilder deletecharat(int k); Man kan sätta in värden av andra typer än String i ett StringBuilderobjekt. Det finns flera metoder append och insert. Dessa har en parameter av typen int, double, char,...! Tidigare exempel, nu med StringBuilder public static String fib(int n) { int f0 = 0; int f1 = 1; int f2 = 1; StringBuilder result = new StringBuilder("1"); for (int i = 2; i <= n; i++) { f2 = f1 + f0; f0 = f1; f1 = f2; result.append( ); result.append(f2); return result.tostring();
StringBuilder Metoden tostring Vad händer här? String s =...;... StringBuilder b = new StringBuilder(s); int i = 0; while (i < b.length() - 1) { if (b.charat(i) ==. ) b.charat(i) ==, ) { b.insert(i + 1, ); i++; i++; s = b.tostring(); Det är vanligt att man lägger till metoden tostring i sina klasser. Metoden tostring anropas automatiskt inuti println och används av debuggern. Den kan alltså användas för att presentera objektet på ett läsligt sätt. tostring deklareras såhär: public String tostring() Metoden tostring Metoden tostring i klassen Point (kap. 3) skulle kunna se ut så här: public String tostring() { return x + " " + y; eller så här: public String tostring() { StringBuilder b = new StringBuilder(); b.append(x); b.append(' '); b.append(y); return b.tostring(); För enstaka uttryck gör Java automatiskt strängkonkatenering med hjälp av StringBuilder. Dessa två exempel är alltså ekvivalenta. saippuakivikauppias
Övning på String Åter till main-metoden Skriv en metod som returnerar true om en given sträng är en palindrom och false i alla andra fall. Lös uppgiften i steg: 1. Palindrom utan mellanslag, endast stora bokstäver. 2. Palindrom med mellanslag, endast stora bokstäver. 3. Palindrom med mellanslag, stora och små bokstäver. public class Example { public static void main(string[] args) { System.out.println( Java är lajbans! ); Programmet är en klass Main-metoden är en metod som andra (men har en speciell uppgift) Main-metoden är statisk (precis som metoderna i Math) Main-metodens parameter är en vektor av strängar Lunds Tekniska Högskola Xxxxxxxxxxxxxxxx Xxxxxxxxxxxxxx ÅÅÅÅ-MM-DD