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 8

Pubblicato nel gruppo Random-IT
Pratica o teoria? Cosa è più importante? Molti diranno che, ovviamente, la pratica è più importante. Ad esempio, esercitati più duramente che puoi e sarai felice. Oserei non essere d'accordo con questo. Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 8 - 1Durante le interviste, nessuno saprà quanto sei bravo nella pratica. Ti verrà chiesto per intero esattamente secondo la teoria. E solo allora, quando avrai superato tutte le fasi dei colloqui e sarai entrato nel progetto, utilizzerai le tue capacità pratiche. Potresti obiettare: a volte ti danno un compito di prova e la pratica è ancora necessaria. Non discuto, a volte vengono dati, ma il nocciolo della questione è che A VOLTE, ma un colloquio teorico avviene SEMPRE. Senti la differenza? Pertanto, è necessario avere una solida base teorica sotto i piedi, che continueremo a rafforzare oggi. Continueremo cioè ad analizzare le domande che spesso vengono poste durante le interviste.

71. Cosa succede se non sovrascriviamo il metodo toString() per Enum?

Diciamo che abbiamo la seguente enumerazione :
public enum Role {
   STUDENT,
   TEACHER,
   DIRECTOR,
   SECURITY_GUARD;
}
Visualizziamo lo studente nella console chiamando toString() su di lui :
System.out.println(Role.STUDENT.toString());
Risultato nella console:
ALUNNO
Cioè, per impostazione predefinita, toString() per enum è il nome della costante stessa.

72. È possibile specificare un costruttore all'interno di un Enum?

Si certo. È attraverso il costruttore che vengono impostati i valori delle variabili enum interne. Ad esempio, aggiungiamo due campi all'enumerazione precedente - ageFrom e ageTo - per indicare la fascia di età per ciascun ruolo:
public enum Role {
   STUDENT(5,18),
   TEACHER(20,60),
   DIRECTOR(40,70),
   SECURITY_GUARD(18,50);

   int ageFrom;
   int ageTo;

   Role(int ageFrom, int ageTo) {
       this.ageFrom = ageFrom;
       this.ageTo = ageTo;
   }
}

73. Qual è la differenza tra == e equals()?

Questa è una delle domande più comuni nelle interviste agli sviluppatori Java. Partiamo dal fatto che quando confrontiamo valori semplici ( int , char , double ...), lo facciamo utilizzando == , poiché le variabili contengono valori specifici e possiamo confrontarli. E le variabili primitive non sono oggetti a tutti gli effetti: non ereditano da Object e non hanno un metodo equals() . Quando parliamo di confrontare variabili che si riferiscono a oggetti, == confronterà solo il valore dei riferimenti, indipendentemente dal fatto che si riferiscano o meno allo stesso oggetto. E anche se un oggetto è identico a un altro, il confronto tramite == darà un risultato negativo ( false ), perché si tratta di un oggetto diverso. Come hai capito, il metodo equals() viene utilizzato per confrontare le variabili di riferimento . Questo è uno dei metodi standard della classe Object , necessario per un confronto completo degli oggetti. Ma è bene fare subito chiarezza: affinché questo metodo funzioni correttamente, è necessario ridefinirlo scrivendo esattamente come devono essere confrontati gli oggetti di questa classe. A meno che non si sovrascriva il metodo, per impostazione predefinita confronterà gli oggetti per == . In IntelliJ IDEA , puoi sovrascriverlo automaticamente (usando gli strumenti IDEA) -> alt + insert , nella finestra che appare, seleziona equals() e hashCode() -> seleziona quali campi di classe dovrebbero partecipare -> e voilà, implementazione automatica di i metodi sono completati. Ecco un esempio di come apparirebbe un metodo equals generato automaticamente per una semplice classe Cat con due campi: int age e String name :
@Override
public boolean equals(final Object o) {
   if (this == o) return true;
   if (o == null || this.getClass() != o.getClass()) return false;
   final Cat cat = (Cat) o;
   return this.age == cat.age &&
           Objects.equals(this.name, cat.name);
}
Se parliamo della differenza tra == e equals per enums , non ce n’è molta. Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 8 - 2Dopotutto, enum memorizza costanti e, anche confrontando valori simili utilizzando == , riceveremo true , poiché i riferimenti saranno sempre agli stessi oggetti. Ebbene, quando si utilizza equals, lavoreremo anche correttamente sulla funzionalità, soprattutto se entri nel corpo del metodo equals per un enum , vedrai che nella classe Enum l'implementazione del metodo è la seguente: Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 8 - 3Cioè, all'interno - il buon vecchio paragone per riferimento! Per riassumere: per enum , il confronto sia con == che con equals è corretto.Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 8 - 4

