JavaRush /Java Blog /Random-IT /Analisi di domande e risposte da interviste per sviluppat...

Analisi di domande e risposte da interviste per sviluppatori Java. Parte 5

Pubblicato nel gruppo Random-IT
Ciao ciao! Oggi gli sviluppatori Java sono molto richiesti. Naturalmente non posso fornirti un posto vacante, ma cercherò di aiutarti ad acquisire nuove conoscenze e a colmare alcune lacune. Quindi continuiamo ad analizzare oltre 250 domande di intervista per sviluppatori Java. I collegamenti alle parti precedenti dell'analisi si trovano alla fine dell'articolo.Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 5 - 1

39. Cosa sono i modificatori di accesso in Java? Nominali. A cosa servono?

In precedenza ho descritto i modificatori di accesso nella domanda sugli elementi di incapsulamento Java. Ma te lo ricorderò comunque. I modificatori di accesso in Java sono parole chiave che descrivono il livello di accesso concesso a un particolare componente Java. I modificatori di accesso possono essere:
  • public : un elemento con questo modificatore sarà accessibile pubblicamente. Quelli. campi e metodi, le classi dichiarate con il modificatore public sono visibili ad altre classi sia dal pacchetto corrente che da pacchetti esterni;
  • protetto : un elemento con questo modificatore sarà accessibile da qualsiasi punto della classe corrente del pacchetto corrente o delle classi discendenti, anche se si trovano in altri pacchetti;
  • default o modificatore mancante: questo modificatore viene utilizzato implicitamente quando il modificatore di accesso non è specificato affatto. È simile al precedente, tranne per il fatto che la visibilità è consentita nelle classi discendenti presenti in altri pacchetti;
  • private è il più privato di tutti i modificatori, consentendo l'accesso all'elemento solo all'interno della classe corrente.
Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 5 - 2

40. Nomina la caratteristica principale dei metodi statici e variabili

