CodeGym/Java blogg/Slumpmässig/Fasta värden i Java: final, konstanter och oföränderlig
John Squirrels
Nivå
San Francisco

Fasta värden i Java: final, konstanter och oföränderlig

Publicerad i gruppen
Hej! Du är redan bekant med ordet "modifierare". Som ett minimum har du stött på åtkomstmodifierare (offentliga, privata) och den statiska modifieraren. Idag ska vi diskutera en speciell modifierare som heter final . Man kan säga att den sista modifieraren "cementerar" delar av vårt program där konstanta, entydiga, oföränderliga beteenden behövs. Det finns tre platser i dina program som du kan använda det: klasser, metoder och variabler. Fasta värden i Java: final, konstanter och oföränderlig - 2 Låt oss gå igenom dem i ordning. Om den slutliga modifieraren används i en klassdeklaration betyder det att klassen inte kan ärvas. I tidigare lektioner använde vi ett enkelt arvsexempel: vi hade en Animalföräldraklass och två barnklasser: CatochDog
public class Animal {
}



public class Cat extends Animal {
   // Fields and methods of the Cat class
}


public class Dog extends Animal {

   // Fields and methods of the Dog class
}
Men om vi använder den slutliga modifieraren på Animalklassen kan klasserna Catoch Doginte ärva den.
public final class Animal {

}

public class Cat extends Animal {

   // Error! Cannot inherit from final Animal
}
Kompilatorn genererar omedelbart ett fel. I Java är många slutklasser redan implementerade. Bland dem du använder ofta, Stringär den mest kända. Dessutom, om en klass deklareras som final , blir alla klassens metoder också slutgiltiga . Vad betyder det? Om en metod deklareras med den slutliga modifieraren kan du inte åsidosätta den metoden. Här har vi till exempel en Animalklass som deklarerar en speak()metod. Men, hundar och katter "talar" definitivt på olika sätt. Så vi kommer att deklarera speak() metoder i både klasserna Catoch Dog, men vi kommer att implementera dem på olika sätt.
public class Animal {

   public void speak() {
       System.out.println("Hello!");
   }
}

public class Cat extends Animal {

   @Override
   public void speak() {
       System.out.println("Meow!");
   }
}

public class Dog extends Animal {

   @Override
   public void speak() {
       System.out.println("Woof!");
   }
}
Vi fick klasserna Catoch Dogatt åsidosätta metoden som deklarerats i den överordnade klassen. Nu kommer ett djur att tala annorlunda, beroende på vilken typ av föremål det är:
public class Main {

   public static void main(String[] args) {

       Cat cat = new Cat();
       Dog dog = new Dog();

       cat.speak();
       dog.speak();
   }
}
Utgång: Mjau! Väft! Men om vi deklarerar Animalklassens speak()metod som slutgiltig kan vi inte åsidosätta den i andra klasser:
public class Animal {

   public final void speak() {
       System.out.println("Hello!");
   }
}


public class Cat extends Animal {

   @Override
   public void speak() {// Error! A final method can't be overridden!
       System.out.println("Meow!");
   }
}
Och våra objekt kommer att tvingas använda speak()metoden som definieras i den överordnade klassen:
public static void main(String[] args) {

   Cat cat = new Cat();
   Dog dog = new Dog();

   cat.speak();
   dog.speak();
}
Utgång: Hej! Hallå! Nu angående slutvariabler . De är också kända som konstanter . För det första (och viktigast av allt) kan det initiala värdet som tilldelats ett konstant värde inte ändras. Det tilldelas en gång för alla.
public class Main {

   private static final int CONSTANT_EXAMPLE = 333;

