Почему конструкторы в java не имеют типа возврата?

Возможный дубликат:
Почему конструктор не возвращает значение

Почему у конструкторов нет типа возврата, даже не пусто? В чем причина этого?

Конструктор является внутренним нестатическим методом с именем и типом возврата void . Он ничего не возвращает. Внутренне первый объект распределяется, а затем вызывается его конструктор. Объект не выделяется самим конструктором.
Другими словами, синтаксис new Object() не только вызывает конструктор, но также создает новый объект и после вызова конструктора возвращает его. Учебник Java Suns утверждает, что «за новым оператором следует вызов конструктора, который инициализирует новый объект». Инициализация не означает создание.

Отвечая на вопрос. Недопустимая декларация типа возврата – это способ, которым вы выделяете конструктор из метода. Но вы можете вернуться из конструктора, как из метода void. Например, этот код компилируется и работает правильно:

 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 } } 

Этот class имеет один метод void ( не пытайтесь его дома – метод верхнего регистра – плохой стиль) и один конструктор. Разница заключается в объявленном типе возврата.

Посмотрите на этот fragment кода JNI, который демонстрирует, что конструктор – это нестатический метод void:

  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; } 

особенно эти fragmentы:

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

а потом

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

первый объект выделяется, и затем вызывается нестатический метод . Подробнее смотрите здесь . В документации по функциям AllocObject указано, что «Выделяет новый объект Java без вызова каких-либо конструкторов для объекта. Возвращает ссылку на объект». Таким образом, объект JVM не выделяется конструктором, а только инициализируется им. Глядя на байт-код конструкторов, мы видим, что объект не возвращается (точно так же, как в методах void).

Другой способ, когда вы разбираете образец classа, вы увидите вызов родительского (Object) конструктора из его конструктора:

 #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 } 

Обратите внимание, что метод самом деле не является частью языка Java. Скорее, это то, что ожидает виртуальная машина Java в файле classа Java. Это различие имеет большое значение, поскольку язык Java не зависит от файла classа. Источник Java может быть скомпилирован в другие двоичные форматы, включая собственные исполняемые файлы. Компилятор Java, который переводит источник языка Java в какой-то другой двоичный формат, не должен генерировать метод с именем , если объекты инициализируются надлежащим образом в соответствующее время. Спецификация языка Java (JLS) детализирует порядок инициализации и когда это происходит, но не говорит, как это делается на самом деле.

Но я вижу, что мы говорим о JVM здесь.

Для некоторых неверующих это пример (thx biziclop), который показывает, что объект существует и распределяется перед возвратом из конструктора:

  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); } } 

Как вы получите возвращаемое значение? Какую ценность вы интересуете, возвращаетесь? Как бы вы объявили тип возврата?

  X x = new X (); 

назначает X-ссылку на x. Теперь, если new X вернет что-то, как вы его получите?

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

Какова логика возврата чего-то из ctor? Сообщение об ошибке? Некоторые loginfo? Напишите его в файл или в атрибут, который вы опросите позже.

Поскольку ctor доступен только один раз для объекта, единственной причиной, по которой я могу думать, использовать другое возвращаемое значение, было бы, чтобы сообщить о процессе создания.

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

Несмотря на то, что реализация конструктора VM не должна возвращать какое-либо значение, на практике это вроде как – ссылка на новый объект. Тогда это было бы синтаксически странно и / или сбивать с толку, чтобы иметь возможность хранить одну или обе ссылки на новый объект и дополнительное возвращаемое значение в одном выражении.

  • Инициализация объединения с нетривиальным конструктором
  • Как я могу вызвать New-Object для конструктора, который принимает один параметр массива?
  • Делает много в конструкторах плохо?
  • java "void" и "non void" конструктор
  • Наследование с помощью конструктора базового classа с параметрами
  • вызов чистой виртуальной функции из конструктора базового classа
  • Как инициализировать поле const в конструкторе?
  • Есть ли неявный конструктор по умолчанию в C ++?
  • Конструктор Java не компилируется должным образом
  • Почему это () и super () должны быть первым утверждением в конструкторе?
  • В любом случае, @Autowire bean, который требует аргументов конструктора?
  • Давайте будем гением компьютера.