74. Cosa fa il metodo ordinal() in Enum?

Quando chiamiamo il metodo int ordinal() su un elemento enum , otterremo il numero ordinale da zero di questo valore nella serie generale di enumerazioni. Usiamo questo metodo su un elemento dell'enumerazione precedente discussa : Ruolo :
System.out.println(Role.DIRECTOR.ordinal());
Di conseguenza, la console visualizzerà:
2

75. È possibile utilizzare Enum con TreeSet o TreeMap in Java?

L'uso dei tipi enum in TreeSet e TreeMap è accettabile. E possiamo scrivere:
TreeSet<Role> treeSet = new TreeSet<>();
treeSet.add(Role.SECURITY_GUARD);
treeSet.add(Role.DIRECTOR);
treeSet.add(Role.TEACHER);
treeSet.add(Role.STUDENT);
treeSet.forEach(System.out::println);
E la console mostrerà:
DIRETTORE STUDENTE INSEGNANTE SECURITY_GUARD
Abbiamo ricevuto l'output non in ordine alfabetico. Il punto è che se utilizziamo elementi enum per i valori TreeSet o come chiavi per TreeMap , gli elementi vengono ordinati nel loro ordine naturale (l'ordine in cui sono specificati in enum ). Comprendere queste funzionalità ci aiuta a scrivere codice migliore.Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 8 - 5

76. Come sono correlati i metodi ordinal() e compareTo() in Enum?

Come affermato in precedenza, ordinal() restituisce il numero ordinale di un valore in un elenco di enumerazione generale. Inoltre, nell'analisi della domanda precedente, hai visto che gli elementi delle enumerazioni, una volta, ad esempio, in un TreeSet (insieme ordinato) prendono l'ordine in cui sono dichiarati in enum . E come sappiamo, TreeSet e TreeMap ordinano gli elementi chiamando il loro metodo compareTo() dell'interfaccia Comparable . Da ciò possiamo supporre che la classe Enum implementi l' interfaccia Comparable , implementandola nel metodo compareTo() , all'interno del quale ordinal() viene utilizzato per impostare l'ordinamento. Entrando nella classe Enum , ne vediamo la conferma: Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 8 - 6E il corpo del metodo stesso: Il Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 8 - 7metodo ordinal() non viene chiamato qui. Viene invece utilizzata la variabile ordinale , ovvero il numero ordinale dell'elemento nell'enumerazione. Il metodo ordinal() stesso non è Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 8 - 8altro che un getter per la variabile ordinale .

77. Scrivi un esempio EnumM

Nelle domande discusse sopra, ho già fornito esempi di enumerazioni e non vedo il motivo di duplicare il codice (ad esempio, la domanda numero 72 sul costruttore in enum).

78. È possibile utilizzare Enum in un caso di switch?

È possibile e necessario! Ripensando alla mia pratica, noto che uno dei luoghi più comuni in cui utilizzare enum sono i costrutti logici come switch . In questo caso, puoi fornire tutte le possibili variazioni di case e, dopo aver scritto la logica per tutti i valori enum , l'utilizzo dell'operatore predefinito potrebbe non essere nemmeno necessario! Dopotutto, se utilizzi una String o un valore numerico, ad esempio, di tipo int , potresti ricevere un valore imprevisto, cosa che a sua volta è impossibile utilizzando un enum . Come sarebbe un interruttore per l'esempio discusso in precedenza:
public void doSomething(Role role) {
   switch (role) {
       case STUDENT:
           // некая логика для STUDENT
           break;
       case TEACHER:
           // некая логика для TEACHER
           break;
       case DIRECTOR:
           // некая логика для DIRECTOR
           break;
       case SECURITY_GUARD:
           // некая логика для SECURITY_GUARD
           break;
   }
}

79. Come ottenere tutti i valori disponibili in un'istanza Enum?

Se è necessario ottenere tutte le istanze di un'enumerazione, esiste un metodo value() che restituisce un array di tutti i valori disponibili di una particolare enumerazione in ordine naturale (nell'ordine in cui sono stati specificati in enum ). Esempio:
Role[] roles = Role.values();
for (Role role : roles) {
   System.out.println(role);
}
La console visualizzerà il seguente output:
DIRETTORE STUDENTE INSEGNANTE SECURITY_GUARD

API di flusso

80.Che cos'è lo streaming in Java?

Java Stream è un modo relativamente nuovo di interagire con un flusso di dati, che a sua volta consente di elaborare dati di grandi dimensioni in modo più conveniente e compatto, nonché di parallelizzare l'elaborazione dei dati tra un certo numero di thread, il che può aumentare le prestazioni nell'utilizzo funzionalità. Questo argomento non può essere discusso più approfonditamente in poche parole, quindi lascerò qui un collegamento a un articolo che può aiutarti ad approfondire questo argomento.Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 8 - 9

81. Quali sono le principali proprietà delle transazioni?

L'argomento si chiama Stream API, ma la domanda riguarda la transazione. Hmm... Per prima cosa, cerchiamo di capire cos'è una transazione. Una transazione è un gruppo di operazioni sequenziali del database che rappresenta un'unità logica di utilizzo dei dati. Una transazione può essere completata interamente e con successo, mantenendo l'integrità dei dati e indipendentemente da altre transazioni eseguite in parallelo, oppure non può essere completata affatto, nel qual caso non ha alcun effetto. Pertanto, le transazioni hanno quattro proprietà principali, chiamate in breve ACID . Vediamo come ogni lettera di questa abbreviazione sta per: A - Atomicità - atomicità - questa proprietà garantisce che nessuna transazione verrà parzialmente registrata nel sistema. Verranno eseguite tutte le sue operazioni secondarie oppure nessuna ( tutto o niente ). C - Coerenza - la coerenza è una proprietà che garantisce che ogni transazione andata a buon fine registri solo risultati validi. Cioè, questa è una garanzia che, in caso di transazione riuscita, tutte le regole e le restrizioni imposte dal sistema su dati specifici verranno rispettate, altrimenti la transazione non verrà completata e i dati nel sistema torneranno al loro stato precedente stato. I - Isolamento - l'isolamento è una proprietà che dice che durante l'esecuzione di una transazione, le transazioni parallele non dovrebbero influenzarne il risultato. Questa proprietà richiede molte risorse, quindi viene generalmente implementata in parte consentendo determinati livelli di isolamento che risolvono determinati problemi di isolamento. Ne discuteremo più in dettaglio nella prossima domanda. Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 8 - 10D - Durabilità - questa proprietà garantisce che se l'utente ha ricevuto conferma dal sistema che la transazione è stata completata, può essere sicuro che le modifiche apportate non verranno annullate a causa di qualche errore. Cioè, puoi essere sicuro che qualche tipo di guasto del sistema operativo non farà nulla ai tuoi dati se hai già ricevuto la conferma del completamento con successo della transazione.

82. Quali sono i livelli di isolamento delle transazioni?

