四、对象与类
4.1 面向对象程序设计概述
面向对象程序设计(OOP):不必关心对象的具体实现,只要能满足用户的需求即可。
4.1.1 类
类(class):即构造对象的模板或蓝图。由类构造对象的过程成为创建类的实例。
封装:从形式上看,封装即使将数据和行为组合在一个包里。实现封装的关键在于据对不能让类中的方法直接地访问其他类的实例域。
4.1.2 对象
要注意对象的三个主要的特性:
行为:可以对对象施加哪些方法?
状态:施加那些方法,对象如何响应?
标识:如何辨别具有相同行为与状态的不用对象?每个对象都有唯一身份
4.1.3 识别类
对于OOP初学者:要先从设计类开始,然后再往每个类中添加方法。
类:一些名词。比如商品(Item),订单(Order)等
方法:动词。比如商品被添加到订单中,订单的取消、支付等
4.1.4 类之间的关系
在类之间,最常见的关系为:
依赖:(uses-a)比如说,Order类要使用Account类,因为Order对象需要访问Account对象,查看其信用状态。但Account类就不需要Order类,这就是一个类依赖另一个类。
聚合:(has-a)一个Order对象中包含Item的对象
继承:(is-a)RushOrder类由Order类继承。
4.2 使用预定义类
4.2.1 对象与对象变量
在Java中,使用构造器(constructor)构造新实例。如Date类。
构造器的名字应该与类名相同,因此Date类的构造器名为Date。要想构造一个Date类,只需要在构造器钱前面加上new操作符。
一定要认识到:**一个对象变量并没有实际包含一个对象,而仅仅是引用一个对象。**例如:
Date deadline ;//这里只是定义一个对象变量
deadline = new Date();//初始化
4.3 用户自定义类
构造器与其他方法有一个重要的不同。构造器总是伴随着new操作符的执行被调用,而不能对一个已经存在的对象调用构造器来达到重新设置实例域的目的
构造器的特点:
- 构造器与类同名
- 每个类可以有一个以上的构造器
- 构造器参数可以有0、1、多个
- 构造器没有返回值
- 构造器总是伴随着new操作一起调用
4.3.9 final实例域
final修饰符大都应用于基本类型域,或者不可变类的域中的每个方法都不会改变其对象,这种类就是好不可变的类
4.4 静态域于静态方法
4.4.1 静态域
如果将域定义为static,每个类中只有一个这样的域,而每一个对象对于所有的实例与却都有自己的一份拷贝。
class Employee{
private static int nextId = 1;//每一个对象都会自己的id域,但这话类的所有实例都将共享一个nextId域,换句话说, 1000个Employee对象,有1000个id,但只有一个nextId
private int id;
...
}
但要注意,即使没有一个实例,静态域nextId也存在,它属于类,而不属于任何独立的对象。
4.4.2 静态常量
例如:Math类定义了静态常量
public class Math{
public static final double PI = 3.1415...
}
在程序中,我们就可以采用Math.PI的形式获取这个常量。
如果static被省略的话PI就变成了Math类的一个实例域。就需要通过Math类的对象访问PI。
4.4.3 静态方法
同样,例如Math.pow方法,不需要对象。
4.5 方法参数
Java总是采用按值调用,也就是说,方法得到到底是所有参数值的一个拷贝,特别是,方法不能修改传递给它的任何参数变量的内容。
public static void tripleValue(double x){
x = x * 3;
}
double percent = 10;
tripleValue(percent );
想要将percent扩大3倍,但是并没有做到这一点,调用这个方法后,percent的值仍然是10.
下面编写一个交换两个雇员对象的方法
public static void swap(Employee x, Employee y){//不起作用
Employee temp = x;
x = y;
y = temp;
}
...
Employee a = new Employee(...)
Employee b = new Employee(...)
swap(a,b);
这个过程说明:
- 一个方法不能修改一个基本数据类型的参数(即数值型或布尔型)
- 一个方法可以改变一个对象参数的状态
- 一个方法不能让对象参数引用一个新的对象
4.6 对象构造
有些类有多个构造器,例如
StringBuilder messages = new StringBuilder();
StringBuilder todoList = new StringBuilder("To do...")
这种特征叫做重载(overloading)。
如果在编写一个类时没有编写构造器,那么系统就会提供一个无参构造器,这个构造器将所有的实例域设置为默认值。但是如果类中提供了至少一个构造器,但是没有提供无参的构造器,那么在构造对象时如果没有提供参数就会被视为不合法。