JAVA程序员必读:基础篇类和继承

来源:互联网 发布:c语言 日期间隔 编辑:程序博客网 时间:2024/05/16 12:52
基础篇类和继承

这节教程将开始讨论对象的生命周期。包括怎样创建对象、怎样使用它以及在不使用它的时候将它从系统中清除。下面一个一个介绍:

对象的生命周期

  在这一小节中你可以学到怎样创建和使用任何类型的对象,还讨论了当对象不再需要的时候系统怎样清除对象的。

  典型的JAVA程序创建对象,对象之间的交互是通过发送消息来实现的。通过这些对象的交互,JAVA程序可以执行一个GUI、运行一个动画或者通过网络发送和接收信息。一旦对象已经完成了任务,它就被作为无用信息被回收,它的资源可以由其它对象回收利用。

  以下是一个小的例子程CreateObjectDemo,它创建三个对象:一个是Point对象和两个Rectange对象,你需要这三个源程序才可以编译这个程序:

public class CreateObjectDemo {

public static void main(String[] args) {

//创建一个Point对象和两个Rectangle对象

Point origin_one = new Point(23, 94);

Rectangle rect_one = new Rectangle(origin_one, 100, 200);

Rectangle rect_two = new Rectangle(50, 100);

// 显示rect_one的宽、高以及面积

System.out.println("Width of rect_one: " + rect_one.width);

System.out.println("Height of rect_one: " + rect_one.height);

System.out.println("Area of rect_one: " + rect_one.area());

// 设置rect_two的位置

rect_two.origin = origin_one;

// 显示rect_two的位置

System.out.println("X Position of rect_two: " + rect_two.origin.x);

System.out.println("Y Position of rect_two: " + rect_two.origin.y);

// 移动rect_two并且显示它的新位置

rect_two.move(40, 72);

System.out.println("X Position of rect_two: " + rect_two.origin.x);

System.out.println("Y Position of rect_two: " + rect_two.origin.y);

}

}

  一旦创建了对象,程序就可以操作对象并将它们有关的一些信息显示出来,以下是这个程序的输出结果:

Width of rect_one: 100

Height of rect_one: 200

Area of rect_one: 20000

X Position of rect_two: 23

Y Position of rect_two: 94

X Position of rect_two: 40

Y Position of rect_two: 72

  这一节使用这个例子来在程序中描述对象的生命周期。从这你可以学到怎样编写代码来创建、使用对象以及系统怎样将它从内存中清除的。

对象的生命周期

下面主要分成几部分来讨论:

1. 创建对象

  1. 使用对象
  2. 清除没有使用的对象

2.1 创建对象

众所周知,可以从类来创建对象。下面的几条语句都是用来创建对象的,它们都是来自上面程序CreateObjectDemo程序:

Point origin_one = new Point(23, 94);

Rectangle rect_one = new Rectangle(origin_one, 100, 200);

Rectangle rect_two = new Rectangle(50, 100);

上面第一条语句从Point类创建了一个对象,而第二条和第三条语句是从Rectangle类众创建了对象。但是每条语句都有三部分组成:

1. 声明:Point origin_oneRectangle rect_one以及Rectangle rect_two都是变量的声明,它们的格式是类型后加变量名。当你创建一个对象的时候,你不必声明一个变量来引用它。然而,变量生命经常出现在创建对象代码的相同行上。

  1. 实例化:new是JAVA运算符,它可以创建新的对象并且为对象分配了内存空间。
  2. 初始化:new运算符后跟着一个构造函数的调用。比如Point(23,94)就是一个Point类的构造函数的调用。这个构造函数初始化了这个新对象。

下页也对这几个部分逐个介绍:

2.1.1 声明一个变量来引用对象

  从前面的教程,你应该知道了如何声明一个变量了,你可以这样来编写:

type name

其中type是数据类型,而name是变量名。

  除了原始类型(比如intboolean),JAVA平台还直接提供了类和接口也是数据类型。这样为了声明一个变量来引用对象,你可以使用类或者接口的名字作为变量的类型。下面的例程使用了PointRectangle类作为类型来声明变量:

Point origin_one = new Point(23, 94);

Rectangle rect_one = new Rectangle(origin_one, 100, 200);

Rectangle rect_two = new Rectangle(50, 100);

  声明没有创建新对象。Point origin_one代码没有一个新的Point对象,它只是声明一个变量orgin_one,它将用来引用Point对象。这个引用暂时是空的直到被赋值了。一个空的引用就是一个NULL引用。

