原文出自 http://www.cnblogs.com/ggjucheng/archive/2012/11/28/2793158.html
对象
一个典型的java程序会创建很多对象,就像你所知道的,这些对象通过方法调用进行交互。通过对象交互,程序可以完成很多任务,例如实现图形界面运行动画,通过网络发送或者接收信息。一个创建好的对象,当它完成任务时,它的资源也会被其他对象重复使用。
这里有一个小程序,叫CreateObjectDemo
,它创建三个对象:一个Point对象和两个Rectangle
对象。编译这个程序,我们需要三个源码文件。
public class CreateObjectDemo { public static void main(String[] args) { // Declare and create a point object // and two rectangle objects. Point originOne = new Point(23, 94); Rectangle rectOne = new Rectangle(originOne, 100, 200); Rectangle rectTwo = new Rectangle(50, 100); // display rectOne's width, // height, and area System.out.println("Width of rectOne: " + rectOne.width); System.out.println("Height of rectOne: " + rectOne.height); System.out.println("Area of rectOne: " + rectOne.getArea()); // set rectTwo's position rectTwo.origin = originOne; // display rectTwo's position System.out.println("X Position of rectTwo: " + rectTwo.origin.x); System.out.println("Y Position of rectTwo: " + rectTwo.origin.y); // move rectTwo and display // its new position rectTwo.move(40, 72); System.out.println("X Position of rectTwo: " + rectTwo.origin.x); System.out.println("Y Position of rectTwo: " + rectTwo.origin.y); } }
这个程序创建对象,操控对象,并显示多个对象的信息,这里是输出:
Width of rectOne: 100 Height of rectOne: 200 Area of rectOne: 20000 X Position of rectTwo: 23 Y Position of rectTwo: 94 X Position of rectTwo: 40 Y Position of rectTwo: 72
以下三个部分用上面的例子,在一个程序中来描述一个对象的生命周期。从中你将学会如何编写代码,在自己的程序中创建和使用对象。您还将了解当对象生命周期结束时,系统会清理对象。
创建对象
正如你所知道的,一个类会为对象提供蓝图,你可以使用类创建对象。CreateObjectDemo
程序每一个语句都是创建对象并赋值给变量:
Point originOne = new Point(23, 94); Rectangle rectOne = new Rectangle(originOne, 100, 200); Rectangle rectTwo = new Rectangle(50, 100);
第一行创建了Pointer类的对象,第二行和第三行分别创建了Rectangle
类的对象。 每一个语句都有三个部分(细节如下):
1.声明:数据类型和变量名
2.实例化:new关键字是java操作符,用来创建对象。
3.初始化:new操作符紧跟着一个构造方法,用来初始化对象。
声明一个指向对象的变量
之前,我们学到,声明一个变量,会这么写:
type name;
这个通知编译器,你将会使用name指向类型为type的数据。如果是原生类型的变量,这个声明会为变量分配合适大小的内存。
你也可以在单行声明一个引用变量,例如:
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; //constructor 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; // 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编译器遇到下面的代码,它知道要调用参数为Pointer并紧跟两个整数的Pointer类的构造方法:
Rectangle rectOne = new Rectangle(originOne, 100, 200);
这个构造方法的调用,初始化rectOne 为originOne
。同样的,构造方法会把宽度设置为100,高度设置为200.现在这里有两个引用指向同一个Point对象----一个对象可以被多个引用指向,就像下图显示:
下面的代码调用Rectangle类参数为两个整数类型的构造方法,它会提供width和height的初始化值。如果检查构造方法的代码,你会看到里面会创建一个Point对象,属性x和y初始化为0:
Rectangle rectTwo = new Rectangle(50, 100);
下面的语句,Rectanglez构造方法没有任何参数,它称之为无参构造方法:
Rectangle rect = new Rectangle();
所有类至少有一个构造方法,如果类没有显式声明一个构造方法,java编译器会自动提供一个构造方法,称之为默认构造方法。默认构造方法调用父类的无参构造方法。如果父类没有构造法方法(Object类有一个构造方法),编译器会拒绝这个程序。
使用对象
当你创建对象后,你极有可能用它来做一些事情,你可能使用它的成员变量的值,改变它的成员变量的值,或者是调用它的方法完成某个任务。
引用对象的成员变量
对象成员变量是通过名字访问的,你必须使用一个明确的名字。
你可以在类里使用一个简单的名字。例如,我们可以在Rectangle
类添加一个语句,输出长度和高度:
System.out.println("Width and height are: " + width + ", " + height);
这个场景下,width
和height就是简单的名字。
在代码中,在类以外访问必须使用类的引用或者表达式,紧着一个.操作符,紧着一个简单的成员变量名,例如:
objectReference.fieldName
例子,CreateObjectDemo类的代码,是在Rectangle的外层,所以要引用对象名为rectOne的origin, width, and height这些成员变量,CreateObjectDemo类必须分别使用rectOne.origin, rectOne.width,rectOne.height.这个程序使用下面的名字显示rectOne对象的宽度和高度:
System.out.println("Width of rectOne: "
+ rectOne.width);
System.out.println("Height of rectOne: "
+ rectOne.height);
的在CreateObjectDemo类中的代码尝试使用简单的名称width 和height是没有任何意义 - 这些成员变量只存在对应的对象,这会导致 一个编译错误。
等下这个程序会使用相同的代码,显示rectTwo的信息。同一类型的多个对象,本身都有自己成员变量的拷贝。所以每一个Rectangle对象都有自己的成员变量origin, width, height.当你通过对象引用访问实例的成员变量时,你引用的就是对应的对象的成员变量了。两个对象rectOne 和rectTwo在CreateObjectDemo程序中都有自己的origin, width, height成员变量。
为了访问成员变量,你可以使用一个对象的命令引用,就像之前的例子,或者使用一个表达式返回一个对象引用。重新调用new操作符返回一个对象的引用。回想一下,new操作符会返回一个对象引用。所以你可以new返回的值,访问对象的成员变量:
int height = new Rectangle().height;
这个语句创建了Rectangle对象并理解获取它的高度。在本质上,这个语句获取了一个Rectangle的默认高度,但是这个语句执行后,这个程序没有任何 引用指向了创建的Rectangle对象。因为程序没有存储该引用。对象没有被引用,它的资源会被java虚拟机回收。
调用对象的方法
你可以通过对象引用调用对象的方法。你在对象引用添加.操作符,再追加方法的简明名字。当然,你需要在闭合的小括号内提供方法的参数。如果方法不要求任何参数,使用空的小括号。
objectReference.methodName(argumentList);
or:
objectReference.methodName();
Rectangle类有两个方法:getArea()计算长方形的面积,move()修改长方形的大小,CreateObjectDemo代码调用了以下两个方法:
System.out.println("Area of rectOne: " + rectOne.getArea());
...
rectTwo.move(40, 72);
第一个语句调用rectOne的getArea()方法,并显示结果。第二个语句调整rectTwo的大小,move()方法将对象的origin.x和origin.y重新赋新值。
和实例成员变量一样,objectReference必须是一个对象引用。您可以使用一个变量的名字,但你也可以使用任何返回一个对象引用的表达式。new操作符返回一个对象的引用,这样你就可以使用new的返回值调用新对象的方法:
new Rectangle(100, 50).getArea()
表达式new Rectangle(100, 50)返回一个对象引用,它指向了Rectangle对象。如图所示,你可以使用.符号来调用新的Rectangle的getArea()方法计算新创建的长方形形的面积。
一些方法,如getArea(), 返回一个值。针对方法的返回值,你可以在表达式中使用方法调用,把返回值赋值给变量,使用它来做条件判断,循环控制。下面的代码,把getArea()的返回值赋值给变量areaOfRectangle:
int areaOfRectangle = new Rectangle(100, 50).getArea();
记住,对一个对象调用方法,就像给对象发送消息。这个场景下,构造方法返回的rectangle对象引用并调用getArea()
垃圾回收器
一些面向对象的语言需要你跟踪创建的所有对象,当他们不需要时,您要显式地销毁他们时。显示管理内存是繁琐并容易出错的, Java平台允许您创建尽可能多的想要的对象(数量有限由你的系统的处理能力决定),你不必担心什么时候销毁对象。 Java运行时中删除不再被使用的对象,这个过程被称为“垃圾回收。
当对象没有任何引用时,它就符合垃圾收集器的回收对象了。引用一般保存在变量里,当变量离开了代码块的范围,就会销毁了。当然,你也可以把一个变量设置为null,显式删除一个对象引用。注意的是程序中,一个对象可以有多少引用,所有的引用删除了,这个对象才符合垃圾收集器的回收对象。
Java运行时环境有一个垃圾收集器,周期性地释放不再被引用的对象的内存。垃圾收集器会自动运行,由它本身决定运行的正确时间。