CodeGym /Java Blog /Random-IT /Le 50 principali domande e risposte sui colloqui di lavor...
John Squirrels
Livello 41
San Francisco

Le 50 principali domande e risposte sui colloqui di lavoro per Java Core. Parte 1

Pubblicato nel gruppo Random-IT
Ciao a tutti, signore e signori, ingegneri del software! Parliamo delle domande dell'intervista. Su cosa devi prepararti e cosa devi sapere. Questo è un ottimo momento per rivedere o studiare questi punti per la prima volta. Le 50 principali domande e risposte sui colloqui di lavoro per Java Core.  Parte 1 - 1 Ho finito con una raccolta piuttosto ampia di domande frequenti su OOP, sintassi Java, eccezioni Java, raccolte e multithreading, che dividerò in più parti per comodità. È difficile coprire tutto in una volta, ma spero che questo materiale fornisca una buona base per coloro che si preparano a trovare il loro primo lavoro come programmatore. Per la migliore comprensione e conservazione, consiglio di esaminare anche altre fonti. Puoi ottenere una comprensione più profonda di un concetto affrontandolo da diverse angolazioni. Importante:Parleremo solo di Java prima della versione 8. Tutte le innovazioni introdotte nelle versioni 9, 10, 11, 12 e 13 non saranno prese in considerazione qui. Qualsiasi idea/commento su come migliorare le risposte è benvenuta . Buona lettura. Andiamo!

Intervista Java: domande su OOP

1. Quali sono le caratteristiche di Java?

Risposta:
  1. Concetti OOP:

    1. orientamento agli oggetti
    2. eredità
    3. incapsulamento
    4. polimorfismo
    5. astrazione
  2. Multipiattaforma: un programma Java può essere eseguito su qualsiasi piattaforma senza alcuna modifica. Naturalmente, ciò richiede una JVM (Java virtual machine) installata.

  3. Prestazioni elevate: il compilatore Just-In-Time (JIT) rende possibili prestazioni elevate. Il compilatore JIT converte il bytecode in codice macchina e quindi la JVM avvia l'esecuzione.

  4. Multithreading: la JVM crea un thread di esecuzione chiamato main thread. Un programmatore può creare più thread derivando dalla classe Thread o implementando l' Runnableinterfaccia.

2. Cos'è l'eredità?

Ereditarietà significa che una classe può ereditare un'altra classe (usando la parola chiave extends ). Ciò significa che puoi riutilizzare il codice dalla classe che erediti. La classe esistente è nota come superclasse la classe appena creata è subclass. La gente dice anche di usare i termini genitore e child.

public class Animal {
   private int age;
}

public class Dog extends Animal {

}
dov'è Animalil parented Dogè il child.

3. Cos'è l'incapsulamento?

Questa domanda viene spesso posta nelle interviste per posizioni di sviluppatore Java. L'incapsulamento nasconde l'implementazione utilizzando modificatori di accesso, getter e setter. Questo viene fatto per impedire l'accesso esterno ovunque gli sviluppatori lo ritengano necessario. Un semplice esempio dalla vita reale è l'auto. Non abbiamo accesso diretto al funzionamento del motore. Tutto quello che dobbiamo fare è inserire la chiave nell'accensione e accendere il motore. I processi che si svolgono sotto il cofano non sono affari nostri. Inoltre, se dovessimo interferire con l'attività del motore, potrebbe verificarsi una situazione imprevedibile, che potrebbe danneggiare l'auto e provocare danni fisici. Esattamente la stessa cosa accade nella programmazione. Questo è descritto bene su Wikipedia. C'è anche un articolo sull'incapsulamento su CodeGym .

4. Cos'è il polimorfismo?