   public static void main(String[] args) {

       CONSTANT_EXAMPLE = 999;// Error! You can't assign a new value to a final variable!
   }
}
En konstant behöver inte initieras omedelbart. Det kan göras senare. Men det värde som ursprungligen tilldelades det kommer att förbli detsamma för alltid.
public static void main(String[] args) {

   final int CONSTANT_EXAMPLE;

   CONSTANT_EXAMPLE = 999;// This is allowed
}
För det andra, notera vår variabels namn. Java har en annan namnkonvention för konstanter. Det är inte den vanliga camelCase- notationen. Om det hade varit en vanlig variabel skulle vi ha kallat den konstantExempel. Men namnen på konstanterna skrivs med versaler, med understreck mellan orden (om det finns mer än ett ord), t.ex. "CONSTANT_EXAMPLE". Varför behöver vi konstanter? De är väldigt användbara om det till exempel finns ett fast värde du regelbundet använder i ett program. Du har till exempel bestämt dig för att skriva historia och skriva spelet "The Witcher 4" själv. Spelet kommer uppenbarligen regelbundet att använda huvudpersonens namn: "Geralt of Rivia". Denna sträng (och andra hjältars namn) deklareras bäst som en konstant: dess värde kommer att lagras på ett ställe, och du kommer definitivt inte att göra ett stavfel när du anger den en miljon gånger.
public class TheWitcher4 {

   private static final String GERALT_NAME = "Geralt of Rivia";
   private static final String YENNEFER_NAME = "Yennefer of Wengerberg";
   private static final String TRISS_NAME = "Triss Merigold";

   public static void main(String[] args) {

       System.out.println("The Witcher 4");
       System.out.println("It's already the fourth Witcher game, but " + GERALT_NAME + " still can't decide who" +
               " he likes more: " + YENNEFER_NAME + " or " + TRISS_NAME);

       System.out.println("But, if you've never played The Witcher before, we'll start from the beginning.");
       System.out.println("The protagonist's name is " + GERALT_NAME);
       System.out.println(GERALT_NAME + " is a witcher, a monster hunter");
   }
}
Output: The Witcher 4 Det är redan det fjärde Witcher-spelet, men Geralt från Rivia kan fortfarande inte bestämma sig för vem han gillar mest: Yennefer från Wengerberg eller Triss Merigold Men om du aldrig har spelat The Witcher förut, börjar vi från början. Huvudpersonens namn är Geralt från Rivia Geralt från Rivia är en häxare, en monsterjägare. Vi har förklarat hjältarnas namn som konstanter. Nu kommer vi definitivt inte att göra ett stavfel, och det finns ingen anledning att skriva ut dem för hand varje gång. Ett annat plus: om vi någonsin behöver ändra variabelns värde över hela programmet, kan du göra det på ett ställe, istället för att manuellt ändra det över hela kodbasen. :)

Oföränderliga typer

