本章思维导图
本章主要内容
本章主要介绍了复用类,其中详细介绍了引入复用类中的一些关键技术,包括有:组合、继承、代理、向上转型、final关键字以及初始化及类的加载等。
一、组合
在组合技术中,只需将对象引用置于新类中即可。由于编译器并不会为每个对象引用都创建默认对象,因此如果想初始化新类中的对象引用,主要如下几种方式:
- 在定义对象的地方;
- 在类的构造器中;
- 在开始使用这些对象之时,也称“惰性初始化”;
- 使用实例初始化,即可以随时随地合法地为对象引用初始化。
二、继承
在继承技术中,通过extends关键字,子类可以继承来自父类中的成员变量及方法。但是需要注意以下几点:
- 子类继承父类中访问权限为public和protected的方法和成员变量;
- 同一个package中,子类可以继承父类中访问权限为默认访问权限(缺省访问权限关键字)的方法及变量;但是在不同的package中,子类则无法继承父类中该类型的方法及变量;
- 子类中可以重写(override)从父类中继承来方法。重写时,方法的方法名、参数列表以及返回值类型完全相同。不过,方法的访问权限是可以修改的,但是只能往更加宽泛的访问权限修改(即父类protected -> 子类public,父类默认访问权限 -> 子类protected或public)。
- 父类中的构造器一旦被重载,则说明父类中没有默认构造器。此时,子类中也必须自定义与父类中某一构造器相同参数列表的构造器,除非父类中含有无参构造器,这样子类也可以不用自定义而使用默认构造器即可。
代码示例:
//父类
public class fatherClass {
protected int i;
public void func1(){
System.out.println("father public func1");
}
protected void func2(){
System.out.println("father protected func2");
}
void func3(){
System.out.println("father default func3");
}
private void func4(){
System.out.println("father private func4");
}
public fatherClass(){
i = 3;
}
public fatherClass(int i){
this.i = i;
}
}
//子类
public class childClass extends fatherClass {
public void func1(){
super.func1();
System.out.println("son public func1");
}
public void func2(){
super.func2();
System.out.println("son public func2");
}
protected void func3(){
super.func3();
System.out.println("son protected func3");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
childClass obj = new childClass();
obj.func1();
obj.func2();
obj.func3();
System.out.println(obj.i);
}
}
实例结果:
//public to public
father public func1
son public func1
//protected to public
father protected func2
son public func2
//default to protected
father default func3
son protected func3
3
三、代理
代理介于组合与继承之间,主要体现有:
- 将一个成员对象置于所要构造的类中(类似组合);
- 在构造的新类中暴露该成员对象的所有成员方法(类似继承)。
代码实例:
public class test {
void say(String str){
System.out.println(str);
}
}
public class testDelegation {
private test obj = new test();
public void say(String str){
obj.say(str);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
testDelegation td = new testDelegation();
td.say("hello world");//print "hello world"
}
}
四、向上转型
由导出类转型为基类,也称为向上转型。也可以说,向上转型是从一个较专用类型向较通用类型转换。
注意:尽管导出类转型为基类,但是调用成员方法时,实际上是调用了导出类中的成员方法。
代码实例:
//基类
public class Instrument {
public void play(){
System.out.println("Instrument is playing");
}
private void sing(){
System.out.println("Instrument is singing");
}
static void tune(Instrument i){
i.play();
i.sing();
}
}
//导出类
public class Wind extends Instrument {
public void play(){
System.out.println("Wind is playing");
}
public static void main(String[] args) {
// TODO Auto-generated method stub
Wind w = new Wind();
Instrument.tune(w);
}
}
示例结果:
Wind is playing
Instrument is singing
五、final关键字
1、final变量
final变量,其值初始化后无法再改变。
(1) final变量与static final变量的区别:static final变量在类装载时进行初始化,final变量则在创建对象时才进行初始化。
代码示例:
import java.util.Random;
public class finalData {
private static Random rand = new Random(24);
private final int var1 = rand.nextInt(10);
private static final int var2 = rand.nextInt(10);
public String toString(){
return "final var1 = " + var1 + "; static final var2 = " + var2;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
finalData fd1 = new finalData();
System.out.println(fd1);
finalData fd2 = new finalData();
System.out.println(fd2);
}
}
示例结果:
final var1 = 0; static final var2 = 5
final var1 = 6; static final var2 = 5
(2) 空白final
声明空白final变量时,必须在构造器中对该变量进行初始化。
代码示例:
public class finalData {
private static Random rand = new Random(24);
private final int var;//空白final变量
finalData(){
var = 3;//对空白final变量进行初始化
}
}
(3) final参数
final参数,表示了无法在方法中对其实参的引用值进行修改。
2、final方法
final方法,可以被继承,但不可以被重写。
3、final类
final类,表示该类不可被继承。
六、初始化及类的加载
- 类的代码在初次使用时才会被加载;
- 类中static域的初始化顺序,与代码书写顺序相同,且只初始化一次;
- 类中实例变量的初始化顺序,与代码书写顺序相同;
- 在继承关系中,基类首先被初始化,导出类才被初始化。
类的初始化顺序如下图所示: