实例方法的意义在于操作数据类型中的值,因此Java语言提供了一种特别的机制来触发实例方法,它突出了实例方法和对象之间的联系。具体来说,我们调用一个实例方法的方式是先写出对象的变量名,紧接着是一个句点,然后是实例方法的名称,之后是0个或多个在括号中并由逗号分隔的参数。实例方法可能会改变数据类型中的值,也可能只是访问数据类型中的值。实例方法拥有静态方法的所有性质——参数按值传递,方法名可以被重载,方法可以有返回值,但它们还有一个特别的性质:方法的每次触发都是和一个对象相关的。
String header; //声明语句
heads= new Counter("heads"); //通过new关键字(触发构造函数),创建一个对象
heads.increment(); //通过语句(没有返回值),触发一个实例方法并改变对象的值
在用例中实例方法和静态方法的调用方式完全相同一可以通过语句( void方法)也可以通过表达式(有返回值的方法)。静态方法的主要作用是实现函数:非静态(实例) 方法的主要作用是实现数据类型的操作。两者都可能出现在用例代码中,但很容易就可以区分它们,因为静态方法调用的开头是类名(按习惯为大写),而非静态方法调用的开头总是对象名。
实例方法 | 静态方法 | |
---|---|---|
举例 | heads . incrementO | Math.sqrt(2.0) |
调用方式 | 对象名 | 类名 |
参数 | 对象的引用和方法的参数 | 方法的参数 |
主要作用 | 访问或改变对象的值 | 计算返回值 |
通过声明语句可以将变量名赋给对象,在代码中,我们不仅可以用该变量创建对象和调用实例方法,也可以像使用整数、浮点数和其他原始数据类型的变量一样使用它。要开发某种给定数据类型的用例,我们需要:
1.声明该类型的变量,以用来引用对象;
2.使用关键字new触发能够创建该类型的对象的一个构造函数;
3.使用变量名在语句或表达式中调用实例方法。
例如,下面用例代码中就使用了Counter类。它接受个命令行参数T并模拟N次掷硬币(它还调用了Random类)。除了这些直接用法外,我们可以和使用原始数据类型的变量一样使用和对象关联的变量:
1.赋值语句;
2.向方法传递对象或是从方法中返回对象;
3.创建并使用对象的数组。
public class Test{
public static void main(String[] args){
int N = Integer.parseInt(args[0]);
Counter heads = new Counter("heads");
Counter tails = new Counter("tails");
for(int t=0;t<N;t++){
if (Random. bernoulli(0.5))
heads.increment();
else tails.increment():
System.out.println(Cheads);
System.out.println(tails);
int d= heads. tally() - tails. tally();
System.out.println("delta:"+Math.abs(d));
}
}
使用引用类型的赋值语句将会创建该引用的一个副本。 赋值语句不会创建新的对象,而只是创建另一个指向某个已经存在的对象的引用。这种情况被称为别名:两个变量同时指向同一个对象。如果x和y是原始数据类型的变量,那么赋值语句x = y会将y的值复制到x中。对于引用类型,复制的是引用(而非实际的值)。如下例所示
Counter C1 = new Counter("ones");
c1.increment();
CounterC2 = c1;
c2. increment();
System.out.println(c1);
对于一般的toString()实现,这段代码将会打印出"2ones"。 改变一个对象的状态将会影响到所有和该对象的别名有关的代码。我们习惯于认为两个不同的原始数据类型的变量是相互独立的,但这种感觉对于引用类型的变量并不适用。
可以将对象作为参数传递给方法,这一般都能简化用例代码。 当我们调用一个需要参数的方法时,该动作的效果相当于java中的每个参数都出现了应该赋值语句的右侧,而参数名则在该赋值语句的左侧。也就是说,Java 将参数值的一个副本从调用端传递给了方法,这种方式称为按值传递。这种方式的一个重要后果是方法无法改变调用端变量的值。
也可以将对象作为方法的返回值。方法可以将它的参数对象返回,如下面的例子所示,也可以创建一个对象并返回它的引用。这非常重要,因为Java中的方法只能有一个返回值——有了对象我们的代码实际上就能返回多个值。
在Java中,所有非原始数据类型的值都是对象。也就是说,数组也是对象。和字符串一样,Java语言对于数组的某些操作有特殊的支持:声明、初始化和索引。和其他对象一样,当我们将数组传递给个方法或是将一个数组变量放在赋值语句的右侧时,我们都是在创建该数组引用的一个副本,而非数组的副本。我们能够重新安排数组的条目并修改数组的内容,如java.utils.Array. sort()等方法。
我们已经看到,数组元素可以是任意类型的数据:我们实现的main()方法的args[]参数就是一个String对象的数组。创建一个对象的数组需要以下两个步骤:
1.使用方括号语法调用数组的构造函数创建数组;
2.对于每个数组元素调用它的构造函数创建相应的对象。
运用数据抽象的思想编写代码(定义和使用数据类型,将数据类型的值封装在对象中)的方式称为面向对象编程。所以,数据类型指的是一组值和一组对值的操作的集合。我们会将数据类型实现在独立的Java类模块中并编写它们的用例。对象是能够存储任意该数据类型的值的实体,或数据类型的实例。对象有三大关键性质:状态、标识和行为。一个数据类型的实现所支持的操作如下。
1.创建对象(创造它的标识):使用new关键字触发构造函数并创建对象,初始化对象中的值并返回对它的引用。
2.操作对象中的值(控制对象的行为,可能会改变对象的状态) :使用和对象关联的变量调用实例方法来对对象中的值进行操作。
3.操作多个对象:创建对象的数组,像原始数据类型的值一样将它们传递给方法或是从方法中返回,只是变量关联的是对象的引用而非对象本身。