
71. Cosa succede se non sovrascriviamo il metodo toString() di Enum?
Supponiamo di avere la seguente enumerazione :public enum Role {
STUDENT,
TEACHER,
DIRECTOR,
SECURITY_GUARD;
}
Visualizziamo il campo STUDENT sulla console chiamando il suo metodo toString() :
System.out.println(Role.STUDENT.toString());
Di conseguenza, otteniamo il seguente output della console:
72. Puoi dichiarare un costruttore all'interno di un Enum?
Sì, naturalmente. Il costruttore è ciò che imposta i valori dei campi interni di enum . 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 poste nei colloqui agli aspiranti sviluppatori Java. Per cominciare, quando confrontiamo valori semplici ( int , char , double ...), usiamo == , poiché queste variabili contengono valori concreti che possono essere confrontati direttamente. Inoltre, le variabili primitive non sono oggetti a tutti gli effetti: non ereditano la classe Object e non hanno un metodo equals() . Se parliamo di confrontare variabili che si riferiscono a oggetti, allora dobbiamo sapere che == confronta solo il valore dei riferimenti, cioè se si riferiscono o meno allo stesso oggetto. Anche se tutti i dati in un oggetto sono identici a tutti i dati in un altro, utilizzando == per un confronto si otterrà un risultato negativo ( false ), poiché si tratta di oggetti separati. Come avrai intuito, utilizziamo il metodo equals() per confrontare le variabili di riferimento. Questo è uno dei metodi standard della classe Object ed è necessario per un confronto completo degli oggetti. Ma devo dire subito che affinché questo metodo funzioni correttamente è necessario sovrascriverlo per indicare esattamente come devono essere confrontati gli oggetti. Se non esegui l'override del metodo, otterrai l'implementazione predefinita, che confronta gli oggetti utilizzando == . In IntelliJ IDEA, puoi sovrascriverlo automaticamente utilizzando una scorciatoia IDEA: Alt+Insert . Nella finestra che appare, seleziona equals() e hashCode() . Quindi seleziona i campi che dovrebbero essere coinvolti. Ecco! I metodi vengono implementati automaticamente. Ecco un esempio di come un metodo equals generato automaticamente cerca la classe Cat più semplice possibile 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);
}
Quando si tratta di enum , non c'è una differenza pratica tra == e equals() . 


74. Cosa fa il metodo ordinal() di Enum?
Quando chiamiamo il metodo int ordinal() su un campo enum , otteniamo l'indice in base zero del campo nell'elenco dei valori enum. Chiamiamo questo metodo su un campo dell'enumerazione Role , che abbiamo considerato in precedenza:System.out.println(Role.DIRECTOR.ordinal());
Di conseguenza, la console visualizza:
75. Enum può essere utilizzato con TreeSet o TreeMap in Java?
Possiamo utilizzare i tipi enum in TreeSet e TreeMap . E possiamo scrivere questo: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à:
76. Come sono correlati i metodi ordinal() e compareTo() di Enum?
Come accennato in precedenza, ordinal() restituisce l'indice di un campo nell'elenco dei campi enum. Inoltre, nella nostra considerazione della domanda precedente, hai visto che quando i campi enum vengono inseriti in un TreeSet (che è un insieme ordinato), assumono l'ordine in cui sono dichiarati in enum . E come sappiamo, TreeSet e TreeMap ordinano gli elementi chiamando il metodo compareTo() della loro interfaccia Comparable . Questo ci dice che la classe Enum implementa l' interfaccia Comparable , il che significa che implementa il metodo compareTo() , che utilizza internamente il metodo ordinal() per determinare l'ordinamento. Entrando nella classe Enum , possiamo confermare la nostra ipotesi:


77. Scrivi un esempio Enum
Nelle domande discusse sopra, ho già fornito esempi di enum s. Non vedo alcun motivo per duplicare il codice qui. Ad esempio, vedere la domanda 72 riguardante un costruttore in un'enumerazione.78. È possibile utilizzare un Enum in un caso di switch?
Può e dovrebbe essere! Osservando la mia esperienza, noterò che uno degli usi più comuni di enum è nei costrutti logici come le istruzioni switch . In questo caso, puoi fornire tutti i casi possibili : una volta scritta la logica per ciascun campo enum , non avrai nemmeno bisogno di una clausola predefinita ! Dopotutto, se usi String o un valore numerico, come un int , potresti ricevere un valore inaspettato, ma ciò è impossibile con un enum . Ecco come apparirebbe un'istruzione switch per l'esempio precedente:public void doSomething(Role role) {
switch (role) {
case STUDENT:
// some logic for STUDENT
break;
case TEACHER:
// some logic for TEACHER
break;
case DIRECTOR:
// some logic for DIRECTOR
break;
case SECURITY_GUARD:
// some logic for SECURITY_GUARD
break;
}
}
79. Come posso ottenere tutti i possibili valori di un Enum?
Se è necessario ottenere tutti i possibili valori enum, esiste un metodo value() , che restituisce un array di tutti i possibili valori per l' enum nel loro ordine naturale (ovvero nell'ordine in cui sono specificati in enum ). Esempio:Role[] roles = Role.values();
for (Role role : roles) {
System.out.println(role);
}
Avremo quanto segue sulla console:
API di flusso
80. Cos'è uno stream in Java?
L' API Java Stream è un modo relativamente nuovo di interagire con un flusso di dati, consentendoci di elaborare i big data in modo più pratico e compatto, nonché di elaborare i dati in parallelo tra un certo numero di flussi, aumentando potenzialmente le prestazioni.81. Nomina le principali proprietà delle transazioni
L'argomento qui è l'API Stream, ma la domanda riguarda le transazioni. Hmm... Innanzitutto, capiamo cos'è una transazione. Una transazione è un gruppo di operazioni sequenziali su un database. Rappresenta un'unità logica di lavoro. Una transazione può essere eseguita indipendentemente da altre transazioni simultanee o completamente e con successo, mantenendo così l'integrità dei dati, oppure non eseguita affatto, nel qual caso non ha alcun effetto. Le transazioni hanno quattro proprietà principali, che possiamo facilmente ricordare grazie all'acronimo ACID . Vediamo cosa significa ciascuna lettera di questo acronimo: A sta per Atomicity . Questa proprietà garantisce che nessuna transazione venga parzialmente impegnata nel sistema. Verranno eseguite tutte le sue sottooperazioni oppure nessuna di esse ( all or Nothing ). С sta per Coerenza . Questa proprietà garantisce che ogni transazione riuscita commetterà solo risultati validi. In altre parole, questa è una garanzia che, se la transazione ha esito positivo, tutte le regole del sistema per dati specifici verranno rispettate. Se la transazione non va a buon fine, non verrà eseguita e i dati del sistema torneranno allo stato precedente. I sta per Isolamento . Questa proprietà fa sì che quando una transazione viene eseguita, le transazioni concorrenti non devono influenzarne l'esito. Questa proprietà richiede molte risorse, quindi, di norma, è parzialmente implementata, consentendo determinati livelli di isolamento che risolvono problemi di isolamento specifici. Ne discuteremo più in dettaglio nella prossima domanda. D sta per Durabilità . Questa proprietà garantisce che se l'utente riceve la conferma che la transazione è stata completata, allora può essere sicuro che le modifiche non verranno annullate a causa di qualche errore. Cioè, puoi essere certo che qualche errore del sistema operativo non avrà alcun effetto sui tuoi dati se hai già ricevuto la conferma che la transazione è stata completata con successo.82. Quali sono i livelli di isolamento delle transazioni?
Come ho detto prima, quando si tratta di proprietà ACID, garantire l'isolamento è un processo che richiede molte risorse. Di conseguenza, questa proprietà è parzialmente implementata. Esistono diversi livelli di isolamento: più alto è il livello, più grave è l'impatto sulle prestazioni. Prima di passare ai livelli di isolamento delle transazioni, dobbiamo considerare vari problemi che si verificano a causa di un isolamento insufficiente delle transazioni :-
letture fantasma : quando la stessa richiesta, richiamata più volte all'interno di una stessa transazione, dà risultati diversi a causa di inserimenti da parte di un'altra transazione;
-
letture non ripetibili : quando la stessa richiesta, richiamata più di una volta all'interno di una singola transazione, restituisce dati diversi a causa di modifiche (aggiornamenti) e cancellazioni da parte di un'altra transazione;
-
letture sporche : lettura di dati non ancora impegnati che sono stati aggiunti o modificati da una transazione e successivamente sottoposti a rollback;
-
aggiornamenti persi : quando un blocco di dati viene modificato simultaneamente da diverse transazioni e tutte le modifiche tranne l'ultima vengono perse (simile a una condizione di competizione nel multithreading).
Livello di isolamento | Il fantasma legge | Letture non ripetibili | Letture sporche | Aggiornamento perso |
---|---|---|---|---|
SERIALIZZABILE | + | + | + | + |
LETTURA RIPETIBILE | - | + | + | + |
LEGGI IMPEGNO | - | - | + | + |
LEGGI SENZA IMPEGNO | - | - | - | + |
NESSUNO | - | - | - | - |
83. Qual è la differenza tra uno Statement e un PreparedStatement?
Qui abbiamo cambiato bruscamente la transizione alle funzionalità di JDBC . In ogni caso, vediamo prima di cosa si tratta . È un oggetto utilizzato per formare query SQL. JDBC utilizza tre tipi: Statement , PreparedStatement e CallableStatement . Non prenderemo in considerazione CallableStatement oggi. Stiamo invece parlando della differenza tra Statement e PreparedStatement .-
L'istruzione viene utilizzata per eseguire semplici query SQL senza parametri di input di runtime. PrepareStatement può accettare parametri di input in fase di esecuzione.
-
Per impostare i parametri per PreparedStatement , i parametri di input vengono scritti come punti interrogativi nella richiesta, in modo che possano essere sostituiti da qualche valore utilizzando vari setter, come setDouble() , setFloat() , setInt() , setTime() ... Questo significa che non inserirai il tipo di dati sbagliato nella richiesta.
-
PreparedStatement è precompilato e utilizza la memorizzazione nella cache, quindi può essere eseguito leggermente più velocemente di una richiesta composta da oggetti Statement . Di conseguenza, le istruzioni SQL eseguite frequentemente vengono create come oggetti PreparedStatement per migliorare le prestazioni.
-
L'istruzione è vulnerabile all'iniezione SQL, ma PreparedStatement le impedisce.
GO TO FULL VERSION