和静态方法一样,我们也需要使用Java的类(class )实现抽象数据类型并将所有代码放入一个和类名相同并带有java扩展名的文件中。文件的第一部分语句会定义表示数据类型的值的实例变量。它们之后是实现对数据类型的值的操作的构造函数和实例方法。实例方法可以是公共的或是私有的(用于辅助计算,用例无法使用)。一个数据类型的定义中可能含有多个构造函数,而且也可能含有静态方法,特别是单元测试用例main(),它通常在调试和测试中很实用。作为第一个例子,我们来学习1.2.1.1节定义的Counter抽象数据类型的实现。它的完整实现(带有注释)如下所示:
public class Counter{ //类名
//实例变量
private final String name;
private int count;
//构造函数
public Counter(String id){
name=id;
}
//实例方法
public void increment()(
count++;
}
//实例方法
public int tally(){
return count;
}
//实例方法
public String toString(){
return count +" "+ name; //实例变量名
}
//测试用例
public static void main(String[] args){
//创建并初始化对象
Counter heads = new Counter("heads") ;
Counter tails = new Counter("tails");
heads.increment();
heads.increment();
tails. increment();
//自动调用toString()方法
System.out.println(heads+" "+tails);
}
}
private int count;
private final String name;
要定义数据类型的值(即每个对象的状态) ,我们需要声明实例变量,声明的方式和局部变量差不多。实例变量和你所熟悉的静态方法或是某个代码段中的局部变量最关键的区别在于:每时刻每个局部变量只会有一个值,但每个实例变量则对应着无数值(数据类型的每个实例对象都会有一个)。
这并不会产生二义性,因为我们在访问实例变量时都需要通过一个对象——我们访问的是这个对象的值。同样,每个实例变量的声明都需要一个可见性修饰符。在抽象数据类型的实现中,我们会使用private,也就是使用Java语言的机制来保证向使用者隐藏抽象数据类型中的数据表示。如果该值在初始化之后不应该再被改变,我们也会使用final。Counter 类型含有两个实例变量,一个String类型的值name和一个 int类型的值count。
每个Java类都至少含有一个构造函数以创建一个对象的标识。 构造函数类似于一个静态方法, 但它能够直接访问实例变量且没有返回值。一般来说, 构造函数的作用是初始化实例变量。每个构造函数都将创建一个对象并向调用者返回一个该对象的引用。构造函数的名称总是和类名相同。我们可以和重载方法一样重载这个名称并定义签名不同的多个构造函数。如果没有定义构造函数,类将会隐式定义一个默认情况下不接受任何参数的构造函数并将所有实例变量初始化为默认值。原始数字类型的实例变量默认值为0,布尔类型变量为false,引用类型变量为null。我们可以在声明语句中初始化这些实例变量并改变这些默认值。当用例使用关键字new时,Java 会自动触发一个构造函数。 重载构造函数一般用于将实例变量由默认值初始化为用例提供的值。例如,Counter 类型有个接受一个参
数的构造函数,它将实例变量name初始化为由参数给定的值(实例变量count仍将被初始化为默认值0)。
//public:可见性修饰符;Counter:构造函数名称(和类名相同);String id:参数变量
public Counter (String id){
name=id;
}
//初始化实例变量的代码,(count将会被初始化为默认值0)
实现数据类型的实例方法(即每个对象的行为)的代码和实现静态方法(函数)的代码完全相同。每个实例方法都有一一个返回值类型、一个签名(它指定了方法名、返回值类型和所有参数变量的名称)和一个主体(它由一系列语句组成,包括一个返 回语句来将一个返回类型的值传递给调用者)。当调用者触发了一个方法时,方法的参数均会被初始化为调用者所提供的值,方法的语句会被执行,直到得到一个返回值并且将该值返回给调用者。它的效果就好像调用者代码中的丽数调用被替换为了这个返回值。实例方法的所有这些行为都和静态方法相同,只有一点关键的不同:它们可以访问并操作实例变量。如何指定我们希望使用的对象的实例变量?就是在一个实例方法中对变量的引用指的是该方法的变量中的值。
//public:可见性修饰符;void:返回值类型;increment():方法名
public void increment(){
Count++; //实例变量名
}
总的来说,我们在实现实例方法的Java代码中使用了三种变量:
? 1.参数变量;
? 2.局部变量;
? 3.实例变量。
在静态方法中前两者的用法没有变化:方法的签名定义了参数变量,在方法被调用时参数方法会被初始化为调用者提供的值;局部变量的声明和初始化都在方法的主体中。参数变量的作用城是整个方法;局部变量的作用城是当前代码段中它的定义之后的所有语句。实例变量则完全不同 :它们为该类的对象保存了数据类型的值,它们的作用城是整个类(如果出现二义性,可以使用this前缀来区别实例变量)。
public class Example{ //实例变量
private int var;
...
private void method1(){
int var; //局部变量
... var ... //调用的是局部变量
... this.var ... //调用实例变量
}
private void method2(){
... var ... //调用实例变量
}
}