Java 调用构造函数是否需要将变量初始化为默认值?
我试图阅读这里几乎每一篇关于变量初始化的文章,但我仍然不了解其中的一些内容。我不清楚我们是否必须调用构造函数来将实例变量初始化为默认值,或者不调用构造函数就可以实现?例如,惯例是我们用Java编写的每个类都在其构造函数中调用一个超类构造函数来“初始化”超类的变量。这到底是什么意思?我们是否必须调用一个超类构造函数来将超类的实例变量初始化为默认值?或者即使没有invokin,超类构造函数实例变量也有一个默认值,我们这样做是为了传递构造函数中描述的值还是声明中给出的值?第二件事是,我们可以通过两种方式初始化变量,不给它们赋值(它们将被设置为默认值),在声明中赋值,例如:Java 调用构造函数是否需要将变量初始化为默认值?,java,initialization,Java,Initialization,我试图阅读这里几乎每一篇关于变量初始化的文章,但我仍然不了解其中的一些内容。我不清楚我们是否必须调用构造函数来将实例变量初始化为默认值,或者不调用构造函数就可以实现?例如,惯例是我们用Java编写的每个类都在其构造函数中调用一个超类构造函数来“初始化”超类的变量。这到底是什么意思?我们是否必须调用一个超类构造函数来将超类的实例变量初始化为默认值?或者即使没有invokin,超类构造函数实例变量也有一个默认值,我们这样做是为了传递构造函数中描述的值还是声明中给出的值?第二件事是,我们可以通过两种方
private int number = 10;
或在构造函数中指定值。我很清楚,我们必须调用构造函数来将变量初始化为构造函数中指定的值,但是其他两个例子呢?我们是否也必须调用构造函数来将实例变量初始化为这些值?有没有人能给我一个简单的命令来创建这个?我知道这里有很多关于对象实例化和初始化顺序的文章,我都读过了,但我仍然不了解其中的很多内容。
如果我错了,告诉我,但我所理解的,问题的答案是,我们必须调用一个超类构造函数来将超类字段初始化为它们的默认值,因为在另一种方式中,如果超类的实例变量已经用默认值初始化,而不调用构造函数-因为我们不必担心变量未初始化(如果未初始化),而是使用默认值
@编辑:说清楚,我的主要问题是:
实例变量何时获得默认值?在构造函数中还是在构造函数之前?是否必须调用构造函数来初始化实例变量,或者甚至在调用构造函数之前就分配了默认值?在面向对象编程语言中,“对象”起着关键作用。因此,启动对象是必须的。我不能完全理解你的要求。。我是根据我的知识讲的 必须实例化类才能使用其字段和方法。为此,您将这样分配
Class_Name object=新Class_Name()代码>在面向对象编程语言中,“对象”起着关键作用。因此,启动对象是必须的。我不能完全理解你的要求。。我是根据我的知识讲的
必须实例化类才能使用其字段和方法。为此,您将这样分配
Class_Name object=新Class_Name()代码>根据:
程序中的每个变量都必须有一个值,然后才能确定其值
使用:
每个类变量、实例变量或数组组件都是
创建时使用默认值初始化(§15.9,§15.10.2):
对于byte类型,默认值为零,即
(字节)0
对于type short,默认值为零,即
(短)0
对于int类型,默认值为零,即0
对于long类型,默认值为零,即0L
对于类型float,默认值为正零,即0.0f
对于double类型,默认值为正零,即0.0d
对于char类型,默认值为空字符,即,
“\u0000”
对于boolean类型,默认值为false
对于所有参考类型(§4.3),默认值为空
每个方法参数(§8.4.1)初始化为相应的
方法调用方提供的参数值(§15.12)
每个构造函数参数(§8.8.1)初始化为
类实例创建提供的相应参数值
表达式(§15.9)或显式构造函数调用(§8.8.7)
异常参数(§14.20)初始化为抛出的对象
代表例外情况(§11.3,§14.18)
局部变量(§14.4,§14.14)必须明确给定一个值
在使用前,通过初始化(§14.4)或赋值
(§15.26),以可使用规则进行验证的方式
转让(§16(明确转让))
因此,如果您的字段在使用前未在任何地方初始化,则对于对象/引用类型,初始(或默认)值将为null
,对于基本boolean
类型,初始值将为false
,对于任何其他基本类型(char
isnull
字符),初始(或默认)值将为0
如果字段已初始化,那么我们需要查看顺序
private class A {
protected int a = 2;
public A() {
System.out.println("Printing from constructor of A");
printValues();
System.out.println();
}
public void printValues() {
System.out.println("a = " + a);
}
}
private class B extends A {
private int b = 3;
private int c = initC();
public B() {
super();
System.out.println("Printing from constructor of B");
printValues();
System.out.println();
}
@Override
public void printValues() {
super.printValues(); // Call parent implementation
System.out.println("b = " + b);
System.out.println("c = " + c);
}
private int initC() {
System.out.println("Printing from initC()");
printValues();
System.out.println();
return 4;
}
public static void main(String[] args) {
new B();
}
}
这将产生:
Printing from constructor of A
a = 2
b = 0
c = 0
Printing from initC()
a = 2
b = 3
c = 0
Printing from constructor of B
a = 2
b = 3
c = 4
在A
(父类)的构造函数中,A
(属于A
)已用2
初始化。其他2个字段保持未初始化状态,返回JLS 4.12.5指定的值
然后A
的构造函数完成并返回到B
的构造函数(子类)。您可能希望它转到B
构造函数部分,但是在调用initC()
之前发生了其他事情。此时,我们可以看到b
也已初始化,但c
尚未初始化,因为initC()
应该返回初始化c
的值
最后,我们
class B extends A {
public B() {}
}
class B extends A {
public B() {
super();
}
}