本教程适用于JDK 8。本页面中描述的示例和实践不会利用后续版本中引入的改进,并且可能使用不再可用的技术。
请参阅Java语言更改,了解Java SE 9及以后版本中更新的语言特性的摘要。
请参阅JDK发行说明,了解所有JDK版本的新功能、增强功能以及已删除或已弃用选项的信息。
如你所知,一个类提供了对象的蓝图;你可以从一个类创建一个对象。以下代码取自CreateObjectDemo
程序,每个语句都创建一个对象并将其赋值给一个变量:
Point originOne = new Point(23, 94); Rectangle rectOne = new Rectangle(originOne, 100, 200); Rectangle rectTwo = new Rectangle(50, 100);
第一行创建了一个Point
类的对象,而第二行和第三行分别创建了一个Rectangle
类的对象。
这些语句中的每个部分都有三个部分(下面会详细讨论):
之前,你学到的是声明一个变量的方式:
类型 名称;
这样通知编译器,你将使用名称引用类型为类型的数据。对于基本类型的变量,这个声明还会为变量保留适当大小的内存空间。
你也可以在单独的一行上声明一个引用变量。例如:
Point originOne;
如果你这样声明originOne
,它的值将在实际创建并赋值给它之前是未确定的。仅仅声明一个引用变量并不会创建一个对象。为此,你需要使用new
操作符,如下一节所述。在使用变量之前,你必须将一个对象赋值给originOne
。否则,将会得到编译器错误。
处于这种状态的变量,当前没有引用任何对象,可以如下图所示表示(变量名originOne
加上一个指向空的引用):
new操作符通过为新对象分配内存并返回对该内存的引用来实例化一个类。 new操作符还会调用对象的构造函数。
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; //构造函数 public Point(int a, int b) { x = a; y = b; } }
这个类包含一个构造函数。你可以通过它的声明来识别构造函数,它使用与类相同的名称,并且没有返回类型。在Point类中的构造函数接受两个整数参数,如代码(int a, int b)所声明的那样。下面的语句为这些参数提供了23和94作为值:
Point originOne = new Point(23, 94);
执行这个语句的结果可以在下图中说明:
这是Rectangle类的代码,其中包含四个构造函数:
public class Rectangle { public int width = 0; public int height = 0; public Point origin; // 四个构造函数 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; } // 一个用于移动矩形的方法 public void move(int x, int y) { origin.x = x; origin.y = y; } // 一个计算矩形面积的方法 public int getArea() { return width * height; } }
每个构造函数都可以使用基本类型和引用类型提供矩形的原点、宽度和高度的初始值。如果一个类有多个构造函数,它们必须具有不同的签名。Java编译器根据参数的数量和类型来区分构造函数。当Java编译器遇到以下代码时,它知道调用需要一个Point参数和两个整数参数的Rectangle类的构造函数:
Rectangle rectOne = new Rectangle(originOne, 100, 200);
这调用了一个Rectangle类的构造函数,将origin初始化为originOne。此外,构造函数将width设置为100,height设置为200。现在有两个引用指向同一个Point对象-一个对象可以有多个引用,如下图所示:
下面的代码调用了需要两个整数参数的Rectangle构造函数,这些参数提供了width和height的初始值。如果你检查构造函数内的代码,你会发现它创建了一个新的Point对象,其x和y值被初始化为0:
Rectangle rectTwo = new Rectangle(50, 100);
下面的语句中使用的Rectangle构造函数不接受任何参数,因此被称为无参构造函数:
Rectangle rect = new Rectangle();
所有的类至少有一个构造函数。如果一个类没有显式声明任何构造函数,Java编译器会自动提供一个无参构造函数,称为默认构造函数。这个默认构造函数调用了类父类的无参构造函数,或者如果类没有其他父类的话,调用了Object类的构造函数。如果父类没有构造函数(Object类有一个构造函数),编译器会拒绝该程序。