2.1.2 实例化对象

  为了创建一个对象你必须用new来实例化它。New运算符是通过为新对象分配内存来实例化一个类的。这个new运算符需要一个后缀参数,即构造函数的一个调用。构造函数的名字提供了要初始化类的名字。构造函数初始化了新的对象。

New运算符号返回一个引用给它创建的对象的。通常,这个引用被赋值为适当类型的变量。

2.1.3 初始化对象

  以下是Point类的代码:

public class Point {

public int x = 0;

public int y = 0;

//一个构造函数

public Point(int x, int y) {

this.x = x;

this.y = y;

}

}

 这个类包含了一个构造函数。你可以识别这个构造函数因为它跟类的名字是相同名字的,它没有任何的返回类型。这个在Point类中的构造函数有两个整型参数,它是由代码(int x, int y)来定义的。下面的整数2394就是这个参数的数值:

Point origin_one = new Point(23, 94);

2.1.3 初始化对象

下面是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) {

this(new Point(0, 0), w, h);

}

public Rectangle(Point p, int w, int h) {

origin = p;

width = w;

height = h;

}

//用于移动rectangle的方法

public void move(int x, int y) {

origin.x = x;

origin.y = y;

}

//用于计算矩形面积的方法

public int area() {

return width * height;

}

}

  每一个构造函数可以让你为矩形的各个方法提供初始数值,你可以设置矩形的原点、宽度和高度。如果一个类中有多个构造函数,它们的名字都是相同的只是它们有不同类型的参数或者不同数目的参数。JAVA平台可以根据参数的不同数目和类型类来区分构造函数。当JAVA平台遇到的代码的时候,它就调用在Rectangle类中的构造函数,这个函数需要一个Point参数以及两个整型参数:

Rectangle rect_one = new Rectangle(origin_one, 100, 200);

  这个调用初始化了矩形的原点(orgin_one)。代码也设置了矩形的宽度(100)和高度(200)。

2.1.3 初始化对象

  多个引用可以引用相同的对象。下面的代码行调用了需要两个整型参数的构造函数,它为宽度和高度提供了初始化数值。如果你仔细看看这个代码,你会发现它创建一个Point对象,它的xy数值被初始化为0

下面的Rectangle构造函数没有任何参数:

Rectangle rect = new Rectangle();

  如果一个类没有显性声明任何构造函数,JAVA平台自动提供一个没有参数的构造函数,这是一个缺省的构造函数,它没有完成任何事情。这样,所有的类就至少有一个构造函数。

2.2 使用对象

  一旦你创建了一个对象,你可能想使用它来做一些事情。你可能从它得到一些信息,或者想改变它的状态或者让它来完成一些动作。对象允许你做以下两件事情:

1. 操作或者检查它的变量。

  1. 调用它的方法。

2.2.1 引用对象的变量

下面是引用对象变量的基本形式,它是使用了有条件的名字即长名字:

objectReference.variableName

  当实例变量处在作用域内的时候,你可以为实例变量使用一个简单的名字,也就是说,在对象类的代码中。处在对象类外面的代码必须使用有条件的名字。比如,在CreateObjectDemo类中的代码处在类Rectangle类代码的外面。所以为了引用Rectangle对象rect_oneoriginwidthheight变量,CreateObjectDemo必须相应使用rect_one.originrect_one.widthrect_one.height。这个程序使用了rect_onewidthheight

System.out.println("Width of rect_one: " + rect_one.width);

System.out.println("Height of rect_one: " + rect_one.height);

  如果直接使用在CreateObjectDemo类中的变量widthheight,那就将产生一个编译错误。在后面,程序还将使用类似的代码来显示关于rect_two的信息。相同类型的对象将有相同实例变量的副本。这样,每一个Rectangle对象就都有变量originwidthheight了。当你通过对象引用来访问实例变量的时候,你就引用了特定对象的变量。在CreateObjectDemo程序有两个对象rect_onerect_two,它们有不同的originwidthheight变量:

  对象的长文件名的第一部分是对象引用,它必须是一个对象的引用。这里你可以使用引用变量的名字,或者你可以使用任何的表达式来返回一个对象引用。重新调用这个new运算符可以返回一个对象的引用。这样你可以使用从new返回的数值来访问一个新的对象变量:

int height = new Rectangle().height;

  这个语句创建了一个新的Rectangle对象并且得到它的height(高度)。从本质上讲,这条语句计算了Rectangle缺省的高度。这里注意,在这条语句被执行后,程序不再有创建了的Rectangle的引用,因为程序不再在变量中存储这个引用。对象就被取消引用,而它的资源可以JAVA平台重新使用。

