2

我哥哥在中学当老师,正在为考试评分。他问了一个问题:“构造函数的目的是什么?”

所以现在有一些答案,比如“构造函数创建了一个对象......”

当然,他希望看到类似“构造函数在对象实例化之后调用,用于初始化对象的成员变量......”(只是一个例子)

问题在于,有很多文献中作者写道,Java 中的构造函数创建了对象,并且通常大多数作者似乎避免对整个过程进行详细解释。

我认为它是这样工作的:

类构造函数被称为 new 运算符的操作数,因为“构造函数的名称提供了要实例化的类的名称”。(见http://docs.oracle.com/javase/tutorial/java/javaOO/objectcreation.html

但在执行此构造函数之前,new 运算符会实例化类(分配内存等)并将成员变量设置为其默认值。

然后执行构造函数并初始化例如成员变量。

在最后一步中,new 运算符返回对对象的引用。

但我真的不知道这是否真的正确,以及事情是否按照确切的顺序发生。

有人详细了解对象创建吗?如果你创建一个子类,它是如何工作的?是先创建超类,然后调用其构造函数,然后以某种方式将子类合并到现有构造中,然后调用其构造函数吗?有人能以某种方式争辩说构造函数“创建”了一个对象吗?

我真的很期待阅读您的答案!

4

3 回答 3

1

据我所知,您的解释是正确的。构造函数背后的主要思想是您可以为对象强制执行有效状态。

考虑一个名为“Rational”的类,它有两个属性:分子 (int) 和分母 (int) 代码如下所示(为简洁起见,我省略了 getter 和 setter)

public class Rational {
    private int numerator;
    private int denominator;

    public Rational(int numerator, int denominator) {
        this.numerator = numerator;
        this.denominator = denominator;
    }

    public double getRationalValue() {
        return (double) numerator / denominator;
    }

    public static void main(String[] args) {
        Rational oneFourth = new Rational(1, 4);
        System.out.println(oneFourth.getRationalValue());
    }
}

如您所见,我编写了一个构造函数,它“要求”分子和分母的值。如果您只有一个默认构造函数,那么任何人都可以在不指定分子或分母的情况下创建 Rational 的实例,并且如果您没有为 int 变量指定值,它们将被初始化为零。每个人都知道,如果你除以零,宇宙就会坍塌,所以我们想避免这种情况。

无论如何,正如您正确解释的那样,构造函数不会生成对象。您应该将它们更多地视为一种称为“后期构造”的方法。

对于基类,总是先调用基类的构造函数。这确保您可以在子类构造函数中访问基类的受保护属性。由于 Java 中的每个类都继承自 Object,因此始终首先调用 Object 构造函数。

以下片段:

public class Base {
    protected String baseProperty;

    public Base() {
        System.out.println("In base constructor");
        this.baseProperty = "This gets initialized first";
    }

    static class Sub extends Base {
        private String subProperty;

        Sub() {
            System.out.println("In sub constructor, baseProperty = " + baseProperty);
        }
    }

    public static void main(String args[]) {
        Base base = new Sub();
    }
}

印刷:

在基础构造函数中

在子构造函数中,baseProperty = This 首先被初始化

于 2013-05-26T17:18:56.100 回答
1

Java 语言规范中涵盖了血淋淋的细节,这是您每天都需要了解的基础知识(在下一节继续,我指出了类初始化,它发生在类第一次调用 new 时它(也有其他方式发生))。

new 为对象分配内存并将其初始化为 0、null、false(取决于类型)。这就是为什么所有实例变量都保证具有初始值的原因。

假设 new 成功,则调用构造函数以允许程序员执行其他初始化/任务。

构造函数做的第一件事就是调用父构造函数(super(...))。这一直发生在层次结构中,直到它到达没有父级的 java.lang.Object 。

在执行构造函数之前,任何实例初始化块都会运行,然后是任何具有赋值运算符的实例变量。

如果一个实例变量被标记为 final 并且有一个赋值运算符,如果我没记错的话,这似乎发生在对 super 的调用之前,这是一种特殊情况(它有一些技巧)。

这就是为什么你永远不应该引用 this.method() (隐式或显式)或将 this 从构造函数中传递出去,因为你将使用未完成的对象。

于 2013-05-26T16:57:06.687 回答
0

从规范中清除您对 new 和 constructor 角色的疑问:

创建对象

如您所知,类提供对象的蓝图;您从一个类创建一个对象。从 CreateObjectDemo 程序中获取的以下每个语句都会创建一个对象并将其分配给一个变量:

Point originOne = new Point(23, 94);
Rectangle rectOne = new Rectangle(originOne, 100, 200);
Rectangle rectTwo = new Rectangle(50, 100);

第一行创建一个 Point 类的对象,第二行和第三行分别创建一个 Rectangle 类的对象。

这些陈述中的每一个都包含三个部分(下面将详细讨论):

声明:以粗体显示的代码是所有将变量名与对象类型相关联的变量声明。

实例化:new 关键字是创建对象的 Java 运算符。

初始化:new 运算符之后是对构造函数的调用,该构造函数初始化新对象。

于 2013-05-26T16:54:12.963 回答