När du har arbetat med Java har du förmodligen redan vant dig vid tanken att programmerare har nästan fullständig kontroll över tillståndet för alla objekt. Om du vill skapa ett Catobjekt kan du. Om du vill byta namn på den kan du. Om du vill ändra dess ålder eller något annat så kan du. Men Java har flera datatyper som har en speciell egenskap. De är oföränderliga . Om en klass är oföränderlig kan tillståndet för dess objekt inte ändras. Vill du ha några exempel? Det kanske överraskar dig, men den mest välkända oföränderliga klassen är String! Så vi kan verkligen inte ändra en strängs värde? Nåväl, låt oss prova det:
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;// Both reference variables point to the same string.
   System.out.println(str2);

   str1 = "I love Python";// but changing str1 has no impact on str2
   System.out.println(str2);// str2 continues to point to the "I love Java" string, but str1 now points to a different object
}
Output: Jag älskar Java Jag älskar Java Efter att vi skrev
str1 = "I love Python";
strängobjektet "I love Java"ändrades inte eller gick någonstans. Den finns lyckligtvis fortfarande kvar och har exakt samma text som tidigare. Koden
str1 = "I love Python";
skapade helt enkelt ett annat objekt, som str1 nu pekar på. Men vi verkar inte ha någon effekt på strängobjektet "Jag älskar Java". Okej, låt oss prova något annat! Klassen Stringär full av metoder, och några av dem verkar ändra objektets tillstånd! Det finns till exempel en replace()metod. Låt oss ändra ordet "Java" till "Python" i vår sträng!
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;// Both reference variables point to the same string.
   System.out.println(str2);

   str1.replace("Java", "Python");// We try to change the state of str1 by swapping the word "Java" with "Python"
   System.out.println(str2);
}
Utdata: Jag älskar Java Jag älskar Java Det fungerade inte igen! Ersättningsmetoden kanske inte fungerar? Låt oss prova något annat. Till exempel, substring(). Den returnerar en delsträng baserat på teckenindex som skickas som argument. Låt oss klippa av de första 10 tecknen i vår sträng:
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;// Both reference variables point to the same string.
   System.out.println(str2);

   str1.substring(10);// Truncate the original String
   System.out.println(str2);
}
Utdata: Jag älskar Java Jag älskar Java Fasta värden i Java: final, konstanter och oföränderlig - 3 Ingenting har förändrats. Och det borde det inte ha. Som vi sa tidigare är strängar oföränderliga. Så, vad är det med alla metoder i klassen String? När allt kommer omkring kan de trunkera strängar, byta tecken och mer. Vad är poängen om inget händer? De kan faktiskt göra dessa saker! Men de returnerar en ny sträng varje gång. Det är meningslöst att skriva
str1.replace("Java", "Python");
eftersom du inte kan ändra det ursprungliga objektet. Men om du skriver metodens resultat till en ny referensvariabel ser du skillnaden direkt!
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;// Both reference variables point to the same string.
   System.out.println(str2);

   String str1AfterReplacement =  str1.replace("Java", "Python");
   System.out.println(str2);

   System.out.println(str1AfterReplacement);
}
Alla Stringmetoder fungerar på detta sätt. Inget kan göras med "I love Java"föremålet. Du kan bara skapa ett nytt objekt och skriva: "<nytt objekt> = resultatet av att manipulera . "I love Java" object "Vilka andra typer är oföränderliga? Några som du definitivt måste komma ihåg direkt är alla omslagsklasser för de primitiva typerna. Integer, Byte, Character, Short, Boolean, Long, Double, Float: alla dessa klasser skapar immutableobjekt (vi kommer att prata om dem i kommande lektioner). Detta inkluderar klasser som används för att skapa stora siffror, till exempel BigIntegeroch BigDecimal. Vi har nyligen täckt undantag och berört stackspåret . Tja , gissa vad, java.lang.StackTraceElementobjekt är också oföränderliga. Detta är vettigt: om någon kunde ändra vår stacks data, skulle det göra det hela meningslöst. Föreställ dig att någon går igenom stackspårningen och ändrar ett OutOfMemoryError till ett FileNotFoundException . Och sedan använder du den stacken för att hitta orsaken till felet. Men programmet använder inte ens filer. :) Så, de gjorde dessa objekt oföränderliga, för säkerhets skull. Okej, så det är mer eller mindre vettigt för StackTraceElement . Men varför skulle någon behöva göra strängar oföränderliga? Varför skulle det vara ett problem att ändra deras värderingar? Det skulle förmodligen till och med vara bekvämare. :/ Det finns flera anledningar till detta. För det första sparar det minne. Oföränderliga strängar kan placeras i strängpoolen, vilket gör att strängar kan återanvändas istället för att skapa nya. För det andra, för säkerheten. Till exempel är användarnamn och lösenord strängar i nästan alla program. Att göra det möjligt att ändra dem kan resultera i behörighetsproblem. Det finns andra anledningar, men vår studie av Java har inte täckt dem ännu, så vi återkommer till dem senare.
Kommentarer
  • Populär
  • Ny
  • Gammal
Du måste vara inloggad för att lämna en kommentar
Den här sidan har inga kommentarer än