2.2.2 关于变量访问

  利用其它对象和类对对象变量直接的操作是不允许的,因为有可能为变量设置的数值没有任何的意义。比如,我们使用前面教程中的Rectangle类,你可以创建一个矩形,它的widthheight都是负的,但是它是没有意义的。

  较好的做法是:不采用直接对变量进行操作,类提供一些方法,其它的对象可以通过这些方法来检查或者改变变量。这些方法要确保变量的数值是有意义的。这样,Rectangle类将提供setWidthsetHeightgetWidth以及getHeight方法来设置或者获得宽度和高度。这些用于设置变量的方法将在调用者试图将widthheight设置为负数的时候汇报一个错误。使用方法而不使用直接变量访问的好处还有:类可以改变变量的类型和名字来存储widthheight而没有影响它的客户程序。

  但是,在实际情况下,有时允许对对象变量直接访问。比如,通过定义Point类和Rectangle类为public,它们都允许对它们的成员变量自由访问。

JAVA编程语言提供了一个反问控制机制,凭它,类可以决定什么其它的类可以直接访问它的变量。如果其它对象对类直接操作可能导致无意义的话,类可以保护变量。改变这些变量应该利用方法调用来控制。如果类授权访问给它的变量,你可以检查和改变这些变量而但不能造成不利的效果。

2.2.2 调用对象的方法

  同样你可以使用有限制的名字(长名字)来调用对象的方法。有限制的名字的格式是:在对象引用的后面加上点(.)再跟着方法的名字,即对象引用.方法名字。同样你还可以利用圆括号()来为方法提供参数。如果方法不需要任何参数就留空它:

objectReference.methodName(argumentList);

or

objectReference.methodName();

Rectangle类有两个方法:areamove,即计算矩形的面积和改变矩形的原点。这里是CreateObjectDemo代码,它调用这两个方法:

System.out.println("Area of rect_one: " + rect_one.area());

...

rect_two.move(40, 72);

  上面的第一条语句调用rect_onearea方法并显示结果。第二条语句是移动rect_two,因为move方法为对象的原点坐标xy赋了新值。其中objectReference 必须是一个对象的引用。你可以使用一个变量名字,而且你也可以使用任何表达式来返回对象的引用。而new运算符返回一个对象的引用,因此你可以使用从new返回的数值来调用一个新的对象方法:

new Rectangle(100, 50).area()

  表达式new Rectangle(100,50)返回一个对象引用,它是引用一个Rectangle对象。上面已经提到,你可以使用点符号(.)来调用新的Rectangle的面积方法以计算新矩形的面积。另外方法area也返回一个数值。对于这些返回数值的方法,你可以使用在表达式中使用方法调用。你可以指定返回的数值给变量,参见如下的例子:

int areaOfRectangle = new Rectangle(100, 50).area();

  这里要提醒一下,在特定对象中调用一个方法跟发送一个信息给对象是相同的。

2.2.3 关于方法访问

  在PointRectangle类中的方法都被声明为public,因此它们可以被任何其它的类所访问。有时,类需要限制访问它的方法。比如,一个类可能可能有一个方法,只有它的子类才能调用它。类可以在它用于控制访问它的变量的时候,使用相同的机制来对它的方法进行控制访问。

2.3 清除没有使用的对象

  有些面向对象语言需要保持对所有对象的跟踪,所以需要在对象不再使用的使用来将它从内存中清除。管理内存是一个很沉闷的事情而且容易出错。JAVA平台允许你创建任意个对象(当然会受到系统的限制),所以你也不必要老是要将它清除。JAVA是在当对象不再使用的使用被清除的。这个过程就是所谓的“垃圾收集”。

  当对象不再有引用的时候,对象就会被清除,即作为垃圾收集的对象。保留在变量中的引用通常在变量超出作用域的时候被清除。或者,你可以通过设置变量为NULL来清除对象引用。这里注意,程序中同一个对象可以有多个引用,对象的所有引用必须在对象被作为垃圾收集对象清除之前清除。

下面讲讲垃圾收集器:

JAVA有一个立即收集器,它周期性地讲不再被引用的对象从内存中清除。这个垃圾收集器是自动执行的,虽然有时候你可能想通过调用系统类的gc方法来显性运行垃圾收集程序。比如,你可能想在创建大量垃圾代码之后或者在需要大量内存代码之前运行垃圾收集器。垃圾收集器从内存中清除不再被引用的对象的机制已经被要到了VB.netC#中去了。

最后介绍对象finalize方法:

  在一个对象得到垃圾收集之前,垃圾收集器在对象自己调用对象的finalize方法之后给对象一个机会来从内存中清除掉。

原创粉丝点击