JavaRush /Java Blog /Random-IT /Finale, Costanti e Immutabile in Java

Finale, Costanti e Immutabile in Java

Pubblicato nel gruppo Random-IT
Ciao! La parola “modificatore” ti è già familiare. Come minimo, ti sei imbattuto nei modificatori di accesso (pubblico, privato) e nel modificatore statico. Oggi parleremo dello speciale modificatore finale . Si può dire che “cementa” quelle aree del nostro programma in cui abbiamo bisogno di un comportamento costante, inequivocabile e immutabile. Può essere utilizzato in tre aree del nostro programma: classi, metodi e variabili. Immutabile in Java: finale, costanti e Immutabile - 2 Esaminiamoli uno per uno. Se una dichiarazione di classe contiene il modificatore finale , significa che non puoi ereditare da questa classe. Nelle lezioni precedenti abbiamo visto un semplice esempio di ereditarietà: avevamo una classe genitore Animale due classi figlie - CateDog
public class Animal {
}

public class Cat extends Animal {
   //..поля и методы класса Cat
}

public class Dog extends Animal {

   //..поля и методы класса Dog
}
Tuttavia, se specifichiamo Animalun modificatore per una classe, neanche finalle classi potranno ereditare da essa . CatDog
public final class Animal {

}

public class Cat extends Animal {

   //ошибка! Cannot inherit from final Animal
}
Il compilatore produce immediatamente un errore. Esistono molte classi già implementate in Java final. Il più famoso di quelli che usi costantemente è String. Inoltre, se una classe viene dichiarata come final, anche tutti i suoi metodi diventano final. Cosa significa? Se viene specificato un modificatore per un metodo final, questo metodo non può essere sovrascritto. Ad esempio, abbiamo una classe Animalche definisce un metodo voice(). Tuttavia, cani e gatti chiaramente “parlano” in modo diverso. Pertanto, in ciascuna delle classi - Cate Dog- creeremo un metodo voice(), ma lo implementeremo in modo diverso.
public class Animal {

   public void voice() {
       System.out.println("Voice!");
   }
}

public class Cat extends Animal {

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

public class Dog extends Animal {

   @Override
   public void voice() {
       System.out.println("Woof!");
   }
}
Nelle classi Cate Dogabbiamo sovrascritto il metodo della classe genitore. Ora l'animale vocalizzerà a seconda dell'oggetto della classe:
public class Main {

   public static void main(String[] args) {

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

       cat.voice();
       dog.voice();
   }
}
Conclusione: Miao! Trama! Tuttavia, se Animaldichiariamo un metodo in una classe voice()come final, non sarà possibile ridefinirlo in altre classi:
public class Animal {

   public final void voice() {
       System.out.println("Voice!");
   }
}


public class Cat extends Animal {

   @Override
   public void voice() {//ошибка! final-метод не может быть переопределен!
       System.out.println("Meow!");
   }
}
Quindi i nostri oggetti saranno costretti a utilizzare il metodo voice()così come è definito nella classe genitore:
public static void main(String[] args) {

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

   cat.voice();
   dog.voice();
}
Conclusione: voce! Voce! Ora parliamo finaldelle -variabili. Altrimenti si chiamano costanti . Innanzitutto (e soprattutto), il primo valore assegnato a una costante non può essere modificato. Viene assegnato una volta e per sempre.
public class Main {

   private static final int CONSTANT_EXAMPLE = 333;

