抽象数据类型
定义方法
为抽象数据类型的对象定义相应的操作,即方法。
定义语法格式:
[访问符][修饰符列表]<返回类型> 方法名 ([参数列表]) {
方法体
}
修饰符列表:
- static 表示该方法是一个静态方法,不需要创建实例对象来使用,可以直接通过类来访问。
- final 表示该方法是一个终极方法,不可以在子类中被重写。
- abstract 表示该方法是一个抽象方法,不可以用来创建实例对象。
参数传递
在函数中,如果传入的参数是基本数据类型,那么函数体对形参的修改不会影响到实参;
而如果传入的参数是引用类型(对象、数组等),那么函数体对形参的修改会影响到实参。
重载方法名
在一个类中写多个方法,对不同的参数进行同样的操作,此时需要重载方法名。
重载方法的方法名必须相同,参数列表必须不同(参数个数或者参数类型不同)。
对象的构造与初始化
此处需要提到一个很重要的概念————构造方法。
Java中的构造方法,与C++中的构造函数几乎完全对应。
子类与继承
子类
当两个类A,B满足“A is a B”关系时,我们可以将A声明为B的一个子类。
继承
与C++类似,Java中也有继承概念。需要用到extends关键字:
public class A extends B {
...
}
表示类A继承自B,此时,A是子类,B是父类。
一旦继承完成,子类将默认具有父类中的所有属性和方法。
Java只允许单重继承。Object类是Java程序中所有类的直接或者间接父类。
多态
多态性是指同一个名字的若干个方法,有着不同的实现。
通过重载、重写完成多态性。
动态绑定
public class Test {
public static void main(String[] args) {
func(new Person());
func(new Student());
func(new Graduate());
}
public static void func(Object o) {
System.out.println(o.toString());
}
}
class Person {
public String toString() {
return "Person!";
}
}
class Student extends Person {
public String toString() {
return "Student!";
}
}
class Graduate extends Student {
public String toString() {
return "!";
}
}
体会上述例子。Person、Student、Graduate均继承了Object的toString方法,却也都对其进行了重写。
而func()方法接收一个对象,动态调用对象本身的toString方法。我们称这种由Java虚拟机在运行时动态决定调用哪一个toString方法的能力为动态绑定。
转换对象
Java允许使用对象的父类类型的一个变量指示该对象,称为转换对象。
// notice that: Manager is an Employee.
Employee e = new Manager();
Employee e;
Manager m = new Manager();
e = m;
我们称e是m的转换对象。相较于原对象m,转换对象e会丢失原对象相对于父类的新增方法、属性。实际应用中,我们可以判断该对象是否是子类的实例。如果是,就强制类型转换该对象(引用),使其恢复全部功能。
方法重写
子类重写父类方法的情况:
- 子类的方法内容与父类不同;
- 子类需要取消某个方法;
- 子类需要实现更复杂的方法
关于方法重写的注意事项:
- 当子类中重写了父类方法后,如果还想使用父类中被隐藏的方法,可以使用super关键字。
- 重写方法的允许访问范围不能小于原方法。
- 父类与子类的构造方法问题:Java要求一个父类的对象要在子类运行前完全初始化。
类成员
静态变量
让一个类的多个实例对象共享,实现多个对象之间的通信,或者用于记录所创建的对象的个数。这样的变量被称为静态变量或者类变量。
静态方法
如果需要在尚未创建类的实例对象时,就去引用该类的程序代码,就可以给相应的程序方法标记关键字static。这样的方法称为静态方法或者类方法。
抽象类
什么是抽象类
抽象类是指不能用来创建实例对象的类。通常可以通过关键字abstract将一个类定义为抽象类。
在抽象类中,每一个未被定义具体实现的方法也标记为abstract,称为抽象方法。
抽象类可以包含抽象方法和非抽象方法。
抽象类的存在,是强迫程序员必须在抽象类的子类中实现相应的抽象方法,以创建实例对象,否则子类仍然是抽象类,不能用来创建实例对象。
开闭原则
接口
接口的最大特点:接口中所有的方法都是抽象方法体,可以将接口看成特殊的抽象类。
接口的定义
interface Storage {
Object storage[] = new Object[100];
void put(Object o);
Object get();
}
接口也具有数据成员和方法,但是数据成员都必须赋初值,并且方法必须是抽象方法。
接口的实现
class StackStorage implements Storage {
private int point = 0;
int objectNum = 0;
public void put(Object o) {
storage[point++] = o;
objectNum++;
}
...
}
一般,可以通过接口实现“多重继承”,接口的实现,实际上是实现类对接口中抽象方法的重写。
接口回调
接口变量,是用接口声明的变量,可以用来调用被类实现的接口方法。
接口的多样性
由接口产生的多态性是指不同的类在实现同一个接口时可能具有不同的实现方式,那么接口变量在回调接口方法时就可能具有多种形态。类似之前抽象类中的动态绑定。