Perché i costruttori di java non hanno un tipo di reso?

Possibile duplicato:
Perché il costruttore non restituisce valore

Perché i costruttori non hanno un tipo di reso, nemmeno vuoto? Qual è la ragione per questo?

Il costruttore è internamente un metodo non statico con il nome e il tipo di void . Non restituisce nulla. Il primo object internamente viene allocato e quindi viene chiamato il suo costruttore. L’object non è allocato con il costruttore stesso.
In altre parole la syntax new Object() non solo chiama il costruttore ma crea anche un nuovo object e dopo aver chiamato il costruttore lo restituisce. Il tutorial Java di The Suns afferma che “Il nuovo operatore è seguito da una chiamata a un costruttore, che inizializza il nuovo object.” Inizializzare non significa creare.

Rispondere alla domanda La dichiarazione del tipo di ritorno mancante è un modo in cui si distingue il costruttore da un metodo. Ma puoi tornare dal costruttore come dal metodo void. Ad esempio questo codice viene compilato ed eseguito correttamente:

 public class TheClass { public TheClass(){ return; } public void TheClass(){ //confusing, but this is void method not constructor return; } public static void main(String[]a){ TheClass n = new TheClass(); n.TheClass();//void method invocation } } 

Questa class ha un metodo void ( non provarlo a casa – il metodo maiuscolo è uno stile sbagliato) e un costruttore. La differenza è nel tipo di reso dichiarato.

Guarda questo frammento di codice JNI che dimostra che il costruttore è un metodo vuoto statico:

  jstring MyNewString(JNIEnv *env, jchar *chars, jint len) { jclass stringClass; jmethodID cid; jcharArray elemArr; jstring result; stringClass = (*env)->FindClass(env, "java/lang/String"); if (stringClass == NULL) { return NULL; /* exception thrown */ } /* Get the method ID for the String(char[]) constructor */ cid = (*env)->GetMethodID(env, stringClass, "", "([C)V"); if (cid == NULL) { return NULL; /* exception thrown */ } /* Create a char[] that holds the string characters */ elemArr = (*env)->NewCharArray(env, len); if (elemArr == NULL) { return NULL; /* exception thrown */ } (*env)->SetCharArrayRegion(env, elemArr, 0, len, chars); result = (*env)->AllocObject(env, stringClass); if (result) { (*env)->CallNonvirtualVoidMethod(env, result, stringClass, cid, elemArr); /* we need to check for possible exceptions */ if ((*env)->ExceptionCheck(env)) { (*env)->DeleteLocalRef(env, result); result = NULL; } } /* Free local references */ (*env)->DeleteLocalRef(env, elemArr); (*env)->DeleteLocalRef(env, stringClass); return result; } 

specialmente questi frammenti:

  /* Get the method ID for the String(char[]) constructor */ cid = (*env)->GetMethodID(env, stringClass, "", "([C)V"); 

e poi

  /* Allocate new object. */ result = (*env)->AllocObject(env, stringClass); if (result) { /* Call uninitialized objects' constuctor. */ (*env)->CallNonvirtualVoidMethod(env, result, stringClass, cid, elemArr); 

il primo object viene allocato e quindi viene chiamato il metodo non . Per i dettagli guarda qui . La documentazione della funzione AllocObject indica che “Assegna un nuovo object Java senza richiamare nessuno dei costruttori per l’object. Restituisce un riferimento all’object.” Quindi in JVM l’object non è allocato dal costruttore, ma solo inizializzato da esso. Guardando nel bytecode dei costruttori stiamo vedendo che nessun object viene restituito (esattamente come nei metodi void).

Un altro modo, quando si disassembla la class di esempio, si vedrà l’invocazione del costruttore genitore (Object) dal suo costruttore:

 #javap -c NewClass Compiled from "NewClass.java" public class NewClass extends java.lang.Object{ public NewClass(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return } 

Nota che il metodo non è in realtà parte del linguaggio Java. Piuttosto, è qualcosa che la macchina virtuale Java si aspetta di vedere in un file di class Java. Questa distinzione è significativa perché il linguaggio Java non dipende dal file di class. Il codice sorgente Java può essere compilato in altri formati binari, inclusi eseguibili nativi. Un compilatore Java che traduce l’origine del linguaggio Java in qualche altro formato binario non ha bisogno di generare un metodo chiamato , a patto che gli oggetti siano inizializzati nel modo corretto al momento giusto. La specifica Java Language Specification (JLS) specifica l’ordine di inizializzazione e quando si verifica, ma non dice come viene effettivamente realizzato.

Ma vedo che stiamo parlando di JVM qui.

Per alcuni di non credenti questo è un esempio (thx biziclop) che mostra che l’object esiste ed è allocato prima di tornare dal costruttore:

  class AnotherClass { private String field; public static AnotherClass ref; public AnotherClass() { this.field = "value"; AnotherClass.ref = this; throw new RuntimeException(); } @Override public String toString() { return field; } } public class MainClass { public static void main(String[] a) { try { new AnotherClass(); return; } catch (RuntimeException ex) { System.out.println("exception"); } System.out.println("instance: " + AnotherClass.ref); } } 

Come otterresti il ​​valore restituito? Che tipo di valore ti interessa, che ti viene restituito? Come dichiareresti il ​​tipo di reso?

  X x = new X (); 

assegna un riferimento X a x. Ora, se la new X restituisse qualcosa, come si dovrebbe ottenere?

  class X { public int X () { return 42; } } 

Qual è la logica per restituire qualcosa al ctor? Un messaggio di errore? Qualche loginfo? Scriverlo su un file o su un attributo, che si interroga in seguito.

Poiché il ctor è accessibile solo una volta per object, l’unica ragione per cui posso pensare, per usare un altro valore di ritorno, sarebbe, informare sul processo di creazione stesso.

  class X { private Y y; public int X () { y = new Y (); } public Y getY () { return y; } } 

Anche se l’implementazione VM di un costruttore non restituisce alcun valore, in pratica lo fa di solito: il riferimento del nuovo object. Sarebbe quindi sintatticamente strano e / o confuso essere in grado di memorizzare uno o entrambi il riferimento del nuovo object e un valore di ritorno aggiuntivo in un’istruzione.