正文  软件开发 > java编程技术 >

对象和简单数据对象 JAVA程序员必读基础篇

对象和简单数据对象  这节教程将开始讨论对象的生命周期。包括怎样创建对象、怎样使用它以及在不使用它的时候将它从系统中清除。下面一个一个介绍:  4 1 对象的生命周期  在这一小节中你可以学到怎样创建 ...

对象和简单数据对象
  这节教程将开始讨论对象的生命周期。包括怎样创建对象、怎样使用它以及在不使用它的时候将它从系统中清除。下面一个一个介绍:
  4.1 对象的生命周期
  在这一小节中你可以学到怎样创建和使用任何类型的对象,还讨论了当对象不再需要的时候系统怎样清除对象的。
  典型的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
  这一节使用这个例子来在程序中描述对象的生命周期。从这你可以学到怎样编写代码来创建、使用对象以及系统怎样将它从内存中清除的。
   下面主要分成几部分来讨论:
  创建对象 
  使用对象 
  清除没有使用的对象 
  4.1.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类众创建了对象。但是每条语句都有三部分组成: 
  声明:Point origin_one、Rectangle rect_one以及Rectangle rect_two都是变量的声明,它们的格式是类型后加变量名。当你创建一个对象的时候,你不必声明一个变量来引用它。然而,变量生命经常出现在创建对象代码的相同行上。 
  实例化:new是JAVA运算符,它可以创建新的对象并且为对象分配了内存空间。 
  初始化:new运算符后跟着一个构造函数的调用。比如 Point(23,94)就是一个Point类的构造函数的调用。这个构造函数初始化了这个新对象。 
  4.1.1.1 声明一个变量来引用对象 
  从前面的教程,你应该知道了如何声明一个变量了,你可以这样来编写: 
  type name
  其中type是数据类型,而name是变量名。
  除了原始类型(比如int和boolean),JAVA平台还直接提供了类和接口也是数据类型。这样为了声明一个变量来引用对象,你可以使用类或者接口的名字作为变量的类型。下面的例程使用了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);
  声明没有创建新对象。Point origin_one代码没有一个新的Point对象,它只是声明一个变量orgin_one,它将用来引用Point对象。这个引用暂时是空的直到被赋值了。一个空的引用就是一个NULL引用。
  4.1.1.2 实例化对象
  为了创建一个对象你必须用new来实例化它。New运算符是通过为新对象分配内存来实例化一个类的。这个new运算符需要一个后缀参数,即构造函数的一个调用。构造函数的名字提供了要初始化类的名字。构造函数初始化了新的对象。
  New运算符号返回一个引用给它创建的对象的。通常,这个引用被赋值为适当类型的变量。
  4.1.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)来定义的。下面的整数23和94就是这个参数的数值:
  Point origin_one = new Point(23, 94);
  4.1.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)。
  多个引用可以引用相同的对象。下面的代码行调用了需要两个整型参数的构造函数,它为宽度和高度提供了初始化数值。如果你仔细看看这个代码,你会发现它创建一个Point对象,它的x和y数值被初始化为0。 
  下面的Rectangle构造函数没有任何参数: 
  Rectangle rect = new Rectangle();
  如果一个类没有显性声明任何构造函数,JAVA平台自动提供一个没有参数的构造函数,这是一个缺省的构造函数,它没有完成任何事情。这样,所有的类就至少有一个构造函数。
  4.1.2 使用对象
  一旦你创建了一个对象,你可能想使用它来做一些事情。你可能从它得到一些信息,或者想改变它的状态或者让它来完成一些动作。对象允许你做以下两件事情: 
  操作或者检查它的变量。 
  调用它的方法。 
  4.1.2.1 引用对象的变量
  下面是引用对象变量的基本形式,它是使用了有条件的名字即长名字:
  objectReference.variableName
  当实例变量处在作用域内的时候,你可以为实例变量使用一个简单的名字,也就是说,在对象类的代码中。处在对象类外面的代码必须使用有条件的名字。比如,在CreateObjectDemo类中的代码处在类Rectangle类代码的外面。所以为了引用Rectangle对象rect_one的origin、width和height变量,CreateObjectDemo必须相应使用rect_one.origin、rect_one.width和rect_one.height。这个程序使用了rect_one的width和height:
  System.out.println("Width of rect_one: " + rect_one.width);
  System.out.println("Height of rect_one: " + rect_one.height);
  如果直接使用在CreateObjectDemo类中的变量width和height,那就将产生一个编译错误。在后面,程序还将使用类似的代码来显示关于rect_two的信息。相同类型的对象将有相同实例变量的副本。这样,每一个Rectangle对象就都有变量origin、width和height了。当你通过对象引用来访问实例变量的时候,你就引用了特定对象的变量。在CreateObjectDemo程序有两个对象rect_one和rect_two,它们有不同的origin、width和height变量: 
  对象的长文件名的第一部分是对象引用,它必须是一个对象的引用。这里你可以使用引用变量的名字,或者你可以使用任何的表达式来返回一个对象引用。重新调用这个new运算符可以返回一个对象的引用。这样你可以使用从new返回的数值来访问一个新的对象变量: 
  int height = new Rectangle().height;
  这个语句创建了一个新的Rectangl

