组合 新类中产生 现有类的对象
继承 现有类的形式并其中添加新代码
7.1组合语法
将对象置于新类:直接定义基本类型;非基本类型对象,引用置于新类;
package chapter7reusing;
// Composition for code reuse.
class WaterSource {
private String s;
WaterSource() {
System.out.println("WaterSource()");
s = "Constructed";
}
public String toString() { //每一个非基本类型对象都有 toString方法
return s;
}
}
public class SprinklerSystem {
private String valve1, valve2, valve3, valve4;
private WaterSource source = new WaterSource();
private int i;
private float f;
public String toString() {
return
"valve1 = " + valve1 + " " +
"valve2 = " + valve2 + " " +
"valve3 = " + valve3 + " " +
"valve4 = " + valve4 + " " +
"i = " + i + " " +
"f = " + f + " " +
"source = " + source;//调用toString(),将source对象转换为String
}
public static void main(String[] args) {
SprinklerSystem sprinklerSystem = new SprinklerSystem();
System.out.println(sprinklerSystem); // 基本类型 初始化为0 对象引用初始化为null
}
}
/* outpub:
WaterSource()
valve1 = null valve2 = null valve3 = null valve4 = null i = 0 f = 0.0 source = Constructed
四种方式初始化
- 定义对象的地方
- 类的构造器
- 惰性初始化
- 使用实例初始化
package chapter7reusing;
//Constructor initialization with composition
import static chapter6access.Print.print;
class Soap {
private String s;
Soap() { // 类的构造器中
print("Soap()");
s = "Constructed";
}
public String toString() {
return s;
}
}
public class Bath {
private String //定义对象的地方初始化,构造器被调用之前初始化
s1 = "Happy",
s2 = "Happy",
s3, s4;
private Soap castille;
private int i;
private float toy;
public Bath() {
print("Inside Bath()");
s3 = "Joy";
toy = 3.14f;
castille = new Soap(); // 使用实例初始化
}
{
i = 47;
}
public String toString() {
if (s4 == null) //惰性初始化:使用对象之前初始化
s4 = "Joy";
return
"s1 = " + s1 + "
" +
"s2 = " + s2 + "
" +
"s3 = " + s3 + "
" +
"s4 = " + s4 + "
" +
"i = " + i + "
" +
"toy = " + toy + "
" +
"castille = " + castille;
}
public static void main(String[] args) {
Bath bath = new Bath();
print(bath);
}
}
惰性初始化 实例第一个类的对象
package chapter7reusing;
class First {
String s;
public First(String si) {
System.out.println("FirstClass()");
s = si;
}
public String toString() {
return s;
}
public void setString(String sNew) {
s = sNew;
}
}
class Second {
String s;
First first;
public Second(String si) {
s = si;
}
public void check() {
if (first == null)
System.out.println("not initialized");
else
System.out.println("initialized");
}
private First lazy() {
if (first == null) {
System.out.println("create first");
first = new First(s);
}
return first;
}
public First getFirst() {
return lazy();
}
public String toString() {
return lazy().toString();
}
public void setFirst(String s) {
lazy().setString(s);
}
}
public class E01_Composition {
public static void main(String[] args) {
Second second = new Second(("init String"));
second.check();
System.out.println(second.getFirst());
second.check();
System.out.println(second);
second.setFirst("New String");
System.out.println(second);
}
} /* Output:
not initialized
create first
FirstClass()
init String
initialized
init String
New String
*/
7.2继承语法
隐式继承 标准根类Object
package chapter7reusing;
// Inheritance syntax & properties.
import javax.swing.*;
class Cleanser {
private String s = "Cleanser";
public void append(String a) {
s += a;
}
public void dilute() {
append(" dilute()");
}
public void apply() {
append(" apply()");
}
public void scrub() {
append(" scrub()");
}
public String toString() {
return s;
}
public static void main(String[] args) { //每个类中设置main方法 单元测试简便易行,无需删除
Cleanser cleanser = new Cleanser();
cleanser.dilute();
cleanser.apply();
cleanser.scrub();
System.out.println(cleanser);
}
}
class NewDetergent extends Detergent {
// 覆盖scrub()
public void scrub() {
append("NewDetergent.scrub()");
super.scrub();
}
// 增加方法
public void sterilize(){ //灭菌
append(" sterilize()");
}
public static void main(String[] args) {
NewDetergent newDetergent = new NewDetergent();
newDetergent.dilute();
newDetergent.apply();
newDetergent.scrub();
newDetergent.foam();
newDetergent.sterilize();
System.out.println(newDetergent);
}/* Output:
Cleanser dilute() apply()NewDetergent.scrub() Detergent.scrub() scrub() foam() sterilize()
*/
}
public class Detergent extends Cleanser {
// 更改方法
public void scrub() {
append(" Detergent.scrub()");
super.scrub(); //调用基类
}
// 增加接口方法
public void foam() {
append(" foam()");
}
//测试新类
public static void main(String[] args) {
Detergent detergent = new Detergent();
detergent.dilute();
detergent.apply();
detergent.scrub();
detergent.foam();
System.out.println(detergent);
System.out.println("Testing base class:");
Cleanser.main(args);
}
}/* Output:
Cleanser dilute() apply() Detergent.scrub() scrub() foam()
Testing base class:
Cleanser dilute() apply() scrub()
*/
7.2.1 初始化基类
基类 导出类
创建一个导出类的对象时,该对象也包含一个基类的子对象。
在构造器中调用基类构造器进行初始化。基类构造器具有初始化基类的能力。
package chapter7reusing;
class Art {
Art() {
System.out.println("Art constructor");
}
}
class Drawing extends Art {
Drawing() {
System.out.println("Drawing constructor");
}
}
public class Cartoon extends Drawing {
Cartoon() {
System.out.println("Cartoon constructor");
}
public static void main(String[] args) {
Cartoon x = new Cartoon();
}
}/* Output: 构建过程 从 基类 向外 扩散
Art constructor
Drawing constructor
Cartoon constructor
*/
package chapter7reusing;
class ClassA {
ClassA() {
System.out.println("ClassA()");
}
}
class ClassB {
ClassB() {
System.out.println("ClassB()");
}
}
class ClassC extends ClassA {
ClassB classB = new ClassB();
}
public class E05 {
public static void main(String[] args) {
ClassC classC = new ClassC();
}
}/* Output 先调用基类构造方法,然后是成员对象的构造方法
ClassA()
ClassB()
*/
带参数的构造器
必须关键字 super显示调用基类构造器,并适当的参数列表
package chapter7reusing;
class Game {
Game(int i) {
System.out.println("Game Constructor");
}
}
class BoardGame extends Game {
BoardGame(int i) {
super(i);
System.out.println("BoardGame constructor");
}
}
public class Chess extends BoardGame {
Chess() {
super(11);
System.out.println("Chess Constructor");
}
public static void main(String[] args) {
Chess chess = new Chess();
}
}/* Output
Game Constructor
BoardGame constructor
Chess Constructor
*/
7.3 代理
public class SpaceShipControl {
void up(int velocity){};
void down(int velocity){};
void left(int velocity){};
void right(int velocity){};
void forward(int velocity){};
void back(int velocity){};
void turboBoost(){};
}
package chapter7reusing;
public class SpaceShipDelegation {
private String name;
private SpaceShipControl control = new SpaceShipControl(); // 成员对象置于类中(就像组合)
public SpaceShipDelegation(String name) {
this.name = name;
}
//Delegated methods;
public void back(int velocity) {
control.back(velocity);
}
public void up(int velocity) {
control.up(velocity);
}
public void down(int velocity) {
control.down(velocity);
}
public void forward(int velocity) {
control.forward(velocity);
}
public void left(int velocity) {
control.left(velocity);
}
public void right(int velocity) {
control.right(velocity);
}
public void turboBoost(int velocity) {
control.turboBoost();
}
public static void main(String[] args) {
SpaceShipDelegation protector = new SpaceShipDelegation("NSEA Protector");
protector.forward(100);
}
}
7.4结合使用组合和继承
package chapter7reusing;
class Plate {
Plate(int i) {
System.out.println("Plate constructor");
}
}
class DinnetPlate extends Plate {
DinnetPlate(int i) {
super(i);
System.out.println("DinnetPlate constructor");
}
}
class Utensil { //器皿
Utensil(int i) {
System.out.println("Utensil constructor");
}
}
class Spoon extends Utensil {
Spoon(int i) {
super(i);
System.out.println("Spoon constructor");
}
}
class Fork extends Utensil {
Fork(int i) {
super(i);
System.out.println("Fork constructor");
}
}
class Knife extends Utensil {
Knife(int i) {
super(i);
System.out.println("Knife constructor");
}
}
class Custom {
Custom(int i) {
System.out.println("Custom constructor");
}
}
public class PlaceSetting extends Custom {
private Spoon sp;
private Fork frk;
private Knife kn;
private DinnetPlate dp;
public PlaceSetting(int i) {
super(i + 1);
sp = new Spoon(i + 2);
frk = new Fork(i + 3);
kn = new Knife(i + 4);
dp = new DinnetPlate(i + 5);
System.out.println("PlaceSetting constructor");
}
public static void main(String[] args) {
PlaceSetting x = new PlaceSetting(9);
}
}
7.4.1 确保正确清理
不建议使用finalize()
package chapter7reusing;
// Ensuring proper cleanup
class Shape {
Shape(int i) {
System.out.println("Shape constructor");
}
void dispose() {
System.out.println("Shape dispose");
}
}
class Circle extends Shape {
Circle(int i) {
super(i);
System.out.println("Drawing Circle");
}
void dispose() {
System.out.println("Erasing Circle");
super.dispose();
}
}
class Triangle extends Shape {
Triangle(int i) {
super(i);
System.out.println("Drawing Triangle");
}
void dispose() {
System.out.println("Erasing Triangle");
super.dispose();
}
}
class Line extends Shape {
private int start, end;
Line(int start, int end) {
super(start);
this.start = start;
this.end = end;
System.out.println("Drawing Line: " + start + ", " + end);
}
void dispose() {
System.out.println("Erasing Line" + start + ", " + end);
super.dispose();
}
}
public class CADSystem extends Shape {
private Circle c;
private Triangle t;
private Line[] lines = new Line[3];
public CADSystem(int i) {
super(i + 1);
for (int j = 0; j < lines.length; j++)
lines[j] = new Line(j, j * j);
c = new Circle(1);
t = new Triangle(1);
System.out.println("Combined constructor");
}
public void dispose() { //注意与初始化的顺序相反 防止子对象依赖另一个子对象
System.out.println("CADSystem.dispose()");
t.dispose();
c.dispose();
for (int i = lines.length - 1; i >= 0; i--)
lines[i].dispose();
super.dispose();
}
public static void main(String[] args) {
CADSystem x = new CADSystem(47);
try {
// Code and exception handing……
} finally {
x.dispose();
}
}
}
7.4.2 名称屏蔽
重载机制 在导出类或基类 都正常工作
package chapter7reusing;
class Homer {
char doh(char c) {
System.out.println("doh(char)");
return 'd';
}
float doh(float f) {
System.out.println("doh(float)");
return 1.0f;
}
}
class Milhouse {
}
class Bart extends Homer {
void doh(Milhouse m) {
System.out.println("doh(Milhouse)");
}
}
public class Hide {
public static void main(String[] args) {
Bart b = new Bart();
b.doh(1);
b.doh('x');
b.doh(1.0f);
b.doh(new Milhouse());
}
}
7.5 组合与继承之间选择
package chapter7reusing;
class Engine {
public void start() {
}
public void rev() {
}
public void stop() {
}
public void service(){
System.out.println("service");
}
}
class Wheel {
public void inflate(int psi) {
} //inflate 充气
}
class Window {
public void rollup() {
}
public void rolldown() {
}
}
class Door {
public Window window = new Window();
public void open() {
}
public void close() {
}
}
public class Car {
public Engine engine = new Engine(); //特例,一般是private 有助于客户端程序员了解如何使用类
public Wheel[] wheel = new Wheel[4];
public Door
left = new Door(),
right = new Door();
public Car() {
for (int i = 0; i < 4; i++)
wheel[i] = new Wheel();
}
public static void main(String[] args) {
Car car = new Car();
car.left.window.rollup();
car.wheel[0].inflate(72);
car.engine.service();
}
}
7.6 protected 关键字
protected 对于类用户而言,是private,但对于导出类,或包内的类来说,是可访问的。
package chapter7reusing;
// The protected keyword.
class Villain {
private String name;
protected void set(String nm) {
name = nm;
}
public Villain(String name) {
this.name = name;
}
public String toString() {
return "I'm a Villain and my name is " + name;
}
}
public class Orc extends Villain {
private int orcNumber;
public Orc(String name, int orcNumber) {
super(name);
this.orcNumber = orcNumber;
}
public void change(String name, int orcNumber) {
set(name); // Available because it's protected.
this.orcNumber = orcNumber;
}
public String toString() {
return "Orc" + orcNumber + ": " + super.toString(); // 根据基类版本
}
public static void main(String[] args) {
Orc orc = new Orc("Limburger", 12);
System.out.println(orc);
orc.change("Bob", 19);
System.out.println(orc);
}
}
向上转型
术语来源: 类继承图 绘制方法为基础
导出类 是 基类的 一个超集,向上转型过程中,唯一可能 是丢失方法
class Instrument {
public void play() {
System.out.println("Instrument play()");
}
static void tune(Instrument i) {
i.play();
}
}
public class Wind extends Instrument {
public static void main(String[] args) {
Wind flute = new Wind();
Instrument.tune(flute); // 将 Wind引用转换为Instruments 引用的动作: 向上转型
}
}
再论组合与继承
最可能:
数据和方法包装一个类中,使用该类对象。
组合技术 使用现有类,开发新类。
继承技术不太常用。 必须向上转型,继承必要
package chapter7reusing;
class Amphibian {
public void swim() {
System.out.println("swim");
}
static void action(Amphibian am) {
System.out.println("Amphibian: ");
am.swim();
}
}
public class Frog extends Amphibian {
// public void swim() {
// System.out.println("Frog");
}
public static void main(String[] args) {
Frog frog = new Frog();
Amphibian.action(frog); //使用基类的静态方法
}
}
或者
package chapter7reusing;
class Amphibian {
public void swim() {
System.out.println("swim");
}
static void action(Amphibian am) {
System.out.println("Amphibian: ");
am.swim();
}
}
public class Frog extends Amphibian {
// public void swim() { //覆盖基类的定义,则调用导出类的方法
// System.out.println("Frog");
// }
public static void main(String[] args) {
Amphibian frog = new Frog(); //定义时 向上转型
frog.action(frog);
}
}
## 7.8 final关键字
设计 效率
用到final 的几种情况:数据 方法 类
final 在字段定义或者构造器中 初始化
### 7.8.1 final 数据
1.永不改变的编译时常量 大写 下划线分隔单词
2.运行时初始化的值,不希望它被改变
```java
package chapter7reusing;
import javax.swing.*;
import java.util.Random;
class Value {
int i;
public Value(int i) {
this.i = i;
}
}
public class FinalData {
private static Random random = new Random(47);
private String id;
public FinalData(String id) {
this.id = id;
}
// 编译时数值 final基本类型 编译期常量
private final int valueOne = 9;
private static final int VALUE_TWO = 99;
// 典型 定义 public 可用于包之外 static 只有一份 final 常量
public static final int VALUE_THREE = 39;
// 非编译期常量 数据是final,但运行时随机生成数值初始化
private final int i4 = random.nextInt(20);
static final int INT_5 = random.nextInt(20);
private Value v1 = new Value(11);
private final Value v2 = new Value(22); // v2 不能指向另一个新对象
private static final Value VAL_3 = new Value(33);
// Arrays:
private final int[] a = {1, 2, 3, 4, 5, 6};
public String toString(){
return id + ":" + "i4 = " + i4 + ", INT_5 = " +INT_5;
}
public static void main(String[] args) {
FinalData fd1 = new FinalData("fd1");
// fd1.valueOne++; // final 变量
fd1.v2.i++; // 对象不是常量
fd1.v1 = new Value(9); //可以,不是final
for(int i =0;i<fd1.a.length;i++)
fd1.a[i]++; // 对象不是常量
// fd1.v2 = new Value(0); // can't
// fd1.VAL_3 = new Value(1); // can't
// fd1.a = new int[3];
System.out.println(fd1);
System.out.println("Creating new FinalData");
FinalData fd2 = new FinalData("fd2");
System.out.println(fd1);
System.out.println(fd2);
}
}
空白final
声明为final 但未给定初值的字段
package chapter7reusing;
class Poppet {
private int i;
Poppet(int ii) {
i = ii;
}
}
public class BlankFinal {
private final int i = 0; // 初始化 final
private final int j; // 空白final
private final Poppet p; // 空白引用 final
// 空白final 必须在 构造方法中 初始化
public BlankFinal() {
j = 1;
p = new Poppet(1);
}
public BlankFinal(int x) {
j = x;
p = new Poppet(x);
}
public static void main(String[] args) {
new BlankFinal();
new BlankFinal(47);
}
}
final 参数
无法在方法中更改参数引用所指向的对象
package chapter7reusing;
class Gizmo {
public void spin() {
}
}
public class FinalArguments {
void with(final Gizmo g) {
// g = new Gizmo(); // g是 final
}
void without(Gizmo g) {
g = new Gizmo();
g.spin();
}
// void f(final int i) { // 无法修改参数
// i++;
// }
int g(final int i) { // 可以读参数
return i + 1;
}
public static void main(String[] args) {
FinalArguments bf = new FinalArguments();
bf.without(null);
bf.with(null);
}
}
7.8.2 final 方法
方法锁定,防止 继承类修改 不会被覆盖
效率 不建议
final 和private 关键字
类中private方法 隐式 指定final
方法为private , 就不是基类接口但一部分
覆盖错觉:并没有覆盖,而是生成了一个新的方法
package chapter7reusing;
class WithFinals {
private final void f() {
System.out.println("WithFinals.f()");
}
private void g() {
System.out.println("WithFinals.g()"); // 隐式 final
}
}
class OverridingPrivate extends WithFinals {
private final void f() {
System.out.println("OverridingPrivate.f()");
}
private void g() {
System.out.println("OverridingPrivate.g()");
}
}
class OverridingPrivate2 extends OverridingPrivate {
public final void f() {
System.out.println("OverridingPrivate2.f()");
}
public void g() {
System.out.println();
}
}
public class FinalOverRidingIllusion {
public static void main(String[] args) {
OverridingPrivate2 op2 = new OverridingPrivate2();
op2.f();
op2.g();
OverridingPrivate op = op2; // 向上转型 但不能调用方法
// op.f();
// op.g();
WithFinals wf = op2;
// wf.f();
// wf.g();
}
}
7.8.3 final 类
final 类,禁止继承,所有方法隐式指定为final
7.8.4 final 忠告
关于Vector/ArrayList Hashtable/HashMap 关于 Final没看明白
7.9 初始化 及 类的加载
基类static 初始化 - 导出类 static 初始化 类加载完毕
-创建对象
基本类型初始化0 对象引用初始化null
基类构造器 导出类构造器
实例变量
构造器 本质是 静态方法
经典
package chapter7reusing;
class Insect {
private int i = 9;
protected int j;
Insect() {
System.out.println("i = " + j + ",j +" + j);
j = 39;
}
private static int x1 = printInit("static Insect.x1 initialized");
static int printInit(String s) {
System.out.println(s);
return 47;
}
}
public class Beetle extends Insect {
private int k = printInit("Beetle.k initialized");
public Beetle() {
System.out.println("k = " + k);
System.out.println("j = " + j);
}
private static int x2 = printInit("static Beetle.x2 initialized");
public static void main(String[] args) {
System.out.println("Beetle Constructor");
Beetle b = new Beetle();
}
}/* Output
static Insect.x1 initialized
static Beetle.x2 initialized
Beetle Constructor
i = 0,j +0
Beetle.k initialized
k = 47
j = 39
*/
class LoadTest {
// The static clause is executed
// upon class loading:
static {
System.out.println("Loading LoadTest");
}
static void staticMember() {}
}
public class E23_ClassLoading {
public static void main(String[] args) {
System.out.println("Calling static member");
LoadTest.staticMember();
System.out.println("Creating an object");
new LoadTest();
}
} /* Output:
Calling static member
Loading LoadTest
Creating an object
*///:~