Creating Objects

如您所知,一个类为对象提供了设计图。您可以从类创建对象。以下来自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运算符之后是对构造函数的调用,该构造函数将初始化新对象。

声明变量以引用对象

先前,您了解到要声明一个变量,您可以编写:

type name;

这会通知编译器您将使用* name 来引用类型为 type *的数据。对于原始变量,此声明还为变量保留了适当的内存量。

您还可以在其自己的行上声明引用变量。例如:

Point originOne;

如果您这样声明originOne,则它的值将不确定,直到实际创建并为其分配对象为止。仅声明引用变量不会创建对象。为此,您需要使用new运算符,如下一节所述。您必须先在originOne中分配一个对象,然后才能在代码中使用它。否则,您将得到一个编译器错误。

处于这种状态的变量当前未引用任何对象,可以如下所示(变量名称originOne,加上指向任何内容的引用):

originOne 为 null。

实例化类

new运算符通过为新对象分配内存并返回对该内存的引用来实例化一个类。 new运算符还会调用对象构造函数。

Note:

短语“实例化一个类”的含义与“创建对象”相同。创建对象时,将创建类的“实例”,因此将“实例化”一个类。

new运算符只需要一个后缀参数:对构造函数的调用。构造函数的名称提供了要实例化的类的名称。

new运算符返回对其创建的对象的引用。此引用通常分配给适当类型的变量,例如:

Point originOne = new Point(23, 94);

new运算符返回的引用不必分配给变量。也可以直接在表达式中使用。例如:

int height = new Rectangle().height;

该声明将在下一节中讨论。

初始化对象

这是Point类的代码:

public class Point {
    public int x = 0;
    public int y = 0;
    //constructor
    public Point(int a, int b) {
        x = a;
        y = b;
    }
}

此类包含一个构造函数。您可以识别构造函数,因为其声明使用与类相同的名称,并且没有返回类型。 Point类中的构造函数采用两个整数参数,如代码\(int a, int b\)所声明。以下语句提供了 23 和 94 作为这些参数的值:

Point originOne = new Point(23, 94);

下图说明了执行此语句的结果:

originOne 现在指向一个 Point 对象。

这是Rectangle类的代码,其中包含四个构造函数:

public class Rectangle {
    public int width = 0;
    public int height = 0;
    public Point origin;

    // four constructors
    public Rectangle() {
        origin = new Point(0, 0);
    }
    public Rectangle(Point p) {
        origin = p;
    }
    public Rectangle(int w, int h) {
        origin = new Point(0, 0);
        width = w;
        height = h;
    }
    public Rectangle(Point p, int w, int h) {
        origin = p;
        width = w;
        height = h;
    }

    // a method for moving the rectangle
    public void move(int x, int y) {
        origin.x = x;
        origin.y = y;
    }

    // a method for computing the area of the rectangle
    public int getArea() {
        return width * height;
    }
}

每个构造函数都可以使用基本类型和引用类型为矩形的原点,宽度和高度提供初始值。如果一个类具有多个构造函数,则它们必须具有不同的签名。 Java 编译器根据参数的数量和类型来区分构造函数。当 Java 编译器遇到以下代码时,它知道要在Rectangle类中调用构造器,该构造器需要Point参数后跟两个整数参数:

Rectangle rectOne = new Rectangle(originOne, 100, 200);

这将调用Rectangle的构造函数之一,该构造函数将origin初始化为originOne。同样,构造函数将width设置为 100,将height设置为 200.现在有两个对同一个Point object的引用-一个对象可以对其具有多个引用,如下图所示:

现在,矩形的原点变量也指向 Point。

下面的代码行调用Rectangle构造函数,该构造函数需要两个整数参数,它们提供widthheight的初始值。如果检查构造函数中的代码,您将看到它创建了一个新的Point对象,该对象的xy值初始化为 0:

Rectangle rectTwo = new Rectangle(50, 100);

以下语句中使用的Rectangle构造函数不带任何参数,因此称为无参数构造函数

Rectangle rect = new Rectangle();

所有类都有至少一个构造函数。如果一个类没有显式声明任何类,则 Java 编译器会自动提供一个无参数的构造函数,称为* default 构造函数*。此默认构造函数调用类父级的无参数构造函数,如果该类没有其他父级,则调用Object构造函数。如果父级没有构造函数(Object确实有一个构造函数),则编译器将拒绝该程序。