4.3 数字
  为了处理数值类型,你可以使用Number类。这个Number类是所有在JAVA平台中所有数字类的父类。它的子类包括Float、Interger等等。 
  本节教程将讨论java.lang和它的子类中的Number类。特别地,这节教程要讨论为什么你需要这些类,并指出通用的方法和类变量,以及向你介绍如何将实例转换为字符串。
  此外,这节教程还讨论你需要的其它类来处理数字。比如,如果你需要以某个特殊格式来显示数字的时候,你可以使用在java.test中的NumberFormat和DecimalFormat类来格式化它。同时,java.lang中的Math包含了类方法来执行数学函数。这个类还有用于三角函数、指数函数等等的方法。 如图18所示:
    
  (图18)
  数字类包含: 
  Number :这个抽象类Number是Byte、Double、Float、Integer、Long和Short的父类。Number的子类必须提供将数值转换为byte、double、float、int、long以及short的方法。 
  Byte:这个类是Number的子类,它是用于字节数值的标准wrapper。 
  Double:这个Double类在对象中包装了原始类型double。Double类的对象包含单一类型(double)的对象。另外,这个类提供了几个用于将double转换为String或者将String转换为double的方法。 
  Float :这个Float类在对象中包装了原始类型Float。Float类的对象包含单一类型(Float)的对象。另外,这个类提供了几个用于将Float转换为String或者将String转换为Float的方法。 
  Integer:这个Integer类在对象中包装了原始类型Integer。Integer类的对象包含单一类型(Integer)的对象。另外,这个类提供了几个用于将Integer转换为String或者将String转换为Integer的方法。 
  Long :这个Long类在对象中包装了原始类型Long。Long类的对象包含单一类型(Long)的对象。另外,这个类提供了几个用于将Long转换为String或者将String转换为Long的方法。 
  Short:这个类是用于short数值的标准wrapper。
  8. BigDecimal:不可变的、任意精度的有符号的十进制数字。BigDecimal包含了任意精度的整型数和非负的32位的整型数,BigDecimal 提供了用于基本算术运算、比较、格式转换等等的操作。这个BigDecimal类给了用户对舍入行为的完全控制,并且强迫用户为舍弃精度的操作显性指定一个舍入行为。基于这个目的有八种舍入模式。对BigDecimal有两种类型的操作:比例/舍入操作和十进制点移动操作。比例/舍入操作返回一个BigDecimal,它的数值大约或者精确地等于运算对象,但是它的数值范围要指定,也就是说,它们可以对它的数值最小的影响来增加或者减少数字的精度。十进制点移动操作(movePointLeft和movePointRight)返回一个由运算对象创建的BigDecima,它是通过在指定方向和指定距离来移动十进制点的。为了达到简短和清晰的目的,伪代码用在了BigDecimal方法的描述中。比如伪代码表达式(i j)就代表了“BigDecimal的数值是由BigDecimal i加上BigDecimal j的数值”。而伪代码表达式(i==j)代表“当且仅当BigDecimal i的数值与BigDecimal j相同的时候才为true”。其它的伪代码表达式也有类似的解释。 
  BigInteger:不可变任意精度的整型数。BigInteger为所有的Java原始整型操作以及所有在java.lang.Math中的相关方法提供相似的操作。另外BigInteger伪模数运算、GCD计算、位操作等等提供了运算。算术运算的语义模仿了定义在JAVA语言规范中的Java的整型算术运算。比如,如果除数为0就会导致ArithmeticException(算术异常)等等。所有在规范中的溢出都将被忽略,因为BigIntegers将尽量适应运算结果的需要。 而移位操作扩展了Java的移位操作,它允许负方向的移位。以负的位距来往右移就相当于往左移位。而无符号的右移运算符(>>>)这里就不再使用。 而按位逻辑操作跟Java的按位操作是相似的。比较运算执行有符号的整型比较,它跟Java的是相似的。 模数算术运算提供计算余数、执行乘幂等方法。这些方法总是返回一个非零的结果(介于0到-1之间)。为了简洁和清晰的目的,伪代码也用在BigInteger方法中。这个伪代码表达式(i j)代表了“等于BigInteger i加上BigInteger j的BigInteger数值”。而伪代码表达式(i==j)代表了“当且仅当BigInteger i等于BigInteger j的时候才返回true”。
  其它的数据类型: 
  Boolean :这个Boolean类在对象中包装了原始类型Boolean。Boolean类的对象包含单一类型(double)的对象。另外,这个类提供了几个用于将Boolean转换为String或者将String转换为Boolean的方法。
  Character :这个Character类在对象中包装了原始类型Character。Character类的对象包含单一类型(Character)的对象。另外,这个类提供了几个用于将字符由小写转换为大写或者由大写转换为小写的方法。
  Void:这个Void类是一个占位符类,它保留对代表原始JAVA类void的引用。 
  非基本算术类型Math:
  这个Math类包含了用于执行数值操作的方法,比如初步的指数、对数、平反根以及三角函数。 不象StrictMath类中的有些数值函数,这个Math类的所有函数不是定义为返回bit-for-bit相同的结果。这允许更好的执行,因为严格的再现情已经不需要了。 
  缺省地,许多Math函数简单代表了在StrictMath中的等价函数。代码发生器支持使用特殊平台的本地库或者微处理器指令以提供性能更高的Math函数实行。这样高性能的执行必须符合Math的规范。
  4.4 数组
  在任何的编程语言中,数组都是一个重要的数据结构。数组是一个固定长度的结构,它存储多个相同类型的数值。你可以在数组中集合相同类型的数值。数组直接被JAVA编程语言所支持,所以没有一个数组类。数组是一个Object类的一个不明显的扩展,所以你可以指定一个数组给一个类型定义为Object的变量。
  JAVA平台集合了它的类到功能包中。不是编写你自己的类,你可以使用有平台提供的类。这节教程中要讨论的绝大多数的类都是java.lang包的成员函数。所有java.lang中的类对你的程序都是有效的。
  数组的长度在数组创建的时候就已经确定。一旦创建以后,数组就有了固定长度的结构,如图19所示:
    
  图19)
  数组元素就是数组中的一个数值,可以通过数组中的位置来访问它。
  如果你想在一个结构中存储不同类型的数据,或者如果你需要一个长度可以动态改变的结构,可以使用Collection,比如Vector而不用数组。
  本教程中将讨论以下的几个方法:
  声明一个变量来引用一个数组 
  创建一个数组 
  访问数组元素 
  获得数组的大小 
  数组初始化程序 
  4.4.1 创建和使用数组合
  (1)声明一个变量来引用一个数组
  以下的代码是声明一个数组变量: 
  int[] anArray; // 声明整型的数组
  象声明其它类型的变量,一个数组声明有两个组件:数组的类型和数组的名字。数组的类型是这样来写的type[],其中type可以是float、boolean、Object、String等,而[]代表了这是一个数组。这里记住在数组中的所有元素都是相同类型的。上面的例程中使用了int[],所以数组anArray就将容纳整型数据了。以下是声明其它类型的数组: 
  float[] anArrayOfFloats;
  boolean[] anArrayOfBooleans;
  Object[] anArrayOfObjects;
  String[] anArrayOfStrings;
  就象声明其它类型的变量,声明数组变量也没有为数组元素分配任何内存。所以必须在引用数组之前被数组赋值
  (2)创建一个数组 
  你可以使用JAVA的new运算符来创建一个数组。下面的语句是为10个整型元素分配一个数组内存: 
  anArray = new int[10]; // create an array of integers
  总得说来,当创建数组的时候,你可以使用new操作符,后面跟着数组元素的数据类型然后就是用方括号[和]括起来的元素的数目,格式如下所示: 
  new elementType[arraySize]
  如果在上面的例程中new语句没有的话,编译器将打印除一个如下的错误是的编译发生错误: 
  ArrayDemo.java:4: Variable anArray may not have been initialized(变量anArray 可能还没有初始化。)
  (3)访问数组元素 
  既然已经给数组分配了内存,我们来为数组元素赋值吧: 
  for (int i = 0; i < anArray.length; i++) {
  anArray[i] = i;
  System.out.print(anArray[i] + " ");
  }
  这部分的代码给出了怎样引用一个数组元素,或者示为它赋予一个数值,或者访问数值。在方括号之间的数值指示了要访问的元素的索引。在JAVA中,数组的索引是从0开始的并且以-1结束。 
  (4)获得数组的大小 
  为了获得数组的大小,你可以使用下面的代码:
  arrayname.length
  这里还提醒一下:JAVA的新手可能会在length后面加一个圆括号(和)。这样是否错误的,因为length不是一个方法。Length是由JAVA平台为所有数组提供的一个属性。
  在上面的例程中的for循环在anArray的每一个元素进行循环,并给每个元素赋值。这个for循环使用了anArray.length来决定什么时候终止循环。
  (5)数组初始化程序 
  JAVA编程语言为创建和初始化数组提供了简捷的语法。一下是这个语法的例子: 
  boolean[] answers = { true, false, true, true, false };
  数组的length(长度)是由大括号{和}之间的数值的数目决定的。
  4.4.2 对象的数组
  数组可以保留引用类型。你可以用创建原始类型数组的方法来创建这样一个数组。以下是一个小的程序ArrayOfStringsDemo,它创建了一个数组包含了三个String对象并且将这三个字符串以小写字母的形式打印出来: 
  public class ArrayOfStringsDemo {
  public static void