Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do constructors in java not have a return type? [duplicate]

Possible Duplicate:
Why constructor not returns value

Why don't constructors have a return type, not even void? What's the reason for that?

like image 953
user845932 Avatar asked Jul 23 '11 15:07

user845932


People also ask

Why do constructors do not have return type in Java?

So the reason the constructor doesn't return a value is because it's not called directly by your code, it's called by the memory allocation and object initialization code in the runtime. Its return value (if it actually has one when compiled down to machine code) is opaque to the user - therefore, you can't specify it.

Why constructors do not have any return type with example?

Constructor looks like method but it is not. It does not have a return type and its name is same as the class name. Mostly it is used to instantiate the instance variables of a class. If the programmer doesn't write a constructor the compiler writes a constructors on his behalf.

Which type of constructors Cannot have a return type?

C++ Constructors have no return type.

Can constructor have return value in Java?

No, constructor does not return any value. While declaring a constructor you will not have anything like return type. In general, Constructor is implicitly called at the time of instantiation. And it is not a method, its sole purpose is to initialize the instance variables.


1 Answers

Constructor is internally a nonstatic method with name <init> and void return type. It does not return anything. Internally first object is allocated and then its constructor is called. Object is not allocated with constructor itself.
In other words the syntax new Object() not only calls the constructor but also creates new object and after calling the constructor returns it. The Suns' Java tutorial stands that "The new operator is followed by a call to a constructor, which initializes the new object." Initialize does not mean create.

Answering the question. Missing return type declaration is a way in which you distinguish the constructor from a method. But you can return from constructor as from void method. For example this code compiles and runs correctly:

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

This class has one void method (don't try it at home - uppercase method is a bad style) and one constructor. The difference is in declared return type.

Look at this JNI code snippet which demonstrates that constructor is a nonstatic void method:

 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,                                "<init>", "([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;  } 

especially these fragments:

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

and then

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

first object is allocated and then nonstatic <init> method is called. For details look here. The AllocObject function documentation stands that "Allocates a new Java object without invoking any of the constructors for the object. Returns a reference to the object." So in JVM object is not allocated by constructor, but only initialized by it. Looking in constructors' bytecode we are seeing that no object is returned (exactly like in void methods).

Another way, when you dissasemble sample class, you will see invocation of parent (Object) constructor from its constructor:

#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."<init>":()V    4:   return  } 

Note that the <init> method is not actually part of the Java language. Rather, it is something the Java virtual machine expects to see in a Java class file. This distinction is significant because the Java language does not depend on the class file. Java source can be compiled into other binary formats, including native executables. A Java compiler that translates Java language source into some other binary format need not generate a method named <init>, so long as objects are initialized in the proper way at the proper time. The Java Language Specification (JLS) details the order of initialization and when it occurs, but doesn't say how it is actually accomplished.

But I see that we're talking about JVM here.

For some of nonbelievers this is example (thx biziclop) which shows that object exists and is allocated before returning from constructor:

   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);         }     } 
like image 82
15 revs, 3 users 98% Avatar answered Sep 23 '22 07:09

15 revs, 3 users 98%