Il polimorfismo è la capacità di un programma di trattare oggetti con la stessa interfaccia nello stesso modo, senza informazioni sul tipo specifico dell'oggetto. Come dice il proverbio, "un'interfaccia - molte implementazioni". Con il polimorfismo, puoi combinare e utilizzare diversi tipi di oggetti in base a comportamenti condivisi. Ad esempio, abbiamo una classe Animal che ha due discendenti: Dog e Cat. La generica classe Animal ha un comportamento condiviso da tutti, la capacità di emettere un suono. Usiamo le capacità polimorfiche quando dobbiamo raccogliere tutto ciò che eredita la classe Animal ed eseguire il metodo "make sound". Ecco come appare:

List<Animal> animals = Arrays.asList(new Cat(), new Dog(), new Cat());
animals.forEach(animal -> animal.makeSound());
In altre parole, il polimorfismo è utile. E questo vale anche per i metodi polimorfici (sovraccarico). Come usare il polimorfismo

Interviste domande sulla sintassi Java

5. Cos'è un costruttore in Java?

I costruttori hanno le seguenti caratteristiche:
  1. Quando viene creato un nuovo oggetto, il programma utilizza il costruttore appropriato per crearlo.
  2. Un costruttore è come un metodo. Le sue caratteristiche distintive risiedono nel fatto che non vi è alcun valore di ritorno (incluso void) e che il suo nome è lo stesso del nome della classe.
  3. Se non viene creato alcun costruttore in modo esplicito, viene creato automaticamente un costruttore vuoto.
  4. Un costruttore può essere sovrascritto.
  5. Se dichiari un costruttore con parametri ma ne necessiti anche uno senza parametri, devi crearlo separatamente, poiché non verrà creato automaticamente.

6. Quali due classi non ereditano Object?

Non lasciarti ingannare dalle domande trabocchetto: non esistono classi del genere. Tutte le classi ereditano la classe Object direttamente o tramite predecessori!

7. Cos'è una variabile locale?

Questa è un'altra popolare domanda di intervista per gli sviluppatori Java. Una variabile locale è una variabile definita all'interno di un metodo ed esiste finché il metodo viene eseguito. Non appena termina l'esecuzione, la variabile locale cessa di esistere. Ecco un programma che utilizza una variabile locale denominata helloMessage nel metodo main():

public static void main(String[] args) {
   String helloMessage;
   helloMessage = "Hello, World!";
   System.out.println(helloMessage);
}

8. Cos'è una variabile di istanza?

Una variabile di istanza è una variabile dichiarata all'interno di una classe. Esiste finché esiste un oggetto. Ad esempio, abbiamo una classe Bee, che ha due variabili di istanza: nectarLoad e maxNectarLoad:

public class Bee {

   /**
    * Current nectar load
    */
   private double nectarLoad;

   /**
    * Maximum nectar that can the bee can collect.
    */
   private double maxNectarLoad = 20.0;
 
  ...
}

9. Cosa sono i modificatori di accesso?

I modificatori di accesso sono un meccanismo per personalizzare l'accesso a classi, metodi e variabili. Esistono i seguenti modificatori, elencati in ordine crescente di accesso:
  1. private— Questo modificatore di accesso viene utilizzato su metodi, campi e costruttori. L'accesso è limitato alla classe in cui sono dichiarati.
  2. package-private (default)— Questo è il livello di accesso predefinito per le classi. L'accesso è limitato al pacchetto specifico in cui è dichiarata una classe, un metodo, una variabile o un costruttore.
  3. protected— Questo modificatore di accesso offre lo stesso livello di accesso dell'aggiunta package-privatedell'accesso per le classi che ereditano una classe con il protectedmodificatore.
  4. public— Questo livello di accesso viene utilizzato anche per le classi. Questo livello di accesso significa che c'è pieno accesso in tutta l'applicazione.
Le 50 principali domande e risposte sui colloqui di lavoro per Java Core.  Parte 1 - 2

10. Cos'è l'override del metodo?