   public static void main(String[] args) {

       CONSTANT_EXAMPLE = 999;//ошибка! Нельзя присвоить новое meaning final-переменной!
   }
}
Non è necessario inizializzare immediatamente la costante. Questo può essere fatto più tardi. Ma il valore assegnato per primo resterà per sempre.
public static void main(String[] args) {

   final int CONSTANT_EXAMPLE;

   CONSTANT_EXAMPLE = 999;//так делать можно
}
In secondo luogo, presta attenzione al nome della nostra variabile. Le costanti Java hanno una convenzione di denominazione diversa. Questo non è il CamelCase a cui siamo abituati. Nel caso di una variabile regolare, la chiameremmo costanteEsempio, ma i nomi delle costanti sono scritti in maiuscolo e tra le parole (se ce ne sono molte) c'è un carattere di sottolineatura - "CONSTANT_EXAMPLE". Perché sono necessarie le costanti? Ad esempio, torneranno utili se utilizzi costantemente un valore costante in un programma. Diciamo che hai deciso di passare alla storia e scrivere il gioco "The Witcher 4" da solo. Ovviamente il gioco utilizzerà costantemente il nome del personaggio principale: "Geralt di Rivia". È meglio separare questa riga e i nomi degli altri eroi in una costante: il valore di cui hai bisogno verrà archiviato in un unico posto e sicuramente non commetterai errori quando lo digiterai per la milionesima volta.
public class TheWitcher4 {

   private static final String GERALT_NAME = "Геральт из Ривии";
   private static final String YENNEFER_NAME = "Йеннифэр из Венгерберга";
   private static final String TRISS_NAME = "Трисс Меригольд";

   public static void main(String[] args) {

       System.out.println("Ведьмак 4");
       System.out.println("Это уже четвертая часть Ведьмака, а " + GERALT_NAME + " ниHow не определится кто ему" +
               " нравится больше: " + YENNEFER_NAME + " or " + TRISS_NAME);

       System.out.println("Но если вы никогда не играли в Ведьмака - начнем сначала.");
       System.out.println("Главного героя зовут " + GERALT_NAME);
       System.out.println(GERALT_NAME + " - ведьмак, охотник на чудовищ");
   }
}
Conclusione:
Ведьмак 4
Это уже четвертая часть Ведьмака, а Геральт из Ривии ниHow не определится, кто ему нравится больше: Йеннифэр из Венгерберга or Трисс Меригольд.
Но если вы никогда не играли в Ведьмака — начнем сначала.
Главного героя зовут Геральт из Ривии
Геральт из Ривии — ведьмак, охотник на чудовищ
Abbiamo separato i nomi dei personaggi in costanti, e ora sicuramente non li scriveremo in modo errato, e non ci sarà bisogno di scriverli a mano ogni volta. Un altro vantaggio: se alla fine abbiamo bisogno di modificare il valore di una variabile in tutto il programma, è sufficiente farlo in un unico posto, invece di rifarlo manualmente in tutto il codice :)

Tipi immutabili

Mentre lavori in Java, probabilmente sei già abituato al fatto che il programmatore controlla quasi completamente lo stato di tutti gli oggetti. Wanted: creato un oggetto Cat. Se volevo, lo ribattezzavo. Se voleva, cambiava età, o qualcos'altro. Ma in Java esistono diversi tipi di dati che hanno uno stato speciale. Sono immutabili o immutabili . Ciò significa che se una classe è immutabile, lo stato dei suoi oggetti non può essere modificato. Esempi? Potresti rimanere sorpreso, ma l'esempio più famoso della classe Immutable è String! Sembrerebbe, non possiamo cambiare il valore di una stringa? Proviamo:
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;//обе переменные-ссылки указывают на одну строку.
   System.out.println(str2);

   str1 = "I love Python";//но поведение str1 ниHow не влияет на str2
   System.out.println(str2);//str2 продолжает указывать на строку "I love Java", хотя str1 уже указывает на другой an object
}
Conclusione: amo Java, amo Java Dopo che abbiamo scritto:
str1 = "I love Python";
l'oggetto con la stringa "I love Java" non è cambiato e non è andato da nessuna parte. Esiste in modo sicuro e contiene esattamente lo stesso testo di prima. Codice:
str1 = "I love Python";
ho appena creato un altro oggetto e ora la variabile str1punta ad esso. Ma non possiamo influenzare in alcun modo l' oggetto “I love Java” . Ok, proviamolo diversamente! La classe Stringè piena di metodi e alcuni di essi sembrano cambiare lo stato della riga! Ad esempio, esiste un metodo replace(). Cambiamo la parola "Java" con la parola "Python" nella nostra riga!
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;//обе переменные-ссылки указывают на одну строку.
   System.out.println(str2);

   str1.replace("Java", "Python");//попробуем изменить состояние str1, заменив слово "Java" на “Python”
   System.out.println(str2);
}
Conclusione: adoro Java, adoro Java Non ha funzionato di nuovo! Forse il metodo della curva non funziona? Proviamone un altro. Per esempio, substring(). Taglia una stringa in base ai numeri dei caratteri trasmessi. Riduciamo il nostro ai primi 10 caratteri:
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;//обе переменные-ссылки указывают на одну строку.
   System.out.println(str2);

   str1.substring(10);//обрезаем исходную строку
   System.out.println(str2);
}
Conclusione: amo Java, amo Java Immutabile in Java: finale, costanti e Immutabile - 3 Non è cambiato nulla. E non avrebbe dovuto. Come abbiamo detto, gli oggetti Stringsono immutabili. Cosa sono allora tutti questi metodi di classe String? Possono tagliare la linea, cambiare i caratteri al suo interno, ecc. Perché allora sono necessari se non succede nulla? Loro possono! Ma restituiscono ogni volta un nuovo oggetto stringa. E' inutile scrivere:
str1.replace("Java", "Python");
- non modificherai l'oggetto originale. Ma se scrivi il risultato del metodo in una nuova variabile di riferimento, vedrai immediatamente la differenza!
public static void main(String[] args) {

   String str1 = "I love Java";

   String str2 = str1;//обе переменные-ссылки указывают на одну строку.
   System.out.println(str2);

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

   System.out.println(str1AfterReplacement);
}
Questo è l'unico modo in cui funzionano tutti questi metodi String. Non puoi fare nulla con l' oggetto "I love Java" . Basta creare un nuovo oggetto e scrivere: “Nuovo oggetto = il risultato di alcune manipolazioni con l' oggetto “I love Java” .” Quali altri tipi sono immutabili? Da quello che devi assolutamente ricordare ora: tutte le classi wrapper sui tipi primitivi sono immutabili. Integer, Byte, Character, Short, Boolean, Long, Double, Float- tutte queste classi creano oggetti immutabili . Ciò include anche le classi utilizzate per creare numeri di grandi dimensioni - BigIntegere BigDecimal. Recentemente abbiamo esaminato le eccezioni e abbiamo toccato il tema StackTrace. Quindi: anche gli oggetti della classe java.lang.StackTraceElement sono immutabili. Questo è logico: se qualcuno potesse modificare i dati nel nostro stack, ciò potrebbe annullare tutto il lavoro con esso. Immagina che qualcuno entri in StackTrace e modifichi OutOfMemoryError in FileNotFoundException . E dovresti lavorare con questo stack e cercare la causa dell'errore. E il programma non utilizza affatto i file :) Pertanto, per sicurezza, questi oggetti sono stati resi immutabili. Bene, con StackTraceElement è più o meno chiaro. Perché qualcuno dovrebbe voler rendere le stringhe immutabili? Quale sarebbe il problema se fosse possibile modificare i loro valori? Probabilmente sarebbe ancora più conveniente :/ Ci sono diverse ragioni per questo. Innanzitutto, risparmiare memoria. È possibile inserire stringhe immutabili String Poole utilizzare ogni volta le stesse invece di crearne di nuove. In secondo luogo, la sicurezza. Ad esempio, la maggior parte degli accessi e delle password in qualsiasi programma sono stringhe. La possibilità di modificarli potrebbe comportare problemi con l'autorizzazione. Ci sono altri motivi, ma non li abbiamo ancora affrontati imparando Java: torneremo più tardi.
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION