# 创建对象

> 原文： [https://docs.oracle.com/javase/tutorial/java/javaOO/objectcreation.html](https://docs.oracle.com/javase/tutorial/java/javaOO/objectcreation.html)

如您所知，一个类提供了对象的蓝图;你从一个类创建一个对象。从 [`CreateObjectDemo`](examples/CreateObjectDemo.java) 程序中获取的以下每个语句都会创建一个对象并将其分配给变量：

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

```

第一行创建 [`Point`](examples/Point.java) 类的对象，第二行和第三行分别创建 [`Rectangle`](examples/Rectangle.java) 类的对象。

这些陈述中的每一个都有三个部分（下面将详细讨论）：

1.  **声明**： **bold** 中设置的代码都是将变量名称与对象类型相关联的变量声明。
2.  **实例化**： `new` 关键字是一个创建对象的 Java 运算符。
3.  **初始化**： `new` 运算符后面是对构造函数的调用，该构造函数初始化新对象。

## 声明变量以引用对象

以前，您了解到要声明变量，您可以写：

```
type name;

```

这通知编译器您将使用 _ 名称 _ 来引用类型为 _ 类型 _ 的数据。对于原始变量，此声明还为变量保留适当的内存量。

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

```
Point originOne;

```

如果您像这样声明`originOne`，则在实际创建并分配对象之前，其值将不确定。简单地声明引用变量不会创建对象。为此，您需要使用`new`运算符，如下一节所述。在代码中使用对象之前，必须将对象分配给`originOne`。否则，您将收到编译器错误。

此状态中的变量（当前不引用任何对象）可以如下所示（变量名称，`originOne`，加上指向空的引用）：

<center>![originOne is null.](img/b097c2585db5a8efc2db67c9b863e7fe.jpg)</center>

## 实例化一个类

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

* * *

**Note:** The phrase "instantiating a class" means the same thing as "creating an object." When you create an object, you are creating an "instance" of a class, therefore "instantiating" a class.

* * *

`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);

```

执行此语句的结果可以在下图中说明：

<center>![originOne now points to a Point object.](img/fb5cf391b552952cb2fd63ee096af3bf.jpg)</center>

这是 `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 对象`的引用 - 对象可以有多个引用，如下图所示：

<center>![Now the rectangle's origin variable also points to the Point.](img/60f2969e1c11172a36bb4aaceff166c1.jpg)</center>

以下代码行调用`Rectangle`构造函数，该构造函数需要两个整数参数，这些参数提供 `width` 和 `height` 的初始值。如果检查构造函数中的代码，您将看到它创建了一个新的 `Point` 对象，其 `x` 和 `y` 值初始化为 0：

```
Rectangle rectTwo = new Rectangle(50, 100);

```

以下语句中使用的 `Rectangle` 构造函数不带任何参数，因此它被称为 _ 无参数构造函数 _：

```
Rectangle rect = new Rectangle();

```

所有类至少有一个构造函数。如果类没有显式声明任何类，则 Java 编译器会自动提供一个无参构造函数，称为 _ 默认构造函数 _。此默认构造函数调用类父无参数构造函数，如果类没有其他父类，则调用`Object`构造函数。如果父项没有构造函数（`Object`确实有一个），编译器将拒绝该程序。