Come ho detto prima, fornire l'isolamento ACID è un processo che richiede molte risorse. Pertanto tale proprietà è parzialmente soddisfatta. Esistono diversi livelli di isolamento e quanto più alto è il livello, tanto maggiore è l’impatto sulla produttività. Prima di passare ai livelli di isolamento delle transazioni, dobbiamo esaminare i vari problemi di isolamento insufficiente delle transazioni :
  • lettura fantasma - quando lo stesso campione (la stessa query) viene richiamato ripetutamente all'interno della stessa transazione, i dati ricevuti differiscono, il che si verifica a causa dell'inserimento di dati da parte di un'altra transazione;

  • lettura non ripetuta : quando lo stesso campione (la stessa query) viene richiamato ripetutamente all'interno della stessa transazione, i dati ricevuti differiscono, il che si verifica a causa di modifiche (aggiornamento) ed eliminazioni di dati da parte di un'altra transazione;

  • lettura sporca - il processo di lettura dei dati aggiunti o modificati da una transazione che successivamente non è stata confermata (ripristinata), ad es. lettura di dati non validi;

  • aggiornamento perso : quando diverse transazioni modificano gli stessi dati contemporaneamente, tutte le modifiche tranne l'ultima vengono perse (che ricorda il problema della "race condition" in un ambiente multi-thread).

I livelli di isolamento delle transazioni sono caratterizzati dai problemi di isolamento da cui proteggono. Consideriamo sotto forma di tabella i livelli di isolamento e da quali problemi proteggono:
Livello di isolamento Lettura fantasma Lettura non ripetitiva Lettura sporca Aggiornamento perso
SERIALIZZABILE + + + +
LETTURA RIPETIBILE - + + +
LEGGI IMPEGNO - - + +
LEGGI SENZA IMPEGNO - - - +
NESSUNO - - - -
E non dimenticare l’altro lato della medaglia: maggiore è il livello di isolamento, maggiore sarà il tempo necessario per l’elaborazione delle transazioni (se più transazioni vengono eseguite in parallelo). Se vuoi approfondire questo argomento, ecco un ottimo articolo per iniziare.

83. Qual è la differenza tra Statement e PreparedStatement?

E qui non c'è una transizione molto fluida verso le funzionalità della tecnologia JDBC . Quindi, per prima cosa, scopriamo cos'è effettivamente Statement . Questo è un oggetto utilizzato per generare query SQL. JDBC utilizza tre tipi : Statement , PreparedStatement e CallableStatement . Oggi non parleremo di CallableStatement : parliamo della differenza tra Statement e PreparedStatement .
  1. L'istruzione viene utilizzata per eseguire semplici query SQL senza parametri in entrata inseriti dinamicamente. PrepareStatement viene utilizzato con la possibilità di inserire dinamicamente parametri di input.

  2. Per impostare i parametri in PreparedStatement, i parametri di input nella richiesta vengono scritti come punti interrogativi, per poi inserire qualche valore al loro posto utilizzando vari setter, come setDouble() , setFloat() , setInt() , setTime() .. .. Di conseguenza, non inserirai il tipo sbagliato di dati nella tua query.

  3. PreparedStatement è "precompilato" e utilizza la memorizzazione nella cache, quindi la sua esecuzione può essere leggermente più veloce rispetto all'esecuzione di query da oggetti Statement . Di conseguenza, le query SQL eseguite frequentemente vengono scritte come oggetti PreparedStatement per migliorare le prestazioni .

  4. Statement è vulnerabile alle SQL injection, mentre PreparedStatement le previene. Scopri di più sull'eliminazione delle SQL injection e altre best practice nella sicurezza Java in questo articolo .

Se stai iniziando a studiare la tecnologia per connettere un'applicazione Java ad un Database - JDBC, ti consiglio di iniziare con questo articolo . Bene, a questo punto ci fermiamo oggi.Analisi di domande e risposte da interviste per sviluppatori Java.  Parte 8 - 11
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION