Ciao a tutti, oggi continuo ad analizzare oltre 250 domande di interviste per sviluppatori Java. Parti precedenti dell'analisi: prima , seconda , terza . Quindi continuiamo.
<nome classe>{ereditarietà dalla classe genitore} {implementazione dell'interfaccia}
Quindi, quello che abbiamo: {class access modifier} - solo i modificatori public e il modificatore di accesso mancante, ovvero default , sono disponibili per la class . {class static} - static è un modificatore che indica che questa classe è statica, applicabile solo alle classi interne (classi all'interno di altre classi). {finalità della classe} - come ricordiamo, questo è il modificatore finale , in presenza del quale la classe diventa non ereditabile (esempio dal riquadro - String ). {astrazione della classe} - modificatore - abstract , che indica che questa classe potrebbe avere metodi non implementati. Questo modificatore è in conflitto con il modificatore finale , cioè solo uno di essi può essere nell'intestazione della classe, poiché il modificatore astratto implica che la classe data verrà ereditata e le sue parti astratte verranno implementate. E final indica che questa è la versione finale (finale) della classe e non può essere ereditata. In realtà, utilizzare entrambi i modificatori contemporaneamente sarebbe assurdo e il compilatore non ce lo permetterà. <class> è una parola chiave obbligatoria che indica una dichiarazione di classe. <nome classe> è un nome di classe semplice, che è l'identificatore di una classe Java specifica. Il nome completo della classe è costituito dal nome completo del pacchetto + . + nome della classe semplice. {ereditarietà dalla classe genitore} : specifica la classe genitore (se presente) utilizzando la parola chiave extends . Ad esempio, .. estende ParentClass . {implementazione dell'interfaccia} - specificando le interfacce che questa classe implementa (se presenti) utilizzando la parola chiave implements . Ad esempio: ... implementa FirstInterface, SecondInterface ... Bene, come esempio di intestazione di classe, considera l'intestazione della classe Lion , che eredita da Cat e implementa l' interfaccia WildAnimal :
29. È possibile utilizzare return in un costruttore?
Puoi, ma senza il valore di ritorno per il diritto alla restituzione . Cioè, puoi usare return; come costruzione ausiliaria durante i calcoli nel costruttore per terminare (interrompere) urgentemente l'esecuzione di ulteriore codice e completare l'inizializzazione dell'oggetto. Ad esempio, abbiamo una classe Cat e se Cat is homeless - isHomeless = true , dobbiamo completare l'inizializzazione e non compilare altri campi (dopotutto, ci sono sconosciuti, poiché il gatto è senza casa):public Cat(int age, String name, boolean isHomeless) {
if (isHomeless){
this.isHomeless = isHomeless;
return;
}
this.isHomeless = isHomeless;
this.age = age;
this.name = name;
}
Ma quando si tratta di valori specifici, un costruttore non può utilizzare return per restituire un valore perché:
- quando dichiari un costruttore non avrai nulla che assomigli a un tipo restituito;
- In genere, il costruttore viene chiamato implicitamente durante l'istanziazione;
- Un costruttore non è un metodo: è un meccanismo separato il cui unico scopo è inizializzare le variabili di istanza e l' operatore new è responsabile della creazione di un oggetto .
30. È possibile lanciare un'eccezione da un costruttore?
I costruttori gestiscono le eccezioni esattamente allo stesso modo dei metodi. E se i metodi ci consentono di lanciare eccezioni scrivendo Throws <ExceptionType> nell'intestazione del metodo , allora il costruttore ci consente di farlo e anche quando ereditiamo e definiamo un costruttore erede, possiamo espandere il tipo di eccezione. Ad esempio, IOException -> Eccezione (ma non viceversa). Come esempio per lanciare un'eccezione da parte di un costruttore, prendiamo la classe Cat . Diciamo che al momento della creazione vogliamo inserire nome ed età da console:public Cat() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
this.name = reader.readLine();
this.age = Integer.parseInt(reader.readLine());
}
Poiché reader.readLine() lancia una IOException, la specifichiamo nell'intestazione come possibile eccezione lanciata.
31. Da quali elementi è composta l'intestazione della classe? Scrivi un esempio
Parlando degli elementi che compongono l'intestazione della classe, diamo un'occhiata a un piccolo diagramma:- i componenti obbligatori saranno tra parentesi <>
- facoltativo - in {}
public final class Lion extends Cat implements WildAnimal
32. Da quali elementi è composta l'intestazione del metodo? Scrivi un esempio
Ancora una volta, quando osservi gli elementi che compongono l'intestazione di un metodo, considera un piccolo diagramma in cui:- i componenti obbligatori sono tra parentesi <>
- facoltativo - in {}
public static void main(String[] args) throws IOException
33. Crea un costruttore predefinito nell'oggetto discendente se non è definito nell'oggetto base (ma è definito un altro costruttore)
Non capisco appieno la domanda in sé, ma forse significa che, ad esempio, nel genitore abbiamo qualche costruttore personalizzato:public Cat(int age, String name) {
this.age = age;
this.name = name;
}
Pertanto, nella classe antenata, dobbiamo assolutamente definire un costruttore che riempirà (chiamerà) il costruttore genitore:
public class Lion extends Cat {
public Lion(int age, String name) {
super(age, name);
}
}
34. Quando viene utilizzata la parola chiave this?
In Java, questo ha due significati diversi. 1. Come riferimento all'oggetto corrente, come this.age = 9 . Cioè, questo si riferisce all'oggetto su cui è stato chiamato e al quale fa riferimento il codice che lo utilizza . La funzione principale è aumentare la leggibilità del codice ed evitare ambiguità. Ad esempio, se il nome del campo della classe interna e l'argomento del metodo sono gli stessi:public void setName(String name) {
this.name = name;
}
Ciò significa che this.name è un campo del nome dell'oggetto e un argomento del metodo. Il riferimento this non può essere utilizzato nei metodi statici. 2. questo può essere utilizzato in un costruttore sotto forma di chiamata al metodo, come this(value) . In questo caso si tratterà di una chiamata ad un altro costruttore della stessa classe. In breve, puoi chiamare due costruttori contemporaneamente quando crei un oggetto:
public Cat(int age, String name) {
this(name);
this.age = age;
}
public Cat(String name) {
this.name = name;
}
Quando viene creato un oggetto Cat e viene chiamato il primo costruttore, entrambi i campi dell'oggetto verranno chiamati e inizializzati con successo. Ci sono un paio di sfumature:
- this() funziona solo nel costruttore.
- Un riferimento a un altro costruttore deve trovarsi nella prima riga del blocco costruttore (corpo). Pertanto, più di un (altro) costruttore di una determinata classe non può essere chiamato in un costruttore.
35. Cos'è un inizializzatore?
Per quanto ho capito, in questa domanda stiamo parlando di blocchi di inizializzazione ordinari e statistici. Innanzitutto, ricordiamo cos'è l'inizializzazione. L'inizializzazione è creazione, attivazione, preparazione al lavoro, determinazione dei parametri. Portare un programma o un componente in uno stato di pronto per l'uso. Come ricorderete, durante la creazione dell'oggetto, una variabile di classe può essere inizializzata direttamente al momento della dichiarazione:class Cat {
private int age = 9;
private String name = "Tom";
Oppure impostalo esternamente tramite un costruttore:
class Cat {
private int age;
private String name;
public Cat(int age, String name) {
this.age = age;
this.name = name;
}
Ma c'è un altro modo: impostare una variabile oggetto interna tramite un blocco di inizializzazione, che assomiglia a parentesi graffe { } all'interno della classe, senza nome (come un metodo o un costruttore):
class Cat {
private int age;
private String name;
{
age = 10;
name = "Tom";
}
Cioè, un blocco di inizializzazione è un pezzo di codice che viene caricato quando viene creato un oggetto. In genere, tali blocchi vengono utilizzati per eseguire alcuni calcoli complessi necessari durante il caricamento di una classe. I risultati di questi calcoli possono essere specificati come valori per le variabili. Inoltre, oltre ai normali blocchi di inizializzazione, ce ne sono di statici, che sembrano uguali, ma hanno la parola chiave static prima della parentesi graffa :
class Cat {
private static int age;
private static String name;
static{
age = 10;
name = "Tom";
}
Questo blocco è esattamente uguale al precedente. Ma se quello normale viene attivato quando ciascun oggetto viene inizializzato, quello statico si attiverà solo una volta, quando la classe viene caricata. In un tale blocco, di norma, vengono eseguiti anche alcuni calcoli complessi per la successiva inizializzazione delle variabili di classe statiche. A un blocco statico si applicano le stesse restrizioni dei metodi statici: non può utilizzare dati non statici, così come un riferimento all'oggetto corrente - this . Successivamente, possiamo vedere l'ordine di inizializzazione della classe (insieme al suo antenato) per una migliore comprensione del momento in cui vengono attivati i blocchi di inizializzazione.
36. Per ereditare una classe pubblica, la classe Child estende Parent, scrivere l'ordine di inizializzazione dell'oggetto
Quando viene caricata la classe Child, l'ordine di inizializzazione sarà il seguente:- Campi statici della classe Parent .
- Blocco di inizializzazione statico per la classe Parent .
- Campi statici della classe Child .
- Blocco di inizializzazione statico per la classe Child .
- Campi non statici della classe Parent .
- Non un blocco di inizializzazione statico per la classe Parent .
- Costruttore per la classe Parent .
- Campi non statici della classe Child .
- Non un blocco di inizializzazione statico per la classe Child .
- Costruttore della classe Child .
37. Quali relazioni conosci tra classi (oggetti)?
Esistono due tipi di relazioni tra le classi in Java:- È-una relazione
Lion IS-A Cat
(ma non tutti i gatti sono un leone ) La situazione è esattamente la stessa con le interfacce. Se la classe Lion implementa l' interfaccia WildAnimal , anche loro sono in una relazione:
Lion IS-A WildAnimal
- Relazioni HA-A
Car HAS-A Passenger
E viceversa: se Passenger ha un riferimento a Car , allora questa sarà la relazione:
Passenger HAS-A Car
38. Quali connessioni associative tra oggetti conosci?
Aggregazione e composizione non sono altro che casi particolari di associazione. L'aggregazione è una relazione in cui un oggetto è parte di un altro. Ad esempio, un passeggero potrebbe trovarsi in un'auto. Inoltre, potrebbero esserci più passeggeri o non esserci affatto (se stiamo parlando di una Tesla, l'autista non è richiesto). Per esempio:public class Car {
private List passengers = new ArrayList<>();
void setPassenger(Passenger passenger) {
passengers.add(passenger);
}
void move() {
for (Passenger passenger : passengers) {
System.out.println("Перевозка пассажира - " + passenger.toString());
}
passengers.clear();
}
}
Cioè, non ci interessa il numero di passeggeri (o se ce ne sono): la funzionalità della classe Auto non dipende da questo. L'aggregazione implica anche che quando un oggetto viene utilizzato da un altro oggetto, il primo può essere utilizzato in altri oggetti. Ad esempio, lo stesso studente può essere membro sia di un club di maglieria che di un gruppo musicale di rocker e allo stesso tempo frequentare un gruppo di studenti di inglese. Come hai capito, l'aggregazione è una relazione associativa più libera tra le classi. La composizione è un rapporto ancora più rigido quando un oggetto non solo è parte di un altro oggetto, ma il lavoro dell'altro oggetto dipende molto dal primo. Ad esempio, il motore di un'auto. Sebbene il motore possa esistere senza l’auto, è inutile al di fuori di essa. Ebbene, un'auto non può funzionare senza motore:
public class Car {
private Engine engine;
public Car(Engine engine) {
this.engine = engine;
}
void startMoving() {
engine.start();
...
}
La composizione implica anche che quando un oggetto viene utilizzato da un altro oggetto, il primo non può appartenere a nessun altro. Se torniamo al nostro esempio, un motore può appartenere solo a un'auto, ma non a due o più contemporaneamente. Probabilmente ci fermeremo qui oggi.
GO TO FULL VERSION