introduzione
Come sappiamo, Java è un linguaggio di programmazione orientato agli oggetti. Cioè, il concetto di base, perché dire che la base dei fondamenti è che tutto è un oggetto. Gli oggetti sono descritti utilizzando le classi.
Le classi, a loro volta, hanno stato e comportamento. Ad esempio, un conto bancario può avere uno stato sotto forma di quantità di denaro nel conto e avere il comportamento di aumentare e diminuire il saldo. Il comportamento in Java viene implementato utilizzando metodi. La modalità di descrizione dei metodi viene introdotta all'inizio del tuo percorso di apprendimento di Java. Ad esempio, nel tutorial ufficiale di Oracle: “
Defining Methods ”. Ci sono due aspetti importanti qui:
- Ogni metodo ha una firma. La firma è costituita dal nome del metodo e dai suoi parametri di input;
- I metodi devono specificare un tipo restituito;
- Il tipo restituito non fa parte della firma del metodo.
Ancora una volta, questa è una conseguenza del fatto che Java è un linguaggio fortemente tipizzato e il compilatore vuole capire in anticipo quali tipi vengono utilizzati il più possibile. Ancora una volta, per proteggerci dagli errori. In generale, tutto va per il bene. Bene, questo ancora una volta instilla in noi una cultura della gestione dei dati, mi sembra. Pertanto, per i metodi viene specificato il tipo di valore. E per restituire lo stesso valore dai metodi, viene utilizzata la parola chiave
return
.
Dichiarazione di restituzione della parola chiave in Java
La parola chiave istruzione
return
si riferisce alle "istruzioni del flusso di controllo" come discusso nel tutorial di Oracle "
Dichiarazioni del flusso di controllo ". Puoi anche leggere come restituire i valori nel tutorial ufficiale: “
Restituzione di un valore da un metodo ”. Il compilatore controlla attentamente, al meglio delle sue capacità, che il valore restituito da un metodo corrisponda al tipo di valore restituito specificato dal metodo.
Usiamo l'IDE online di tutorialspoint come esempio . Diamo un'occhiata all'esempio originale:
public class HelloWorld {
public static void main(String []args) {
System.out.println("Hello World");
}
}
Come possiamo vedere, qui viene eseguito un metodo
main
, che è il punto di ingresso al programma. Le righe di codice vengono eseguite dall'alto verso il basso. Il nostro
main
metodo non può restituire valori, altrimenti riceveremo un errore: "
Error: Main method must return a value of type void
". Pertanto, il metodo verrà semplicemente visualizzato sullo schermo. Spostiamo ora la ricezione della stringa in un metodo separato per la ricezione del messaggio:
public class HelloWorld {
public static void main(String []args) {
System.out.println(getHelloMessage());
}
public static String getHelloMessage() {
return "Hello World";
}
}
Come possiamo vedere, utilizzando la parola chiave
return
abbiamo specificato il valore restituito, che abbiamo utilizzato successivamente nel metodo
println
. Nella descrizione (definizione) del metodo,
getHelloMessage
abbiamo indicato che ci restituirà
String
. Ciò consente al compilatore di verificare che le azioni del metodo siano coerenti con il modo in cui è dichiarato. Naturalmente, il tipo del valore restituito specificato nella definizione del metodo può essere più ampio del tipo del valore restituito dal codice, ad es. La cosa principale è che i tipi sono ridotti l'uno all'altro. Altrimenti otterremo un errore di compilazione: "
error: incompatible types
". A proposito, probabilmente è sorta immediatamente la domanda: perché
return
si applica agli operatori di controllo del flusso di programma? Ma perché può interrompere il normale svolgimento del programma da cima a fondo. Per esempio:
public class HelloWorld {
public static void main(String []args){
if (args.length == 0) {
return;
}
for (String arg : args) {
System.out.println(arg);
}
}
}
Come si vede dall'esempio, interrompiamo l'esecuzione del metodo
main
se il nostro programma Java viene chiamato senza parametri. È importante ricordare che se poi si
return
dispone del codice, questo diventa inaccessibile. E il nostro compilatore intelligente lo noterà e non ti consentirà di eseguire un programma del genere. Ad esempio, questo codice non verrà compilato:
public static void main(String []args) {
System.out.println("1");
return;
System.out.println("2");
}
C'è uno sporco trucco per aggirare questo problema. Ad esempio, per scopi di debug o per qualche altro motivo. Il codice sopra può essere corretto racchiudendolo
return
in
if
un blocco:
if (2==2) {
return;
}
Dichiarazione di ritorno nella gestione degli errori
C'è una circostanza molto complicata: possiamo usarla
return
insieme alla gestione degli errori. Vorrei dire subito che usarlo
return
in
catch
un blocco è una forma molto, molto brutta, quindi dovresti evitarlo. Ma ci serve un esempio, no? Eccolo:
public class HelloWorld {
public static void main(String []args) {
System.out.println("Value is: " + getIntValue());
}
public static int getIntValue() {
int value = 1;
try {
System.out.println("Something terrible happens");
throw new Exception();
} catch (Exception e) {
System.out.println("Catched value: " + value);
return value;
} finally {
value++;
System.out.println("New value: " + value);
}
}
}
A prima vista, sembra che debba essere restituito 2, perché
finally
viene sempre eseguito. Ma no, il valore sarà 1 e la modifica alla variabile
finally
verrà ignorata. Inoltre, se contenesse
value
un oggetto e dicessimo
finally
,
value = null
restituirebbe
catch
comunque un riferimento all'oggetto, non
null
. Ma dal blocco
finally
l’operatore
return
avrebbe funzionato correttamente. I colleghi chiaramente non ti ringrazieranno per un simile regalo.
void.class
E infine. Puoi scrivere una costruzione strana come
void.class
. Sembrerebbe, perché e qual è il punto? Infatti, in vari framework e casi complicati in cui viene utilizzata
l'API Java Reflection , ciò potrebbe essere molto necessario. Ad esempio, puoi verificare quale tipo restituisce un metodo:
import java.lang.reflect.Method;
public class HelloWorld {
public void getVoidValue() {
}
public static void main(String[] args) {
for (Method method : HelloWorld.class.getDeclaredMethods()) {
System.out.println(method.getReturnType() == void.class);
}
}
}
Ciò può essere utile nei framework di test in cui è necessario sostituire il codice reale dei metodi. Ma per fare ciò, è necessario capire come si comporta questo metodo (ovvero, quali tipi restituisce). Esiste un secondo modo per implementare il metodo
main
dal codice sopra:
public static void main (String[] args) {
for (Method method : HelloWorld.class.getDeclaredMethods()) {
System.out.println(method.getReturnType() == Void.TYPE);
}
}
Una discussione piuttosto interessante sulla differenza tra loro può essere letta su StackOverflow:
qual è la differenza tra java.lang.Void e void? #Viacheslav
GO TO FULL VERSION