首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否需要调用构造函数来将变量初始化为默认值?

问是否需要调用构造函数来将变量初始化为默认值?
EN

Stack Overflow用户
提问于 2018-11-02 15:10:47
回答 3查看 1.7K关注 0票数 0

我试着浏览了这里关于变量初始化的几乎每一篇文章,但我仍然不理解关于它的一些事情。我不清楚我们是否必须调用构造函数来将实例变量初始化为默认值,或者这可以在不调用构造函数的情况下发生?例如,约定我们在Java中编写的每个类都在其构造函数中调用一个超类构造函数来“初始化超类的变量”。这到底是什么意思?我们是否必须调用一个超类构造函数来将超类的实例变量初始化为默认值?或者即使没有调用超类构造函数实例变量也有默认值,我们这样做是为了将构造函数中描述的值或声明过程中给出的值传递给它们?第二件事是,我们可以通过几种方式初始化变量,不给它们一个值(它们将被设置为默认值),在声明中给出值,例如:

代码语言:javascript
复制
private int number = 10;

或在构造函数中指定值。对我来说,很明显,我们必须调用构造函数来将变量初始化为构造函数中指定的值,但是其他两个示例呢?我们是否也必须调用构造函数来将实例变量初始化为这些值?有人可以给我一个订单,让我用简单的话来创建这个吗?我知道这里有很多关于对象实例化和初始化顺序的文章,我已经读过了,但我仍然不理解其中的许多东西。如果我错了,告诉我,但我理解的是,问题的答案是我们必须调用一个超类构造函数来将超类字段初始化为它们的默认值,因为在另一种方式下,如果超类的实例变量已经用默认值初始化了,而没有调用构造函数,那么调用超类构造函数就没有意义了-因为我们不必担心我们的变量在初始化时是未初始化的-使用默认值。

@EDIT:明确地说,我的主要问题是:实例变量何时获得默认值?在构造函数中还是在构造函数之前?是否必须调用构造函数来初始化实例变量,或者在调用构造函数之前就已经分配了默认值?

EN

回答 3

Stack Overflow用户

发布于 2018-11-02 15:27:23

在面向对象的程序设计语言中,“对象”起着关键作用。因此,初始化对象是必须的。我不能确切地得到你所要求的。我是根据我的知识告诉你的。

你必须实例化一个类来使用它的字段和方法。为此,您可以像这样分配

​

代码语言:javascript
复制
Class_Name object = new Class_Name();

​

无论您是否在调用类中创建默认构造函数都没有问题,它将创建一个默认构造函数。

但是,一旦你创建了一个带参数的构造函数,你就必须创建一个默认的构造函数来初始化一个类似上面的对象。

您可以按照您所描述的那样为类中的变量赋值&通过参数化的构造函数。最好编写私有修饰符来初始化变量(这里是封装概念)。

您可以通过在构造函数中传递参数来更改实例化变量的值。

如果你没有为你的变量设置任何值。编译器将为其设置一个默认值。请看这篇文章https://www.javaworld.com/article/2076614/core-java/object-initialization-in-java.html

票数 1
EN

Stack Overflow用户

发布于 2018-11-02 16:01:47

根据JLS 4.12.5的说法

程序中的每个变量在使用它的值之前都必须有一个值:

每个类变量、实例变量或数组组件在创建时都使用默认值进行初始化(§15.9、§15.10.2):

对于byte类型,默认值为0,即(byte)0的值。

对于short类型,默认值为0,即(short)0的值。

对于int类型,默认值为0,即0。

对于long类型,默认值为零,即0L。

对于浮点类型,默认值为正零,即0.0f。

对于双精度类型,默认值为正零,即0.0d。

对于char类型,默认值为空字符,即'\u0000‘。

对于boolean类型,缺省值为false。

对于所有引用类型(§4.3),默认值为null。

每个方法参数(§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 (确定赋值))进行验证。

因此,如果您的字段在使用之前没有在任何地方进行初始化,那么对于object/reference类型,初始(或默认)值将是null;对于原始boolean类型,初始(或默认值)将是false;对于任何其他原始类型,初始(或默认)值将是0 (对于char,0是null字符)。

如果字段已初始化,那么我们需要查看顺序。

代码语言:javascript
复制
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();
    }
}

这将生成:

代码语言:javascript
复制
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进行了初始化。其他两个字段保持未初始化状态,返回JLS 4.12.5指定的值。

然后,A的构造函数结束并返回到B (子类)的构造函数。您可能希望它转到B构造函数部分,但在此之前发生了其他事情- initC()正在被调用。此时,我们可以看到b也已经被初始化,但是c还没有被初始化,因为initC()应该返回初始化c的值。

最后,我们看到所有3个字段都被初始化了。

顺序是这样的:

  1. 大多数超类的字段首先被初始化。
  2. 当从超类的构造函数返回时,子类初始化它自己的字段将继续执行,这允许您使用初始化的值。

因此,内联初始化字段声明允许您确保字段在使用时具有值,即使在构造函数中也是如此,而在构造函数中初始化只能确保值在退出构造函数后被初始化(子类可以确保它也被初始化)。

票数 1
EN

Stack Overflow用户

发布于 2018-11-02 16:34:33

实例变量获取默认值时的

?在构造函数中还是在构造函数之前?

在构造函数之前。如果它们在构造函数之后获得默认值,那么在构造函数中将它们设置为不同的值就没有意义了。

是否必须调用构造函数来初始化实例变量,或者在调用构造函数之前就已经分配了默认值?

这并不重要,构造函数总是在你创建一个新的实例时被调用。如果您编写的子类没有显式调用其超类的构造函数,那么超类的无参数构造函数将被自动调用。

例如,如下所示:

代码语言:javascript
复制
class B extends A {
     public B() {}
}

等同于:

代码语言:javascript
复制
class B extends A {
     public B() {
         super();
     }
}

如果不显式调用超类构造函数,那么超类的no-args构造函数将被调用。如果不存在这样的构造函数,那么您的代码将不会编译。

构造函数总是被调用。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53114074

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档