Una formulazione molto strana: "metodi variabili". Sicuramente questo si riferisce a metodi ordinari e non statici. Quindi, la differenza principale è che i metodi statici appartengono alla classe e, infatti, per loro non è necessario creare un'istanza di questa classe: può essere chiamata solo utilizzando il tipo di classe. Ad esempio, abbiamo un metodo statico per accarezzare il gatto:
public class CatService {
   public static void petTheCat(Cat cat) {
       System.out.println("Погладить кота - " + cat.getName());
   }
Non abbiamo bisogno di un'istanza della classe CatService per chiamarla :
Cat cat = new Cat(7, "Bobi");
CatService.petTheCat(cat);
Mentre i metodi ordinari sono legati a (appartengono a) un oggetto e per chiamarli è necessario avere un'istanza (oggetto) su cui verrà chiamato il metodo. Ad esempio, un gatto ha un metodo non statico: miagolare:
class Cat {
   public void mew() {
       System.out.println("Meow! Meow! Meow!");
   }
Per chiamare questo metodo, abbiamo bisogno di un'istanza specifica del gatto:
Cat cat = new Cat(7, "Bobi");
cat.mew();

41. Quali sono le principali restrizioni sui metodi statici e “variabili”?

Come ho detto prima, la limitazione principale di un metodo regolare è che deve sempre esserci un'istanza in cui verrà chiamato questo metodo. Ma un metodo statico non lo richiede, ma non può fare riferimento al riferimento this - agli elementi dell'oggetto corrente - poiché per esso l'oggetto corrente non esiste.

42. Cosa significa la parola chiave statica? È possibile sovrascrivere o sovraccaricare un metodo statico?

Un elemento designato dalla parola chiave static non appartiene ad un oggetto della classe, bensì alla classe, e viene caricato quando viene caricata la classe stessa. Gli elementi statici sono gli unici per l'intero programma e gli elementi regolari sono gli unici per un oggetto specifico. Lo statico può essere:
  • campi di classe;
  • blocco di inizializzazione della classe;
  • metodo di classe;
  • classi interne di una classe (questa però è pur sempre una tautologia).
Un metodo statico non può essere sovrascritto: appartiene alla classe e non è ereditato, ma allo stesso tempo può essere sovraccaricato.

43. Può un metodo essere statico e astratto allo stesso tempo?

Ne ho già parlato nell’articolo precedente: un metodo non può essere astratto e statico allo stesso tempo. L'astrattezza di un metodo significa che deve essere sovrascritto nel successore. Allo stesso tempo, un metodo statico appartiene alla classe e non può essere sovrascritto: ciò causerebbe una contraddizione, che il compilatore vedrà e inizierà a imprecare. Se ti trovi in ​​​​una situazione del genere, dovresti pensare seriamente alla correttezza dell'architettura della tua applicazione (dopo tutto, c'è chiaramente qualcosa che non va).Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 5 - 3

44. È possibile utilizzare metodi statici in mezzo a quelli normali? Viceversa? Perché?

I metodi statici possono essere utilizzati in quelli normali, poiché nulla lo impedisce. Allo stesso tempo, la situazione inversa è impossibile: un metodo statico non può utilizzare un metodo regolare senza avere un riferimento a un'istanza specifica di questa classe. E come ricordiamo, il riferimento this non è disponibile per i membri della classe statica: possono esserci tutti gli oggetti specifici della classe che desideri, e ognuno di essi avrà un riferimento a se stesso al suo interno - this . E come capire allora quale particolare questo collegamento bisogna prendere? Ma assolutamente no. Pertanto, gli elementi statici non possono riferirsi a elementi non statici, senza un riferimento ad un oggetto specifico. In realtà, un metodo statico può utilizzare un metodo non statico solo se ha un riferimento a un oggetto specifico. Ad esempio, quello che è arrivato come argomento:
public static void petTheCat(Cat cat) {
   System.out.println("Погладить кота - " + cat.getName());
}
Qui vediamo che il metodo statico petTheCat chiama il normale metodo non statico dell'oggetto Cat - getName .

45. Cos'è l'interfaccia? Può esserci un'interfaccia finale?

Come ricordiamo, in Java non esiste l'ereditarietà multipla. Le interfacce sono una sorta di alternativa ad esso. L'interfaccia sembra una classe molto essenziale. Definiscono funzionalità senza un'implementazione specifica, che viene implementata dalle classi che implementano (implementano) queste interfacce. Esempio di interfaccia:
public interface Animal {
    void voice();
}
Un esempio di implementazione dell'interfaccia da parte di una classe:
class Cat implements Animal {

   @Override
   public void voice() {
       System.out.println("Meow! Meow! Meow!");
   }
}
La cosa principale che devi sapere sull'utilizzo delle interfacce è:
  1. I metodi di interfaccia dovrebbero contenere solo un'intestazione, senza un corpo del metodo specifico, ad es. deve essere astratto (ma senza utilizzare la parola chiave abstract ). L'eccezione a ciò sono i metodi statici e predefiniti, che richiedono un corpo del metodo.
  2. Una classe può implementare molte interfacce (come ho detto, questa è un'alternativa all'ereditarietà multipla), che vengono scritte separate da virgole: la classe Lion implementa Animal, Wild .
  3. Le interfacce vengono create utilizzando la parola chiave -interface .
  4. Quando si implementa un'interfaccia tramite una classe, la parola chiave è implements .
  5. Una classe che implementa una particolare interfaccia deve implementare tutti i suoi metodi astratti oppure deve dichiararsi astratta.
  6. Lo scopo principale dell'utilizzo delle interfacce è implementare il polimorfismo (la capacità degli oggetti di assumere molte forme).
  7. Di norma, i modificatori di accesso per i metodi non sono scritti nell'interfaccia: sono public per impostazione predefinita e non è possibile specificare altri modificatori diversi da public . A partire da Java 9, puoi utilizzare modificatori privati ​​per i metodi.
  8. Le variabili dell'interfaccia sono di default statiche final , ovvero costanti: devono sempre essere inizializzate direttamente nell'interfaccia.
  9. Non è possibile creare un oggetto interfaccia.
La risposta alla domanda se le interfacce possano essere definitive ovviamente non lo è. Dopotutto, l'essenza stessa delle interfacce deve essere implementata. E come tutti ricordiamo molto bene, final a livello di classe lo rende non ereditabile e, nel caso di un'interfaccia, non implementabile. Perché abbiamo bisogno di un'interfaccia che non può essere implementata e utilizzata? Esatto: non ce n'è bisogno! E il compilatore la pensa così)) Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 5 - 4Il significato è apparso solo con l'introduzione di metodi statici nelle interfacce con Java 8, ma ciò non ha cambiato il fatto che l'interfaccia non può essere definitiva. Ho parlato di interfacce, in modo molto superficiale, perché... questo è un argomento ampio. Maggiori informazioni a questo proposito negli articoli sulle interfacce in Java e sulla differenza tra classi astratte e interfacce .

46. ​​​​Dove posso inizializzare i campi statici?

I campi statici possono essere inizializzati:
  • direttamente al momento della dichiarazione, attraverso il segno uguale = ;
  • nel blocco di inizializzazione statica;
  • in un blocco di inizializzazione non statico, ma è necessario comprendere che ogni volta che viene creato un oggetto, questo campo verrà sovrascritto da questo blocco di inizializzazione;
  • nel costruttore della classe. Ogni volta che viene chiamato questo costruttore (ovvero, quando viene creato un oggetto tramite questo costruttore), questo campo verrà sovrascritto;
  • nei metodi statici;
  • in metodi non statici;
  • in classi interne statiche e non statiche, locali e anonime.

47. Cosa sono le classi anonime?

Le classi anonime sono classi che non hanno un proprio tipo. Di cosa sto parlando? Quando abbiamo parlato di interfacce, ho detto che non puoi creare un oggetto interfaccia: puoi solo creare un oggetto di una classe che implementa l'interfaccia. Cosa succede se non vuoi implementare un'interfaccia in una classe, ma hai comunque bisogno di un oggetto del tipo interfaccia? E molto probabilmente, questo sarà un singolo caso di utilizzo di questo oggetto. E non è necessario creare una classe di implementazione completa. Come lo farai? Giusto! Attraverso una lezione anonima! Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 5 - 5Diciamo che abbiamo un'interfaccia Animal :
public final interface Animal {
   public void voice();
}
Se vogliamo istanziare questa interfaccia tramite una classe anonima:
Animal cat = new Animal() {
   @Override
   public void voice() {
       System.out.println("Meow! Meow! Meow!");
   }
};
E poi puoi tranquillamente utilizzare questo oggetto e il suo metodo implementato - voice . Cioè, una classe anonima implementa questa interfaccia e tutti i suoi metodi astratti proprio qui e ora. Altrimenti non saremo in grado di creare un oggetto interfaccia/classe astratta, poiché esistono metodi non implementati/astratti. Come ho già detto, le classi anonime vengono utilizzate non solo per implementare metodi astratti di un'interfaccia, ma anche per implementare metodi astratti di una classe astratta. Questo approccio è utile per le situazioni in cui un oggetto viene utilizzato una sola volta o una determinata implementazione di metodi è necessaria solo una volta e non è necessario creare una classe separata che implementerà la classe/interfaccia astratta richiesta. Ma noterò anche che l'uso di classi anonime è un evento raro nel lavoro: di norma, la preferenza viene ancora data alle classi ordinarie. Puoi leggere ulteriori informazioni sulle classi anonime in questo articolo .

48. Cosa sono le classi primitive?

Per quanto mi riguarda, questa è una domanda molto strana e, forse, è una domanda trappola, perché in Java non esistono classi primitive: tranne forse il concetto di tipi primitivi, che abbiamo già considerato in precedenza. Come ricordiamo, ci sono 8 tipi primitivi in ​​Java: byte , short , int , long , float , double , char , boolean .Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 5 - 6

49. Cos'è la classe “wrapper”?

Il problema principale con l'utilizzo dei tipi primitivi in ​​Java è che non sono ancora classi e Java è ancora un linguaggio OOP. Cioè, i programmi scritti in questo linguaggio si riducono all'interazione tra oggetti. Ebbene, i primitivi non sono oggetti. Non hanno metodi, nemmeno quelli standard della classe Object . Bene, cosa succederebbe se avessimo bisogno di usare una primitiva come chiave in Map ? Quindi devi chiamare il metodo hashCode . Puoi anche chiamare il metodo equals lì . Cosa poi? Possono esserci moltissimi momenti in cui dovrebbe esserci una classe, e non una primitiva, che rende le primitive elementi inutilizzati e indesiderabili nel programma, perché questo distrugge l'idea stessa di OOP. Ma non tutto è così brutto come sembra. Dopotutto, Java ha il concetto di wrapper primitivo. Ogni tipo primitivo ha una classe analoga:
  • byte -> Byte.class
  • breve -> Classe.breve
  • int -> Classe.intera
  • lungo -> Classe.lunga
  • float -> Float.class
  • doppio -> Doppio.class
  • char -> Classe.carattere
  • booleano -> Booleano.class
Questa è una rappresentazione di tipi semplici, ma sotto forma di classi a tutti gli effetti con una serie di metodi diversi e funzionali. Per un comodo utilizzo di queste classi, sono stati introdotti i concetti di autoboxing e unboxing. Autoboxing : conversione automatica di un tipo primitivo in una classe analogica, se necessario (ad esempio, da int a Integer ). L'unboxing è il processo inverso del precedente: convertire automaticamente una classe wrapper primitiva in un tipo primitivo (ad esempio, da Integer a int ). Grazie all'introduzione delle classi wrapper primitive e dei processi di autoboxing e unboxing , i tipi primitivi sono riusciti a diventare membri a pieno titolo del linguaggio OOP: Java. Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 5 - 7Per approfondire questo argomento ti consiglio vivamente la lettura di questo articolo .

50. Cos'è la classe annidata? Quando viene utilizzato?

La classe nidificata è una classe interna che è membro di un'altra classe. In Java esistono 4 tipi di classi interne: 1. Classe interna Questo tipo di classe viene dichiarato direttamente nel corpo di un'altra classe. Una classe interna annidata può accedere a qualsiasi campo o metodo privato di un'istanza della classe esterna. Ad esempio, creiamo uno zoo in cui avremo un animale: una zebra:
public class Zoo {
   class Zebra {
       public void toFeed(String food) {
           System.out.println("Дать зебре - " + food);
       }
   }
}
Niente di complicato, vero? Diamo un'occhiata a un esempio di creazione di un oggetto di classe interna:
Zoo.Zebra zebra = new Zoo().new Zebra();
zebra.toFeed("яблоко");
Come hai già visto, è imperativo creare un oggetto della classe framing, in base al riferimento del quale è possibile creare un oggetto della classe interna. Vorrei anche notare che una classe interna annidata non può avere metodi statici o campi statici. Ciò accade perché una classe interna è implicitamente associata all'oggetto della sua classe esterna e non può dichiarare alcun metodo statico al suo interno. 2. Classi nidificate statiche Questa classe è simile alla precedente, solo che ha un modificatore di accesso statico vicino alla dichiarazione della classe. Poiché questo tipo di classe non ha accesso ai campi non statici della classe esterna, è più simile alla parte statica della classe esterna che a una classe interna. In questo caso, i dati della classe hanno accesso a tutti i membri statici della classe esterna, anche a quelli privati. Esempio di una classe nidificata statica:
public class Zoo {
   static class Zebra {
       public void toFeed(String food) {
           System.out.println("Дать зебре - " + food);
       }
   }
}
Il metodo di creazione è leggermente diverso dal precedente:
Zoo.Zebra zebra = new Zoo.Zebra();
zebra.toFeed("яблоко");
Qui non abbiamo bisogno di un oggetto di una classe esterna per creare un oggetto di una classe statica annidata. Della classe esterna abbiamo bisogno solo del suo tipo in modo da poter trovare la posizione della classe nidificata. 3. Classi locali Le classi locali sono classi dichiarate all'interno del corpo di un metodo, e la creazione e l'utilizzo di un oggetto di una classe locale è possibile solo all'interno di questo metodo. Esempio:
public class Zoo {
   public void toFeed(String animal, String food) {
       switch(animal){
           case "зебра":
               class Zebra {
                   void toFeedZebra(String food) {
                       System.out.println("Дать зебре - " + food);
                   }
               }
               Zebra zebra = new Zebra();
               zebra.toFeedZebra(food);
               ...
Esempio di utilizzo:
Zoo zoo = new Zoo();
zoo.toFeed("зебра", "яблоко");
Senza vedere il codice del metodo toFeed , non sospetteresti nemmeno l'esistenza di una classe locale, vero? Una classe locale non può essere statica o transitoria , ma può essere contrassegnata come astratta o finale (solo OR, poiché l'utilizzo di questi due modificatori causerà un conflitto). 4. Classi anonime Abbiamo già parlato delle classi anonime sopra e, come ricorderete, possono essere create da due fonti: interfacce e classi. Vengono utilizzate le ragioni per utilizzare le classi interne statiche e non statiche perché a volte è meglio incorporare classi piccole all'interno di classi più grandi e tenerle insieme: in questo modo avranno maggiore coesione e uno scopo comune. In realtà, l'uso di classi nidificate aumenta l'incapsulamento del codice. Il motivo per scegliere le classi locali potrebbe essere che una determinata classe viene utilizzata esclusivamente all'interno di un singolo metodo. In questo caso è necessario diffondere il codice in tutta l'applicazione? NO. Ma allo stesso tempo aggiungerò che nella mia pratica non ho mai visto l'uso delle classi locali, perché la loro necessità è molto controversa. Bene, il motivo per utilizzare classi anonime potrebbe essere che un'implementazione specifica di un'interfaccia o di una classe astratta sarà necessaria solo una volta, quindi non è necessario creare una classe separata e completa con un'implementazione per questo. Invece, in modo semplice, abbiamo implementato i metodi di cui avevamo bisogno tramite una classe anonima, abbiamo utilizzato questo oggetto e ce ne siamo dimenticati (beh, il Garbage Collector se ne è ricordato). Questo e questoAnalisi di domande e risposte da interviste per sviluppatori Java.  Parte 5 - 8 articolo ti aiuteranno a studiare le lezioni interne in modo più dettagliato .

51. Quali modificatori di accesso può avere una classe?

Come ricordiamo, esistono diversi tipi di classi e ad esse sono applicabili diversi modificatori di accesso:
  • una classe esterna può avere il modificatore di accesso pubblico o essere priva di modificatore (modificatore predefinito);
  • la classe interna supporta tutti e 4 i modificatori di accesso;
  • La classe statica annidata supporta tutti i modificatori di accesso tranne protected , perché questo modificatore implica ereditarietà, che contraddice il membro statico della classe (gli elementi statici non vengono ereditati);
  • una classe locale può avere solo un modificatore predefinito (ovvero nessun modificatore);
  • classe anonima : se non è presente alcuna dichiarazione del tipo di classe, non ci sono affatto modificatori di accesso.
È qui che ci fermeremo oggi. Arrivederci!Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 5 - 9
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION