为什么java中的构造函数没有返回类型?
可能重复:为什么java中的构造函数没有返回类型?,java,constructor,return-type,Java,Constructor,Return Type,可能重复: 为什么构造函数没有返回类型,甚至没有void?原因是什么?构造函数在内部是一个名为和void返回类型的非静态方法。它不返回任何内容。在内部分配第一个对象,然后调用其构造函数。对象未与构造函数本身一起分配。 换句话说,语法newobject()不仅调用构造函数,还创建新对象,调用构造函数后返回它。“新操作符后面是对构造函数的调用,构造函数初始化新对象。”初始化并不意味着创建 回答问题。缺少返回类型声明是区分构造函数和方法的一种方式。但您可以从构造函数返回,就像从void方法返回一样。
为什么构造函数没有返回类型,甚至没有void?原因是什么?构造函数在内部是一个名为
和void
返回类型的非静态方法。它不返回任何内容。在内部分配第一个对象,然后调用其构造函数。对象未与构造函数本身一起分配。换句话说,语法
newobject()
不仅调用构造函数,还创建新对象,调用构造函数后返回它。“新操作符后面是对构造函数的调用,构造函数初始化新对象。”初始化并不意味着创建
回答问题。缺少返回类型声明是区分构造函数和方法的一种方式。但您可以从构造函数返回,就像从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
}
}
这个类有一个void方法(不要在家里尝试——大写方法是一种糟糕的样式)和一个构造函数。区别在于声明的返回类型
看看这个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,
"<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;
}
首先分配对象,然后调用非静态的
方法。详情请参阅。“分配一个新的Java对象而不调用该对象的任何构造函数。返回对该对象的引用。”因此在JVM中,对象不是由构造函数分配的,而是由构造函数初始化的。查看构造函数的字节码,我们发现没有返回任何对象(与void方法完全相同)
另一种方法是,当您分解示例类时,您将看到父(对象)构造函数从其构造函数调用:
#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
}
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);
}
}
尽管构造函数的VM实现不返回任何值,但实际上它确实返回了新对象的引用。如果能够在一条语句中存储一个或两个新对象的引用和一个额外的返回值,那么在语法上会很奇怪和/或让人困惑。如何获取返回值?你对什么样的价值感兴趣,被返还?您将如何声明返回类型
X x = new X ();
将X参照指定给X。现在,如果new X
将返回某些内容,您应该如何获取它
class X {
public int X () {
return 42;
}
}
从ctor返回某些内容的逻辑是什么?错误消息?一些登录信息?将其写入稍后轮询的文件或属性
因为每个对象只访问一次ctor,所以我能想到的唯一原因,使用另一个返回值,就是通知创建过程本身
class X {
private Y y;
public int X () {
y = new Y ();
}
public Y getY () { return y; }
}
谢谢分享你的智慧。我假设第一个代码片段来自JVM?你能给这些代码提供一些链接吗?另一个证明在调用构造函数之前对象已经被完全创建的证据是从构造函数中抛出一个异常。如果您错误地将
此
发布到另一个对象,则引用将保持活动状态并完全可用。还有一个是反序列化,根本不调用任何构造函数。我总是对那些在回答中提到这一点的人投反对票。说真的,如果有人不同意某件事,他们可能会也可能不会就此发表评论,你并不需要让他们回到你的答案上来证明自己。@M28:IMHO你不明白它在这里是如何工作的。我们是在选举岗位上投票,而不是在选举人民。你说“我总是投反对票”。这不是总统选举。这不是关于答案作者,而是关于其他读者。从我的观点来看,投票和答案是对他们和OP的,而不是对答案作者的。@M28我想你误解了规则。请花点时间阅读手册,了解其含义。请注意,所列标准中缺少不同意。这与语法有关。例如,i++
操作符有更多的逻辑。Sun Java教程指出,新运算符后面是对构造函数的调用,构造函数初始化新对象。-它解释了一切:“Tyell:不是一个精确的副本,因为这个问题不命名语言,它的答案指的是不同语言的混合,而这个问题是关于java的。为什么C++的构造函数有返回类型?这不是复制的。这个问题特别与Java有关,如@DanielPryden注释,而“duplicate”是与语言无关的。@biziclop您可以将其存储在变量中,这样就不需要返回类型,因为构造函数已经创建了一个新的对象,请注意:)但是,其他一些语言需要构造函数专门将“void”声明为返回类型。一方面,这使它显式清晰,另一方面,不声明返回类型使构造函数签名更容易识别。@Cawas这听起来不是个好主意。如果你能做到这一点,你就无法在不检查变量的情况下知道它是否为空。如果要发出无法创建对象的信号,可以抛出异常。
class X {
public int X () {
return 42;
}
}
class X {
private Y y;
public int X () {
y = new Y ();
}
public Y getY () { return y; }
}