
Intervista Java: domande su OOP
1. Quali sono le caratteristiche di Java?
Risposta:-
Concetti OOP:
- orientamento agli oggetti
- eredità
- incapsulamento
- polimorfismo
- astrazione
-
Multipiattaforma: un programma Java può essere eseguito su qualsiasi piattaforma senza alcuna modifica. Naturalmente, ciò richiede una JVM (Java virtual machine) installata.
-
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.
- Multithreading: la JVM crea un thread di esecuzione chiamato
main thread
. Un programmatore può creare più thread derivando dalla classe Thread o implementando l'Runnable
interfaccia.
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 comesuperclass
e 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'è Animal
il parent
ed 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:- Quando viene creato un nuovo oggetto, il programma utilizza il costruttore appropriato per crearlo.
- 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.
- Se non viene creato alcun costruttore in modo esplicito, viene creato automaticamente un costruttore vuoto.
- Un costruttore può essere sovrascritto.
- 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:private
— Questo modificatore di accesso viene utilizzato su metodi, campi e costruttori. L'accesso è limitato alla classe in cui sono dichiarati.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.protected
— Questo modificatore di accesso offre lo stesso livello di accesso dell'aggiuntapackage-private
dell'accesso per le classi che ereditano una classe con ilprotected
modificatore.public
— Questo livello di accesso viene utilizzato anche per le classi. Questo livello di accesso significa che c'è pieno accesso in tutta l'applicazione.

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?

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
ArrayList
della 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 oggettoadd(int index, Object o)
— Questo metodo aggiunge un oggetto a un indice specificoadd(Collection<Object> c)
— Questo metodo aggiunge un elenco di oggettiadd(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.
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 dalladefault
parola 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 inIterable
interfaccia. 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 abstract
parola 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 abstract
parola 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
17. Qual è la differenza tra String, StringBuilder e StringBuffer?
String
i 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 
name = "pen";
Il pool di stringhe costanti ha questo aspetto: 
String
i 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.
StringBuffer name = “book”;


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).
- 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 unint
array, dobbiamo scrivere quanto segue:
int[] intArray = new int[100];
Da questa sintassi si possono trarre diverse conclusioni:
- Quando viene dichiarato un array, il suo tipo è noto. Se il tipo è noto, è nota anche la dimensione di ogni cella dell'array.
- La dimensione dell'intero array è nota.
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
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à NullPointerException
lanciato 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?
Lafinal
parola chiave può essere utilizzata su variabili, metodi e classi.
- Il valore di una variabile final non può essere modificato dopo che è stato inizializzato.
- Una classe finale è sterile :) Non può avere figli.
- Un metodo final non può essere sovrascritto da un discendente.
Variabili finali
Java ci offre due modi per dichiarare una variabile e assegnarle un valore:- Puoi dichiarare una variabile e inizializzarla successivamente.
- Puoi dichiarare una variabile e assegnare subito un valore.
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 final
variabile. 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 unafinal
variabile 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 comefinal
non può essere estesa. In parole povere, nessun'altra classe può ereditarlo. Un eccellente esempio di final
classe 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
GO TO FULL VERSION