Sovrascriviamo i metodi quando una classe figlia vuole cambiare il comportamento della sua classe genitore. Se abbiamo anche bisogno di fare ciò che è nel metodo genitore, possiamo usare super.methodName() nel figlio, che eseguirà il metodo genitore. Possiamo aggiungere la nostra logica aggiuntiva dopo. Requisiti che devono essere osservati:
  • la firma del metodo deve essere la stessa
  • il valore restituito deve essere lo stesso

11. Cosa sono le firme dei metodi?

Le 50 principali domande e risposte sui colloqui di lavoro per Java Core.  Parte 1 - 3Una firma del metodo è la combinazione del nome del metodo e degli argomenti accettati dal metodo. La firma del metodo è l'identificatore univoco di un metodo durante l'overload dei metodi.

12. Che cos'è l'overload del metodo?

Il sovraccarico del metodo è una caratteristica del polimorfismo in cui cambiamo la firma del metodo per creare più metodi che eseguono la stessa azione:
  • lo stesso nome
  • argomentazioni diverse
  • ci possono essere diversi tipi di ritorno
Ad esempio, il metodo ArrayListdella classe add()può essere sovraccaricato, permettendoci di aggiungere in modi diversi a seconda degli argomenti di input:
  • add(Object o)— Questo metodo aggiunge semplicemente un oggetto
  • add(int index, Object o)— Questo metodo aggiunge un oggetto a un indice specifico
  • add(Collection<Object> c)— Questo metodo aggiunge un elenco di oggetti
  • add(int index, Collection<Object> c)— Questo metodo aggiunge un elenco di oggetti a partire da un indice specifico.

13. Cos'è un'interfaccia?

Java non supporta l'ereditarietà multipla. Per superare questa limitazione, sono state aggiunte interfacce nella forma che conosciamo e amiamo ;) Per molto tempo, le interfacce hanno avuto solo metodi senza alcuna implementazione. Nel contesto di questa risposta, parliamone. Per esempio:


public interface Animal {
   void makeSound();
   void eat();
   void sleep();
}
Alcuni dettagli seguono da questo:
  • Tutti i metodi in un'interfaccia sono pubblici e astratti
  • Tutte le variabili sono public static final
  • Le classi non ereditano le interfacce (cioè non usiamo la parola chiave extends). Invece, le classi li implementano (cioè usiamo la parola chiave implements). Inoltre, puoi implementare tutte le interfacce che desideri.
  • Le classi che implementano un'interfaccia devono fornire un'implementazione di tutti i metodi presenti nell'interfaccia.
Come questo:

public class Cat implements Animal {
   public void makeSound() {
       // Method implementation
   }

   public void eat() {
       // Implementation
   }

   public void sleep() {
       // Implementation
   }
}

14. Qual è un metodo predefinito in un'interfaccia?

Parliamo ora dei metodi predefiniti. A cosa servono? Per chi sono? Questi metodi sono stati aggiunti per servire "entrambe le mani". Di cosa sto parlando? Bene, da un lato, c'era la necessità di aggiungere nuove funzionalità: lambda e l'API Stream. D'altra parte, era necessario mantenere ciò per cui Java è famoso: la retrocompatibilità. Per fare ciò, le interfacce necessitavano di alcune nuove soluzioni già pronte. È così che ci sono arrivati ​​i metodi predefiniti. Un metodo predefinito è un metodo implementato in un'interfaccia, contrassegnato dalla defaultparola chiave. Ad esempio, il noto stream()metodo nell'interfaccia Collection. Credimi, questa interfaccia non è così semplice come sembra. O anche l'altrettanto famoso forEach()metodo inIterableinterfaccia. Inoltre non esisteva fino a quando non sono stati aggiunti i metodi predefiniti. A proposito, puoi anche leggerlo su CodeGym qui .

15. Come ereditiamo quindi due metodi predefiniti identici?

La risposta precedente su cosa sia un metodo predefinito pone un'altra domanda. Se puoi implementare metodi nelle interfacce, in teoria puoi implementare due interfacce con lo stesso metodo. Come lo facciamo? Ecco due diverse interfacce con lo stesso metodo:

interface A {
   default void foo() {
       System.out.println("Foo A");
   }
}

interface B {
   default void foo() {
       System.out.println("Foo B");
   }
}
E abbiamo una classe che implementa queste due interfacce. Ma come scegliamo un metodo specifico nell'interfaccia A o B? Il seguente costrutto speciale lo consente A.super.foo():

public class C implements A, B {
   public void fooA() {
       A.super.foo();
   }

   public void fooB() {
       B.super.foo();
   }
}
Pertanto, il fooA()metodo utilizzerà il foo()metodo predefinito dell'interfaccia A, mentre il fooB()metodo utilizzerà il foo()metodo dell'interfaccia B.

16. Cosa sono i metodi e le classi astratti?

In Java, abstractè una parola riservata. È usato per denotare classi e metodi astratti. Innanzitutto, abbiamo bisogno di definizioni. Un metodo astratto è un metodo dichiarato utilizzando la abstractparola chiave senza un'implementazione in una classe astratta. Cioè, questo è un metodo come in un'interfaccia, ma con l'aggiunta di una parola chiave, ad esempio:

public abstract void foo();
Una classe astratta è una classe contrassegnata anche dalla abstractparola chiave:

public abstract class A {

}
Una classe astratta ha diverse caratteristiche:
  • non puoi creare un oggetto di una classe astratta
  • può avere metodi astratti
  • potrebbe anche non avere metodi astratti
Le classi astratte sono necessarie per l'astrazione (scusate la tautologia) che ha un insieme di comportamenti e stati comuni (ovvero metodi e variabili). La vita reale è piena di esempi. Tutto intorno a noi. "Animale", "Macchina", "Figura geometrica" ​​e così via.

17. Qual è la differenza tra String, StringBuilder e StringBuffer?

Stringi valori vengono archiviati in un pool di stringhe costanti. Non appena viene creata una stringa, viene visualizzata in questo pool. E non puoi cancellarlo. Per esempio:

String name = "book";
La variabile punterà al pool di stringhe costanti Le 50 principali domande e risposte sui colloqui di lavoro per Java Core.  Parte 1 - 4Impostando la variabile name su un valore diverso, abbiamo:

name = "pen";
Il pool di stringhe costanti ha questo aspetto: Le 50 principali domande e risposte sui colloqui di lavoro per Java Core.  Parte 1 - 5In altre parole, entrambi i valori rimangono lì. Buffer di stringhe:
  • Stringi valori sono memorizzati in uno stack. Se un valore viene modificato, il nuovo valore sostituirà quello vecchio.
  • String Bufferè sincronizzato ed è quindi thread-safe.
  • A causa della sicurezza del thread, le sue prestazioni sono scarse.
Esempio:

StringBuffer name = “book”;
Le 50 principali domande e risposte sui colloqui di lavoro per Java Core.  Parte 1 - 6Non appena il valore della variabile name cambia, il valore nello stack cambia: Le 50 principali domande e risposte sui colloqui di lavoro per Java Core.  Parte 1 - 7StringBuilder è esattamente uguale a StringBuffer, solo che non è thread-safe. Di conseguenza, è notevolmente più veloce di StringBuffer.

18. Qual è la differenza tra una classe astratta e un'interfaccia?

Classe astratta:
  • Le classi astratte hanno un costruttore predefinito. Viene chiamato ogni volta che viene creato un discendente della classe astratta.
  • Possono includere sia metodi astratti che metodi non astratti. In generale, una classe astratta non deve avere metodi astratti.
  • Una classe che ne eredita una astratta deve implementare solo metodi astratti.
  • Una classe astratta può avere variabili di istanza (vedi domanda n. 5).
Interfaccia:
  • Un'interfaccia non ha un costruttore e non può essere inizializzata.
  • È possibile aggiungere solo metodi astratti (ad eccezione dei metodi predefiniti).
  • Le classi che implementano l'interfaccia devono implementare tutti i metodi (ad eccezione dei metodi predefiniti).
  • Le interfacce possono avere solo costanti.

19. Perché l'accesso a un elemento in un array è O(1)?

Questa domanda è stata letteralmente posta nella mia ultima intervista. Come ho appreso in seguito, lo scopo di questa domanda è vedere come pensa una persona. Chiaramente, c'è poco valore pratico in questa conoscenza. Basta saperlo. Innanzitutto, dobbiamo chiarire che O(1) è la notazione per la complessità temporale di un algoritmo a "tempo costante". In altre parole, questa designazione indica il tempo di esecuzione più veloce. Per rispondere a questa domanda, dobbiamo considerare ciò che sappiamo sugli array. Per creare un intarray, dobbiamo scrivere quanto segue:

int[] intArray = new int[100];
Da questa sintassi si possono trarre diverse conclusioni:
  1. Quando viene dichiarato un array, il suo tipo è noto. Se il tipo è noto, è nota anche la dimensione di ogni cella dell'array.
  2. La dimensione dell'intero array è nota.
Ne consegue quindi che per capire su quale cella scrivere, basta calcolare su quale area di memoria scrivere. Per un computer, questo è facile. Il computer sa dove inizia la memoria allocata, il numero di elementi e la dimensione di ogni cella. Tutto ciò significa che il punto in cui scrivere sarà uguale al punto iniziale dell'array + la dimensione di ogni cella moltiplicata per l'indice.

Quindi, come arriviamo a O(1) quando accediamo agli oggetti in un ArrayList?

Questa domanda segue immediatamente la precedente. La verità è che quando si lavora con un array che contiene primitive, conosciamo in anticipo (al momento della creazione) la dimensione del tipo di elemento. Ma cosa facciamo se abbiamo questo tipo di gerarchia di ereditarietà e Le 50 principali domande e risposte sui colloqui di lavoro per Java Core.  Parte 1 - 8vogliamo creare una raccolta per elementi di tipo A e aggiungere diverse implementazioni (B, C e D):

List<A> list = new ArrayList();
list.add(new B());
list.add(new C());
list.add(new D());
list.add(new B());
In questa situazione, come calcoliamo la dimensione di ogni cella? Dopotutto, ogni oggetto sarà diverso, possibilmente con diversi campi aggiuntivi. Cosa fare? Qui la domanda è posta in un modo che ha lo scopo di confonderti. Sappiamo che la collezione non memorizza direttamente gli oggetti. Memorizza solo i riferimenti agli oggetti. E tutti i riferimenti hanno la stessa dimensione, ed è noto. Di conseguenza, calcoliamo gli indirizzi qui nello stesso modo della domanda precedente.

21. Autoboxing e unboxing

Cenni storici: l'autoboxing e l'unboxing sono alcune delle principali innovazioni di JDK 5. L'autoboxing è il processo di conversione automatica da un tipo primitivo a una corrispondente classe wrapper. L'unboxing è l'esatto opposto dell'autoboxing. È il processo di conversione di una classe wrapper in una primitiva. Ma se il valore di un wrapper è null, verrà NullPointerExceptionlanciato a durante l'unboxing.

Primitive e relativi involucri

Primitivo Classe wrapper
booleano Booleano
int Numero intero
byte Byte
char Carattere
galleggiante Galleggiante
lungo Lungo
corto Corto
Doppio Doppio

// Si verifica l'autoboxing:

  • quando si assegna una primitiva a un riferimento a una classe wrapper:

    PRIMA di Java 5:

    
    // Manual boxing (the way it was BEFORE Java 5).
    public void boxingBeforeJava5() {
       Boolean booleanBox = new Boolean(true);
       Integer intBox = new Integer(3);
       // And so on for other types
    }
    
    After Java 5:
    // Automatic boxing (the way it became in Java 5).
    public void boxingJava5() {
       Boolean booleanBox = true;
       Integer intBox = 3;
       // And so on for other types
    }
    
  • quando una primitiva viene passata come argomento a un metodo che si aspetta un wrapper:

    
    public void exampleOfAutoboxing() {
       long age = 3;
       setAge(age);
    }
    
    public void setAge(Long age) {
       this.age = age;
    }
    

// L'unboxing avviene:

  • quando assegniamo un'istanza di una classe wrapper a una variabile primitiva:

    
    // BEFORE Java 5:
    int intValue = new Integer(4).intValue();
    double doubleValue = new Double(2.3).doubleValue();
    char c = new Character((char) 3).charValue();
    boolean b = Boolean.TRUE.booleanValue();
    
    // And after JDK 5:
    int intValue = new Integer(4);
    double doubleValue = new Double(2.3);
    char c = new Character((char) 3);
    boolean b = Boolean.TRUE;
    
  • Durante le operazioni aritmetiche. Le operazioni si applicano solo ai tipi primitivi, quindi è necessario unboxing per i primitivi.

    
    // BEFORE Java 5:
    Integer integerBox1 = new Integer(1);
    Integer integerBox2 = new Integer(2);
    
    // A comparison used to require this:
    integerBox1.intValue() > integerBox2.intValue()
          
    // In Java 5
    integerBox1 > integerBox2
    
  • quando si passa un'istanza di una classe wrapper a un metodo che accetta la primitiva corrispondente:

    
    public void exampleOfAutoboxing() {
       Long age = new Long(3);
       setAge(age);
    }
    
    public void setAge(long age) {
       this.age = age;
    }
    

22. Qual è la parola chiave final e dove viene utilizzata?

La finalparola chiave può essere utilizzata su variabili, metodi e classi.
  1. Il valore di una variabile final non può essere modificato dopo che è stato inizializzato.
  2. Una classe finale è sterile :) Non può avere figli.
  3. Un metodo final non può essere sovrascritto da un discendente.
Abbiamo coperto le cose di alto livello. Ora approfondiamo.

Variabili finali

Java ci offre due modi per dichiarare una variabile e assegnarle un valore:
  1. Puoi dichiarare una variabile e inizializzarla successivamente.
  2. Puoi dichiarare una variabile e assegnare subito un valore.
Ecco un esempio che dimostra questi usi delle variabili finali:

public class FinalExample {

   // A static final variable that is immediately initialized:
   final static String FINAL_EXAMPLE_NAME = "I'm likely the final one";

   // A final variable that is not initialized, but will only work if you
   // initialize it in the constructor:
   final long creationTime;

   public FinalExample() {
       this.creationTime = System.currentTimeMillis();
   }

   public static void main(String[] args) {
       FinalExample finalExample = new FinalExample();
       System.out.println(finalExample.creationTime);

       // The final FinalExample.FINAL_EXAMPLE_NAME field cannot be accessed
//    FinalExample.FINAL_EXAMPLE_NAME = "Not you're not!";

       // The final Config.creationTime field cannot be accessed
//    finalExample.creationTime = 1L;
   }
}

Una variabile finale può essere considerata una costante?

Poiché non possiamo assegnare nuovi valori alle variabili finali, sembra che queste siano variabili costanti. Ma solo a prima vista: se il tipo di dati della variabile è immutable, allora sì, è una costante. Ma se il tipo di dati è mutable, cioè modificabile, sarà possibile utilizzare metodi e variabili per modificare il valore dell'oggetto referenziato da una finalvariabile. Per questo motivo, non può essere definito una costante. L'esempio seguente mostra che alcune variabili finali sono veramente costanti, mentre altre non lo sono, poiché possono essere modificate.

public class FinalExample {

   // Immutable final variables
   final static String FINAL_EXAMPLE_NAME = "I'm likely the final one";
   final static Integer FINAL_EXAMPLE_COUNT  = 10;

   // Mutable final variables
   final List<String> addresses = new ArrayList();
   final StringBuilder finalStringBuilder = new StringBuilder("Constant?");
}

Variabili finali locali

Quando una finalvariabile viene creata all'interno di un metodo, viene chiamata variabile local final:

public class FinalExample {

   public static void main(String[] args) {
       // You can do this
       final int minAgeForDriveCar = 18;

       // Or you can do this, in a for-each loop:
       for (final String arg : args) {
           System.out.println(arg);
       }
   }

}
Possiamo usare la parola chiave final in un ciclo for potenziato, perché una nuova variabile viene creata dopo ogni iterazione del ciclo. Tieni presente che questo non si applica a un normale ciclo for, quindi otterremo un errore in fase di compilazione.

// The final local j variable cannot be assigned
for (final int i = 0; i < args.length; i ++) {
   System.out.println(args[i]);
}

Classe finale

Una classe dichiarata come finalnon può essere estesa. In parole povere, nessun'altra classe può ereditarlo. Un eccellente esempio di finalclasse nel JDK è String. Il primo passo per creare una classe immutabile è contrassegnarla come final, impedendo così che venga estesa:

public final class FinalExample {
}

// Compilation error!
class WantsToInheritFinalClass extends FinalExample {
}

Metodi finali

Quando un metodo è contrassegnato come final, viene chiamato metodo final (ha senso, giusto?). Un metodo final non può essere sovrascritto in una classe figlia. Per inciso, i metodi wait() e notify() della classe Object sono definitivi, quindi non abbiamo la possibilità di sovrascriverli.

public class FinalExample {
   public final String generateAddress() {
       return "Some address";
   }
}

class ChildOfFinalExample extends FinalExample {

   // Compilation error!
   @Override
   public String generateAddress() {
       return "My OWN Address";
   }
}

Come e dove usare final in Java

  • Utilizzare la parola chiave final per definire alcune costanti a livello di classe;
  • Crea variabili finali per gli oggetti che non desideri vengano modificati. Ad esempio, proprietà specifiche dell'oggetto che possiamo utilizzare per scopi di registrazione.
  • Se non vuoi che una classe venga estesa, contrassegnala come finale.
  • Se devi creare una classe immutabile, devi renderla definitiva.
  • Se vuoi che l'implementazione di un metodo non cambi nei suoi discendenti, contrassegna il metodo come final. Questo è molto importante per essere sicuri che l'implementazione non cambi.

23. Cosa sono i tipi mutabili e immutabili?

Mutevole

Gli oggetti mutabili sono oggetti il ​​cui stato e le cui variabili possono essere modificati dopo la creazione. Esempi di classi mutabili includono StringBuilder e StringBuffer. Esempio:

public class MutableExample {

   private String address;

   public MutableExample(String address) {
       this.address = address;
   }

   public String getAddress() {
       return address;
   }

   // This setter can change the name field
   public void setAddress(String address) {
       this.address = address;
   }

   public static void main(String[] args) {

       MutableExample obj = new MutableExample("First address");
       System.out.println(obj.getAddress());

       // We are updating the name field, so this is a mutable object
       obj.setAddress("Updated address");
       System.out.println(obj.getAddress());
   }
}

Immutabile

Gli oggetti immutabili sono oggetti il ​​cui stato e le cui variabili non possono essere modificati dopo la creazione dell'oggetto. Un'ottima chiave per una HashMap, non credi? :) Ad esempio, String, Integer, Double e così via. Esempio:

// We'll make this class final so no one can change it
public final class ImmutableExample {

   private String address;

   ImmutableExample(String address) {
       this.address = address;
   }

   public String getAddress() {
       return address;
   }

   // We remove the setter

   public static void main(String[] args) {

       ImmutableExample obj = new ImmutableExample("Old address");
       System.out.println(obj.getAddress());

       // There is no way to change this field, so it is an immutable object
       // obj.setName("new address");
       // System.out.println(obj.getName());

   }
}
Nella parte successiva, consideriamo domande e risposte sulle collezioni. Il mio profilo su GitHub Top 50 domande e risposte sui colloqui di lavoro per Java Core. Parte 2
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION