第1章 对象导论 1

在第一章最前面作者就说明了一些话语,这些话语已经很明确的说出了这一章甚至这本书的某些特性:偏重与讲解Java这一面向对象编程语言与面对过程编程语言以及C++的区别,从Java其起源思想讲解Java语言特点以及用法,与市面上大部分教材以及视频直接讲解知识点不同,所以阅读这本书最重要的是要理解面向对象编程的思想。

在阅读第一章的时候,确实看的很费神,对于作者的思想能理解,但是自己却无法转为自己的语言,因此,这一章只列出下列目录,留待以后再补上,毕竟作者自己也说了,可跳过此章

1.1 抽象过程 1

1.2 每个对象都有一个接口 2

1.3 每个对象都提供服务 4

1.4 被隐藏的具体实现 4

1.5 复用具体实现 5

1.6 继承 6

1.6.1 “是一个”与“像是一个”关系 8

1.7 伴随多态的可互换对象 8

1.8 单根继承结构 11

1.9 容器 11

1.9.1 参数化类型(范型) 12

1.10 对象的创建和生命期 13

1.11 异常处理:处理错误 14

1.12 并发编程 14

1.13 Java与Internet 15

1.13.1 Web是什么 15
1.13.2 客户端编程 16
1.13.3 服务器端编程 19

1.14 总结 20


第2章 一切都是对象 21

这一章将开始介绍Java程序的基本组成,但是,也会令你“欲仙欲死”。

2.1 用引用操纵对象 21

这里作者用遥控器与电视机作为讲解引用与对象的关系,很符合要义,我们一般是操控遥控器,在程序中我们也是一般操作对象的引用。这一节引出对象。

2.2 必须由你创建所有对象 22

这一节继承上一节,对对象需要初始化,new 关键字表名“给我一个新的对象”

2.2.1 存储到什么地方 22
  • 寄存器:处理器内部,速度最快,我们无法直接控制
  • 堆栈:RAM中,速度仅次于寄存器;堆栈指针向上移动,释放那些内存;向下移动,分配新的内存;引用存于此处。
  • 堆:RAM内,用于存放所有的Java对象。
  • 常量存储:常量值通常直接存放在程序代码内部
  • 非RAM存储:2个基本的例子——流对象以及持久化对象,即存活于程序之外的数据。
2.2.2 特例:基本类型 23

基本数据类型存储于堆栈中

类型分类:

数据类型转换之默认转换顺序:

类型范围:

2.2.3 Java中的数组 24

2.3 永远不需要销毁对象 24

2.3.1 作用域 24

变量定义在哪个大括号内,它就在这个大括号内有效。并且,在同一个大括号内不能同时定义同名的变量。

2.3.2 对象的作用域 25

一般对象在定义的大括号内消失的是其引用,其对象本身继续占据内存空间。这就牵涉到了Java的垃圾回收机制。

2.4 创建新的数据类型:类 25

引出类class关键字

2.4.1 字段和方法 26

字段–>成员变量;方法–>成员方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Java中的参数传递问题:
基本类型:形式参数的改变对实际参数没有影响。
引用类型:形式参数的改变直接影响实际参数。
成员变量和局部变量的区别?
A:在类中的位置不同
成员变量:在类中方法外
局部变量:在方法定义中或者方法声明上
B:在内存中的位置不同
成员变量:在堆内存
局部变量:在栈内存
C:生命周期不同
成员变量:随着对象的创建而存在,随着对象的消失而消失
局部变量:随着方法的调用而存在,随着方法的调用完毕而消失
D:初始化值不同
成员变量:有默认初始化值
局部变量:没有默认初始化值,必须定义,赋值,然后才能使用。
注意事项:
局部变量名称可以和成员变量名称一样,在方法中使用的时候,采用的是就近原则。
如果你看到了一个方法的形式参数是一个类类型(引用类型),
这里其实需要的是该类的对象。

2.5 方法、参数和返回值 27

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
(1)方法:就是完成特定功能的代码块。
注意:在很多语言里面有函数的定义,而在Java中,函数被称为方法。
(2)格式:
修饰符 返回值类型 方法名(参数类型 参数名1,参数类型 参数名2...) {
方法体语句;
return 返回值;
}

修饰符:目前就用 public static。后面再详细讲解其他修饰符
返回值类型:就是功能结果的数据类型
方法名:就是起了一个名字,方便我们调用该方法。
参数类型:就是参数的数据类型
参数名:就是变量
参数分类:
实参:实际参与运算的数据
形参:方法上定义的,用于接收实际参数的变量
方法体语句:就是完成功能的代码块
return:结束方法
返回值:就是功能的结果,由return带给调用者。
(3)两个明确:
返回值类型:结果的数据类型
参数列表:参数的个数及对应的数据类型
(4)方法调用
A:有明确返回值的方法
a:单独调用,没有意义
b:输出调用,不是很好,因为我可能需要不结果进行进一步的操作。但是讲课一般我就用了。
c:赋值调用,推荐方案
B:void类型修饰的方法
a:单独调用
(6)方法的注意事项
A:方法不调用不执行
B:方法之间是平级关系,不能嵌套定义
C:方法定义的时候,参数是用','隔开的
D:方法在调用的时候,不用在传递数据类型
E:如果方法有明确的返回值类型,就必须有return语句返回。
2.5.1 参数列表 27

2.6 构建一个Java程序 28

2.6.1 名字可见性 28

名字空间,包

2.6.2 运用其他构件 28

import关键字

2.6.3 static 关键字 29
  • (1)静态的意思。

    • 可以修饰成员变量和成员方法。
    • 针对多个对象有共同的这样的成员变量值的时候,Java就提供了一个关键字来修饰:static。
  • (2)静态的特点:

    • A:随着类的加载而加载
    • B:优先与对象存在
    • C:被类的所有对象共享
      这其实也是我们判断该不该使用静态的依据。
      • 举例:饮水机和水杯的问题思考
    • D:可以通过类名调用
      既可以通过对象名调用,也可以通过类名调用,建议通过类名调用。
  • (3)静态的内存图

    • 静态的内容在方法区的静态区
  • (4)静态的注意事项;

    • A:在静态方法中没有this对象
    • B:静态只能访问静态
  • (5)静态变量和成员变量的区别

    • A:所属不同
      • 静态变量:属于类,类变量
      • 成员变量:属于对象,对象变量,实例变量
    • B:内存位置不同
      • 静态变量:方法区的静态区
      • 成员变量:堆内存
    • C:生命周期不同
      • 静态变量:静态变量是随着类的加载而加载,随着类的消失而消失
      • 成员变量:成员变量是随着对象的创建而存在,随着对象的消失而消失
    • D:调用不同
      • 静态变量:可以通过对象名调用,也可以通过类名调用
      • 成员变量:只能通过对象名调用
  • (6)main方法是静态的

    • public:权限最大

    • static:不用创建对象调用

    • void:返回值给jvm没有意义

    • main:就是一个常见的名称。

    • String[] args:可以接收数据,提供程序的灵活性

    • main方法的格式讲解:

      • public static void main(String[] args) {…}

      • public:公共的,访问权限是最大的。由于main方法是被jvm调用,所以权限要够大。

      • static:静态的,不需要创建对象,通过类名就可以。方便jvm的调用。

      • void:因为我们曾经说过,方法的返回值是返回给调用者,而main方法是被jvm调用。你返回内容给jvm没有意义。

      • main:是一个常见的方法入口。我见过的语言都是以main作为入口。

      • String[] args:这是一个字符串数组。值去哪里了?
        这个东西到底有什么用啊?怎么给值啊?

        这个东西早期是为了接收键盘录入的数据的。
        格式是:

        java MainDemo hello world java
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        class MainDemo {
        public static void main(String[] args) {
        //System.out.println(args); //[Ljava.lang.String;@175078b
        //System.out.println(args.length); //0
        //System.out.println(args[0]); //ArrayIndexOutOfBoundsException
        //接收数据后
        System.out.println(args);
        System.out.println(args.length);
        //System.out.println(args[0]);
        for(int x=0; x<args.length; x++) {
        System.out.println(args[x]);
        }
        }
        }
    • A:在静态方法中是没有this关键字的

      • 如何理解呢?
        • 静态是随着类的加载而加载,this是随着对象的创建而存在。
        • 静态比对象先存在。
    • B:静态方法只能访问静态的成员变量和静态的成员方法

      • 静态方法:
        • 成员变量:只能访问静态变量
        • 成员方法:只能访问静态成员方法
      • 非静态方法:
        • 成员变量:可以是静态的,也可以是非静态的
        • 成员方法:可是是静态的成员方法,也可以是非静态的成员方法。
      • 简单记:
        • 静态只能访问静态。

2.7 你的第一个Java程序 30

2.7.1 编译和运行 31

2.8 注释和嵌入式文档 32

1
2
3
4
 /*
* 多行注释
*/
// 单行注释
2.8.1 注释文档 32

javadoc

2.8.2 语法 33
1
2
3
/**
* @注释文档
*/

javadoc只能为public 和 protected 成员进行文档注释

2.8.3 嵌入式HTML 33

支持html标记

2.8.4 一些标签示例 34
1
2
3
4
5
6
7
8
9
10
11
12
/*
* @see: classname 引用其他类
* @link: package.class#member label 用于行内,类似see
* @docRoot: 产生到文档根目录的相对路径
* @inheritDoc: 从当前类的最直接基类中继承相关文档到当前注释中
* @version: version-information
* @since: 指定代码版本,一般是jdk版本
* @param: 参数
* @return: 返回值
* @throws: 异常
* @Deprecated: 表名已不适用
*/
2.8.5 文档示例 35

2.9 编码风格 36

类首字母大写;驼峰命名法

2.10 总结 36

2.11 练习 37


第3章 操作符 38

正如作者所说,第三、第四章可快速浏览

3.1 更简单的打印语句 38

3.2 使用Java操作符 39

3.3 优先级 39

3.4 赋值 39

3.4.1 方法调用中的别名问题 40

3.5 算术操作符 41

3.5.1 一元加、减操作符 43

3.6 自动递增和递减 43

3.7 关系操作符 44

3.7.1 测试对象的等价性 44

3.8 逻辑操作符 45

3.8.1 短路 46

3.9 直接常量 47

3.9.1 指数记数法 48

3.10 按位操作符 49

3.11 移位操作符 49

只能用于整型整数

Integer.toBinaryString() : 转为二进制字符串

3.12 三元操作符 if-else 52

3.13 字符串操作符 + 和 += 53

3.14 使用操作符时常犯的错误 54

3.15 类型转换操作符 54

3.15.1 截尾和舍入 55
3.15.2 提升 56

3.16 Java没有sizeof 56

3.17 操作符小结 56

3.18 总结 63


第4章 控制执行流程 64

快速阅读此章

4.1 true和false 64

4.2 if-else 64

4.3 迭代 65

4.3.1 do-while 65
4.3.2 for 66
4.3.3 逗号操作符 67

4.4 Foreach语法 67

4.5 return 69

4.6 break和 continue 69

4.7 臭名昭著的goto 70

java没有goto,但是有标签

4.8 switch 73

4.9 总结 75


第5章 初始化与清理 76

5.1 用构造器确保初始化 76

构造方法

  • 作用概述
    • 给对象的数据进行初始化
  • 构造方法格式
    • 方法名与类名相同
    • 没有返回值类型,连void都没有
    • 没有具体的返回值
  • 构造方法注意事项
    • 如果你不提供构造方法,系统会给出默认构造方法
    • 如果你提供了构造方法,系统将不再提供
    • 构造方法也是可以重载的
  • 思考题:构造方法中可不可以有return语句呢?
    • 可以。而是我们写成这个样子就OK了:return;
    • 其实,在任何的void类型的方法的最后你都可以写上:return;

5.2 方法重载 77

方法重载:
在同一个类中,方法名相同,参数列表不同。与返回值无关。(同类同名不同参)
参数列表不同:
参数的个数不同。
参数的对应的数据类型不同。
方法重载案例
不同的类型的多个同名方法的比较。

5.2.1 区分重载方法 79
5.2.2 涉及基本类型的重载 79

5.2.3 以返回值区分重载方法 82

这是行不通的

5.3 默认构造器 83

5.4 this关键字 84

this : 是当前类的对象引用。简单的记,它就代表当前类的一个对象。

  • 注意:谁调用这个方法,在该方法内部的this就代表谁。
  • this:哪个对象调用那个方法,this就代表那个对象
  • this的场景:
    解决局部变量隐藏成员变量
5.4.1 在构造器中调用构造器 85
5.4.2 static的含义 86

5.5 清理:终结处理和垃圾回收 87

5.5.1 finalize()的用途何在 87
5.5.2 你必须实施清理 88
5.5.3 终结条件 88
5.5.4 垃圾回收器如何工作 89

5.6 成员初始化 91

5.6.1 指定初始化 93

5.7 构造器初始化 94

5.7.1 初始化顺序 94
5.7.2 静态数据的初始化 95
5.7.3 显式的静态初始化 96
5.7.4 非静态实例初始化 97

5.8 数组初始化 98

5.8.1 可变参数列表 102
1
2
3
void function(Object... args){
//args说明可变参数,0至多个
}

5.9 枚举类型 105

5.10 总结 107


第6章 访问权限控制 109

6.1 包:库单元 110

6.1.1 代码组织 110
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
包(理解)
(1)其实就是文件夹
(2)作用:
A:区分同名的类
B:对类进行分类管理
a:按照功能分
b:按照模块分
(3)包的定义(掌握)
package 包名;
多级包用.分开。
(4)注意事项:(掌握)
A:package语句必须在文件中的第一条有效语句
B:在一个java文件中,只能有一个package
C:如果没有package,默认就是无包名
(5)带包的编译和运行
A:手动式
B:自动式(掌握)
javac -d . HelloWorld.java

3:导包(掌握)
(1)我们多次使用一个带包的类,非常的麻烦,这个时候,Java就提供了一个关键字import
(2)格式:
import 包名...类名;
另一种:
import 包名...*;(不建议)
(3)package,import,class的顺序
package > import > class
6.1.2 创建独一无二的包名 111
6.1.3 定制工具库 114
6.1.4 用 import改变行为 115
6.1.5 对使用包的忠告 115

6.2 Java访问权限修饰词 116

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
	(1)权限修饰符
本类 同一个包下 不同包下的子类 不同包下的无关类
private Y
默认 Y Y
protected Y Y Y
public Y Y Y Y
(2)这四种权限修饰符在任意时刻只能出现一种。
public class Demo {}
常见的修饰符
(1)分类:
权限修饰符:private,默认,protected,public
状态修饰符:static,final
抽象修饰符:abstract
(2)常见的类及其组成的修饰
类:
默认,public,final,abstract
常用的:public

成员变量:
private,默认,protected,public,static,final
常用的:private

构造方法:
private,默认,protected,public
常用的:public

成员方法:
private,默认,protected,public,static,final,abstract
常用的:public
(3)另外比较常见的:
public static final int X = 10;
public static void show() {}
public final void show() {}
public abstract void show();
6.2.1 包访问权限 116
6.2.2 public:接口访问权限 116
6.2.3 private: 你无法访问 118
6.2.4 protected:继承访问权限 118

6.3 接口和实现 120

6.4 类的访问权限 121

6.5 总结 123


第7章 复用类 125

7.1 组合语法 125

7.2 继承语法 127

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
(1)把多个类中相同的成员给提取出来定义到一个独立的类中。然后让这多个类和该独立的类产生一个关系,
这多个类就具备了这些内容。这个关系叫继承。
单独的这个类称为父类,基类或者超类;这多个类可以称为子类或者派生类。
(2)Java中如何表示继承呢?格式是什么呢?
A:用关键字extends表示
B:格式:
class 子类名 extends 父类名 {}
(3)继承的好处:
A.提高了代码的复用性
多个类相同的成员可以放到同一个类中
B.提高了代码的维护性
如果功能的代码需要修改,修改一处即可
C.让类与类之间产生了关系,是多态的前提
其实这也是继承的一个弊端:类的耦合性很强

(4)继承的弊端:
A:让类的耦合性增强。这样某个类的改变,就会影响其他和该类相关的类。
原则:低耦合,高内聚。
耦合:类与类的关系
内聚:自己完成某件事情的能力
B:打破了封装性
(5)Java中继承的特点
A:Java中类只支持单继承
一个类只能有一个父类,不可以有多个父类。
B:Java中可以多层(重)继承(继承体系)
class A{}
class B extends A{}
class C extends B{}
(6)继承的注意事项:
A:子类不能继承父类的私有成员
B:子类不能继承父类的构造方法,但是可以通过super去访问
C:不要为了部分功能而去继承
(7)什么时候使用继承呢?
A:继承体现的是:is a的关系。
B:采用假设法
(8)Java继承中的成员关系
A:成员变量
a:子类的成员变量名称和父类中的成员变量名称不一样,这个太简单
b:子类的成员变量名称和父类中的成员变量名称一样,这个怎么访问呢?
子类的方法访问变量的查找顺序:
在子类方法的局部范围找,有就使用。
在子类的成员范围找,有就使用。
在父类的成员范围找,有就使用。
找不到,就报错。
B:构造方法
a:子类的构造方法默认会去访问父类的无参构造方法
是为了子类访问父类数据的初始化
注意:子类每一个构造方法的第一条语句默认都是:super();
b:父类中如果没有无参构造方法,怎么办?
子类通过super去明确调用带参构造
子类通过this调用本身的其他构造,但是一定会有一个去访问了父类的构造
让父类提供无参构造
C:成员方法
a:子类的成员方法和父类中的成员方法名称不一样,这个太简单
b:子类的成员方法和父类中的成员方法名称一样,这个怎么访问呢?
通过子类对象访问一个方法的查找顺序:
在子类中找,有就使用
在父类中找,有就使用
找不到,就报错
(9)两个面试题:
A:Override和Overload的区别?Overload是否可以改变返回值类型?
方法重写:
在子类中,出现和父类中一模一样的方法声明的现象。
方法重载:
同一个类中,出现的方法名相同,参数列表不同的现象。(同类同名不同参)
方法重载能改变返回值类型,因为它和返回值类型无关。

方法重载:同名同类不同参
同名:方法名相同
同类:同一作用域
不同参(参数列表):个数、类型、顺序
构造方法的重载
方法重写(覆盖):
前提条件:必须有继承
必要条件:子类方法和父类中的方法同原型(方法名、
返回值类型、形参列表完全相同)
注意:1、子类方法的访问权限不得低于父类方法的访问权限
2、子类中抛出的异常不得多于父类方法抛出的异常

返回值类型 方法名 形参列表
方法重写:必须相同 相同 相同
方法重载:无关 相同 必须不同

B:this关键字和super关键字分别代表什么?以及他们各自的使用场景和作用。
this:代表当前类的对象引用
super:代表父类存储空间的标识。(可以理解为父类的引用,通过这个东西可以访问父类的成员)
场景和作用:
A:调用成员变量
this.成员变量 调用本类的成员变量
super.成员变量 调用父类的成员变量
B:调用构造方法
this(...) 调用本类的构造方法
super(...) 调用父类的构造方法
注意事项:
this(...)或者super(...)必须出现在第一条语句上。
如果不是放在第一条语句上,就可能对父类的数据进行了多次初始化,
所以必须放在第一条语句上。
C:调用成员方法
this.成员方法 调用本类的成员方法
super.成员方法 调用父类的成员方法
(10)数据初始化的面试题
A:一个类的初始化过程
成员变量进行初始化
默认初始化
显示初始化
构造方法初始化
B:子父类的构造执行过程
先进行父类初始化,然后进行子类初始化。
C:分层初始化
(11)方法重写:子类中出现了和父类中方法声明一模一样的方法。
方法重写的注意事项:
A:父类中私有方法不能被重写
因为父类私有方法子类根本就无法继承
B:子类重写父类方法时,访问权限不能更低
最好就一致
C:父类静态方法,子类也必须通过静态方法进行重写
其实这个算不上方法重写,但是现象确实如此,至于为什么算不上方法重写,多态中我会讲解
D:子类重写父类方法的时候,最好声明一模一样
方法重写的应用:当子类需要父类的功能,而功能主体子类有自己特有内容时,可以重写父类中的方法。
这样,即沿袭了父类的功能,又定义了子类特有的内容。

方法重载:本类中出现的方法名一样,参数列表不同的方法。与返回值无关。
7.2.1 初始化基类 129

7.3 代理 130

7.4 结合使用组合和继承 132

7.4.1 确保正确清理 133
7.4.2 名称屏蔽 135

7.5 在组合与继承之间选择 137

7.6 protected关键字 138

7.7 向上转型 139

7.7.1 为什么称为向上转型 139
7.7.2 再论组合与继承 140

7.8 final关键字 140

7.8.1 final 数据 140
7.8.2 final 方法 143
7.8.3 final 类 144
7.8.4 有关final的忠告 145
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
final是最终的意思,可以修饰类,方法,变量
面试题:特点:
final可以修饰类,该类不能被继承。
final可以修饰方法,该方法不能被重写。(覆盖,复写)
final可以修饰变量,该变量不能被重新赋值。因为final修饰的变量是常量。

final修饰变量的初始化时机
A:被final修饰的变量只能赋值一次。
B:在构造方法完毕前。(非静态的常量)

final:最终的(finally,finalize)
1final修饰变量:常量,只能访问,不能改变值
定义常量时必须初始化(常量名全大写)
public static final int NUMBER = 20;
2、修饰方法:该方法不能被重写
3、修饰类:不允许有子类

面试题:final修饰局部变量的问题
基本类型:基本类型的值不能发生改变。
引用类型:引用类型的地址值不能发生改变,但是,该对象的堆内存的值是可以改变的。

7.9 初始化及类的加载 145

7.9.1 继承与初始化 146

7.10 总结 147


第8章 多态 148

8.1 再论向上转型 148

8.1.1 忘记对象类型 149

8.2 转机 150

8.2.1 方法调用绑定 150
8.2.2 产生正确的行为 151
8.2.3 可扩展性 153
8.2.4 缺陷:“覆盖”私有方法 156
8.2.5 缺陷:域与静态方法 156

8.3 构造器和多态 157

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
多态:同一个对象(事物),在不同时刻体现出来的不同状态。
多态的前提:
A:要有继承关系。
B:要有方法重写。
C:要有父类引用指向子类对象。

多态的分类:
a:具体类多态
class Fu {}
class Zi extends Fu {}

Fu f = new Zi();
b:抽象类多态
abstract class Fu {}
class Zi extends Fu {}

Fu f = new Zi();
c:接口多态
interface Fu {}
class Zi implements Fu {}

Fu f = new Zi();

多态中的成员访问特点:
A:成员变量
编译看左边,运行看左边。
B:构造方法
创建子类对象的时候,访问父类的构造方法,对父类的数据进行初始化。
C:成员方法
编译看左边,运行看右边。
由于成员方法存在方法重写,所以它运行看右边。
D:静态方法
编译看左边,运行看左边。
(静态和类相关,算不上重写,所以,访问还是左边的)
多态的好处:
A:提高了代码的维护性(继承保证(体现))
B:提高了代码的扩展性(由多态保证(体现))
多态的弊端:
不能使用子类的特有功能。

我就想使用子类的特有功能?行不行?
行。怎么用呢?
A:创建子类对象调用方法即可。(可以,但是很多时候不合理。而且,太占内存了)
B:把父类的引用强制转换为子类的引用。(向下转型)
对象间的转型问题:
向上转型:
Fu f = new Zi();
向下转型:
Zi z = (Zi)f; //要求该f必须是能够转换为Zi的。

多态:多种形态(同一函数,不同形态)
1、静态多态:程序在编译的时候就知道调用哪个方法
方法重载(Overrload)
2、动态多态:程序在运行时才确定调用哪个方法
方法重写(Override)
8.3.1 构造器的调用顺序 157
8.3.2 继承与清理 159
8.3.3 构造器内部的多态方法的行为 162
1
2
3
4
5
6
7
8
Student s = new Student();做了哪些事情?(理解)
- (1)把Student.class文件加载到内存
- (2)在栈内存为s开辟空间
- (3)在堆内存为学生对象申请空间
- (4)给学生的成员变量进行默认初始化。
- (5)给学生的成员变量进行显示初始化。
- (6)通过构造方法给成员变量进行初始化。
- (7)对象构造完毕,把地址赋值给s变量

8.4 协变返回类型 164

8.5 用继承进行设计 165

8.5.1 纯继承与扩展 166
8.5.2 向下转型与运行时类型识别 167

8.6 总结 168


Thinking in Java 4th英文版的课后习题答案: http://greggordon.org/java/tij4/solutions.htm

第9章 接口 169

需要细看

9.1 抽象类和抽象方法 169

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
一个没有具体的方法体的方法是抽象的方法。在一个类中如果有抽象方法,该类必须定义为抽象类。
(1)抽象类的特点
A:抽象类和抽象方法必须用关键字abstract修饰
B:抽象类中不一定有抽象方法,但是有抽象方法的类一定是抽象类
C:抽象类不能实例化
D:抽象类的子类
a:是一个抽象类。
b:是一个具体类。这个类必须重写抽象类中的所有抽象方法。
(2)抽象类的成员特点:
A:成员变量
有变量,有常量
B:构造方法
有构造方法,用于子类访问父类数据的初始化。
C:成员方法
有抽象,有非抽象
(3)抽象类的几个小问题
A:抽象类有构造方法,不能实例化,那么构造方法有什么用?
用于子类访问父类数据的初始化
B:一个类如果没有抽象方法,却定义为了抽象类,有什么用?
为了不让创建对象
C:abstract不能和哪些关键字共存
a:final 冲突
b:private 冲突
c:static 无意义

9.2 接口 172

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
(1)接口的特点:
A:接口用关键字interface修饰
interface 接口名 {}
B:类实现接口用implements修饰
class 类名 implements 接口名 {}
C:接口不能实例化
那么,接口如何实例化呢?
按照多态的方式来实例化。
D:接口的实现类(子类)
a:是一个抽象类。
b:是一个具体类,这个类必须重写接口中的所有抽象方法。
由此可见:
A:具体类多态(几乎没有)
B:抽象类多态(常用)
C:接口多态(最常用)
(2)接口的成员特点:
A:成员变量
只能是常量
默认修饰符:public static final
B:构造方法
没有构造方法
C:成员方法
只能是抽象的
默认修饰符:public abstract
所有的类都默认继承自一个类:Object。
类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。
(3)类与类,类与接口,接口与接口
A:类与类
继承关系,只能单继承,可以多层继承
B:类与接口
实现关系,可以单实现,也可以多实现。
还可以在继承一个类的同时,实现多个接口
C:接口与接口
继承关系,可以单继承,也可以多继承
(4)面试题:抽象类和接口的区别:
A:成员区别
抽象类:
成员变量:可以变量,也可以常量
构造方法:有
成员方法:可以抽象,也可以非抽象
接口:
成员变量:只可以常量
成员方法:只可以抽象
B:关系区别
类与类
继承,单继承
类与接口
实现,单实现,多实现
接口与接口
继承,单继承,多继承
C:设计理念区别
抽象类 被继承体现的是:”is a”的关系。抽象类中定义的是该继承体系的共性功能。
接口 被实现体现的是:”like a”的关系。接口中定义的是该继承体系的扩展功能。
抽象类:
1、如果一个类中只要有一个方法是抽象方法,该类变成抽象类
2、抽象类不能被实例化,只用来被继承
3、如果一个类继承一个抽象类,必须实现抽象类中所有的抽象方法
否则,该类也会变成一个抽象类
4、抽象类的引用可以指向子类的实例,达到多态的效果
5、构造方法和静态方法不能定义成抽象方法

接口:
1、如果一个类中所有的方法都是抽象方法,可以定义成接口
interface
2、接口中所有的方法都是抽象方法,不能包含非抽象方法,
在方法中可以省略abstract关键字
3、接口不能被实例化,只用来被实现(implements)
4、如果一个类实现一个接口,必须实现接口中所有的抽象方法,
否则该类也会变成抽象类
5、接口的引用指向实现类的实例
6、接口中所有的量都是常量,没有变量
7、接口中没有构造方法
8、为了弥补继承的单一性,接口提供了多实现(一个类可以实现
多个接口),必须要实现多个接口中提供的抽象方法
9、一个类在继承一个类的同时可以去实现接口
10、接口可以继承接口

9.3 完全解耦 174

适配器模式

9.4 Java中的多重继承 178

Java是伪多重继承模式,属于单继承、多实现结合而形成的;在写法上,继承要写在多实现前面

9.5 通过继承来扩展接口 180

9.5.1 组合接口时的名字冲突 181

9.6 适配接口 181

9.7 接口中的域 183

9.7.1 初始化接口中的域 184

9.8 嵌套接口 185

9.9 接口与工厂 186

工厂方法设计模式

9.10 总结 188


第10章 内部类 190

需要细看,后期需要时不时的回看

10.1 创建内部类 190

10.2 链接到外部类 191

10.3 使用.this与.new 193

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
(1)把类定义在另一个类的内部,该类就被称为内部类。隐含着一个指向外部类的对象引用
举例:把类B定义在类A中,类B就被称为内部类。
(2)内部类的访问规则
A:可以直接访问外部类的成员,包括私有
B:外部类要想访问内部类成员,必须创建对象
(3)内部类的分类
A:成员内部类
B:局部内部类
成员位置:在成员位置定义的类,被称为成员内部类。
局部位置:在局部位置定义的类,被称为局部内部类。
(4)成员内部类
A:private 为了数据的安全性
B:static 为了访问的方便性
如何直接访问内部类的成员:
外部类名.内部类名 对象名 = 外部类对象.内部类对象;
成员内部类不是静态的:
外部类名.内部类名 对象名 = new 外部类名.new 内部类名();
成员内部类是静态的:
外部类名.内部类名 对象名 = new 外部类名.内部类名();

注意:静态内部类访问的外部类数据必须用静态修饰。
(5)局部内部类
局部内部类访问局部变量的注意事项?
A:局部内部类访问局部变量必须加final修饰。
B:为什么呢?
因为局部变量使用完毕就消失,而堆内存的数据并不会立即消失。
所以,堆内存还是用该变量,而改变量已经没有了。
为了让该值还存在,就加final修饰。
通过反编译工具我们看到了,加入final后,堆内存直接存储的是值,而不是变量名。

10.4 内部类与向上转型 194

10.5 在方法和作用域内的内部类 195

10.6 匿名内部类 196

1
2
3
4
5
6
7
8
9
10
11
12
13
14
	A:是局部内部类的简化形式
B:前提
存在一个类或者接口
C:格式:
new 类名或者接口名() {
重写方法;
}
D:本质:
其实是继承该类或者实现接口的子类匿名对象
E:匿名内部类中用到外部参数时,外部参数必须是final修饰
匿名内部类在开发中的使用
我们在开发的时候,会看到抽象类,或者接口作为参数。
而这个时候,我们知道实际需要的是一个子类对象。
如果该方法仅仅调用一次,我们就可以使用匿名内部类的格式简化。
10.6.1 再访工厂方法 199

10.7 嵌套类 201

内部类声明static,即为嵌套类,这时,就不包含外围对象的引用了,也只能访问外部的static成员

10.7.1 接口内部的类 202

接口可以有内部类

10.7.2 从多层嵌套类中访问外部类的成员 203

10.8 为什么需要内部类 204

10.8.1 闭包与回调 205
10.8.2 内部类与控制框架 207

10.9 内部类的继承 212

10.10 内部类可以被覆盖吗 212

10.11 局部内部类 214

10.12 内部类标识符 215

10.13 总结 215


第11章 持有对象 216

这一章是初步介绍容器也就是集合的知识点:List、Set、Map、Queue

11.1 泛型和类型安全的容器 216

11.2 基本概念 219

11.3 添加一组元素 220

1
2
3
Arrays.asList()
Collections.addAll()
collection.addAll()

11.4 容器的打印 221

11.5 List 223

ArrayList LinkedList

11.6 迭代器 226

11.6.1 ListIterator 227

ListIterator是一个功能更加强大的, 它继承于Iterator接口,只能用于各种List类型的访问。可以通过调用listIterator()方法产生一个指向List开始处的ListIterator, 还可以调用listIterator(n)方法创建一个一开始就指向列表索引为n的元素处的ListIterator。只用于list集合

ListIterator 与Iterator 的区别:

(1)ListIterator有add()方法,可以向List中添加对象,而Iterator不能
(2)ListIterator和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向(顺序向前)遍历。Iterator就不可以。
(3)ListIterator可以定位当前的索引位置,nextIndex()和previousIndex()可以实现。Iterator没有此功能。
(4)都可实现删除对象,但是ListIterator可以实现对象的修改,set()方法可以实现。Iierator仅能遍历,不能修改。

11.7 LinkedList 228

11.8 Stack 229

先进后出,可以将LinkedList作为Stack使用

11.9 Set 231

不重复元素

11.10 Map 233

11.11 Queue 236

先进先出,LinkedList实现了此接口

11.11.1 PriorityQueue 237

优先级队列,有序队列

11.12 Collection和Iterator 238

重点在于Iterator 接口思想,与下面的Foreach一样,理解Iterator 原理

11.13 Foreach与迭代器 241

实现Iterable接口的Iterator 方法皆可用于foreach

11.13.1 适配器方法惯用法 243

适配器模式实现Iterator 方法

11.14 总结 248


第12章 通过异常处理错误 248

12.1 概念 249

12.2 基本异常 249

12.2.1 异常参数 250

12.3 捕获异常 250

12.3.1 try块 250
12.3.2 异常处理程序 250

12.4 创建自定义异常 251

12.4.1 异常与记录日志 253

12.5 异常说明 256

12.6 捕获所有异常 256

12.6.1 栈轨迹 257

12.6.2 重新抛出异常 258

12.6.3 异常链 260

12.7 Java标准异常 263

Throwable

​ —Error

​ —Exception

​ ——RuntimeException

​ ——非RuntimeException

12.7.1 特例:RuntimeException 263

12.8 使用finally进行清理 264

12.8.1 finally用来做什么 265
12.8.2 在return中使用finally 267
12.8.3 缺憾:异常丢失 268

某些情况下,使用finally会使异常丢失:前一个异常还没处理就抛出另一个异常

12.9 异常的限制 269

继承上的限制

12.10 构造器 271

在创建需要清理的对象之后,立即进入一个try—finally块

12.11 异常匹配 275

子类异常可匹配父类异常

12.12 其他可选方式 276

源于异常的来源以及其他处理方式,重点在于理解

12.12.1 历史 277
12.12.2 观点 278
12.12.3 把异常传递给控制台 279
12.12.4 把“被检查的异常”转换为“不受检查的异常” 279

12.13 异常使用指南 281

12.14 总结 281

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
(1)程序出现的不正常的情况。
1、编译时异常:语法错误
2、运行时异常:逻辑错误(数组下标越界)
(2)异常的体系
Throwable
|--Error 严重问题,我们不处理,比如说内存溢出。
|--Exception
|--RuntimeException 运行期异常,这种问题我们也不处理,因为是你的问题,而且这个问题出现肯定是我们的代码不够严谨,需要修正代码的。
|--非RuntimeException 编译期异常,必须处理的,否则程序编译不通过
(3)异常的处理:
A:JVM的默认处理
把异常的名称,原因,位置等信息输出在控制台,同时会结束程序。
B:自己处理
a:try...catch...finally
自己编写处理代码,后面的程序可以继续执行
b:throws
把自己处理不了的,在方法上声明,告诉调用者,这里有问题,这个格式必须跟在方法的括号后面。

try...catch...finally的处理格式:
try {
可能出现问题的代码;
}catch(异常名 变量) {
针对问题的处理;
}finally {
释放资源;
}
(4)面试题
A:编译期异常和运行期异常的区别?
编译期异常 必须要处理的,否则编译不通过
运行期异常 可以不处理,也可以处理
B:throwthrows是的区别
throws
用在方法声明后面,跟的是异常类名
可以跟多个异常类名,用逗号隔开
表示抛出异常,由该方法的调用者来处理
throws表示出现异常的一种可能性,并不一定会发生这些异常
throw
用在方法体内,跟的是异常对象名
只能抛出一个异常对象名
表示抛出异常,由方法体内的语句处理
throw则是抛出了异常,执行throw则一定抛出了某种异常
(5)finally关键字及其面试题
A:finally用于释放资源,它的代码永远会执行。特殊情况:在执行到finally之前jvm退出了
B:面试题
a:final,finally,finalize的区别?
final:最终的意思,可以修饰类,成员变量,成员方法
修饰类,类不能被继承
修饰变量,变量是常量
修饰方法,方法不能被重写
finally:是异常处理的一部分,用于释放资源。
一般来说,代码肯定会执行,特殊情况:在执行到finally之前jvm退出了
finalize:是Object类的一个方法,用于垃圾回收

b:如果在catch里面有return,请问finally还执行吗?如果执行,在return前还是后?

会,前。实际上在中间。

C:异常处理的变形
try...catch...finally
try...catch...
try...catch...catch...
try...catch...catch...fianlly
try...finally 这种做法的目前是为了释放资源。

注意:
A:try里面的代码越少越好
B:catch里面必须有内容,哪怕是给出一个简单的提示

注意事项:
1:能明确的尽量明确,不要用大的来处理。
2:平级关系的异常谁前谁后无所谓,如果出现了子父关系,父必须在后面。

注意:
一旦try里面出了问题,就会在这里把问题给抛出去,然后和catch里面的问题进行匹配,
一旦有匹配的,就执行catch里面的处理,然后结束了try...catch继续执行后面的语句。

d.JDK7出现了一个新的异常处理方案:
try{

}catch(异常名1 | 异常名2 | ... 变量 ) {
...
}

注意:这个方法虽然简洁,但是也不够好。
A:处理方式是一致的。(实际开发中,好多时候可能就是针对同类型的问题,给出同一个处理)
B:多个异常间必须是平级关系。
(6)自定义异常
继承自Exception或者RuntimeException,只需要提供无参构造和一个带参构造即可

自定义异常:
1、定义一个类继承Exception类
2、定义一个带参数的构造方法
3、调用父类带参数的构造方法

public class MyException extends Exception {
public MyException() {
}

public MyException(String message) {
super(message);
}
}

(7)异常的注意实现
A:父的方法有异常抛出,子的重写方法在抛出异常的时候必须要小于等于父的异常
B:父的方法没有异常抛出,子的重写方法不能有异常抛出
C:父的方法抛出多个异常,子的重写方法必须比父少或者小

异常注意事项:
A:子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类。(父亲坏了,儿子不能比父亲更坏)
B:如果父类抛出了多个异常,子类重写父类时,只能抛出相同的异常或者是他的子集,子类不能抛出父类没有的异常
C:如果被重写的方法没有异常抛出,那么子类的方法绝对不可以抛出异常,如果子类方法内有异常发生,那么子类只
try,不能throws

8)异常中要了解的几个方法:
public String getMessage():异常的消息字符串
public String toString():返回异常的简单信息描述此对象的类的 name(全路径名)
": "(冒号和一个空格) 调用此对象getLocalizedMessage()方法的结果
(默认返回的是getMessage()的内容)
printStackTrace() 获取异常类名和异常信息,以及异常出现在程序中的位置。返回值void
把信息输出在控制台。

Exception类中的方法:
getMessage():获得异常相关的描述信息(获得异常产生的原因)
printStackTrace():获得异常相关的描述信息(包括异常产生的
原因以及异常产生的位置)

第13章 字符串 283

13.1 不可变String 283

13.2 重载“+”与StringBuilder 283

每一个+号,意味着new了一个StringBuilder 对象

13.3 无意识的递归 287

13.4 String上的操作 288

13.5 格式化输出 289

13.5.1 printf() 289

%d 整数;%f 浮点型;%s字符串

13.5.2 System.out.format() 289

等价于printf(),此方法适用于PrintStream或者PrintWriter对象

13.5.3 Formatter类 290

格式化输出

13.5.4 格式化说明符 291

空格对齐

13.5.5 Formatter转换 292

Formatter.formatter()

13.5.6 String.format() 294

String.format()内部还是调用Formatter.formatter()

13.6 正则表达式 295

13.6.1 基础 295
1
2
3
4
5
6
7
8
9
1. 可能有一个负号在最前:-?   即?号表示可能存在
2. 在正则表达式中,\d表示一位数字,在Java中,反斜杠需要转义,即\\d表示一位数字
3. \\\\普通的反斜杠
4. 换行和制表符之类的只需要单个反斜杠:\n\t
5. 一个或多个之前的表达式:+
-?\\d+ :表示可能有一个负号,后面跟着一位或多位数字
6. | 表示或者,(-|\\+)?\\d+ 表示以一个加号或减号开头(可能都没有,因为后面有个问号)的数字,由于字符+在正则表达式中有特殊含义,需要\\转义
7. \W(Java中需要写成\\W):非单词字符
8. \w(Java中需要写成\\w):一个单词字符
13.6.2 创建正则表达式 297

jdk1.6的正则表达式:

13.6.3 量词 299

CharSequence接口,正则表达式能接受此接口类型的参数

13.6.4 Pattern和Matcher 300

相关方法的用法

13.6.5 split() 305
1
2
3
split(CharSequence input)
split(CharSequence input, int limit)
limit表示分割后数组的大小,限制分割
13.6.6 替换操作 306

replace相关操作

13.6.7 reset() 307
13.6.8 正则表达式与Java I/O 307

13.7 扫描输入 309

Scanner 类是jdk1.5新加入的

13.7.1 Scanner定界符 310

默认空白字符分割,可以使用正则表达式指定

scanner.useDelimiter(pattern)

13.7.2 用正则表达式扫描 311
1
2
3
4
scanner.next(pattern);
MatchResult match = scanner.match();
match.group(1);
match.group(1);

13.8 StringTokenizer 312

作者说基本上可以放弃了,使用正则表达式或者Scanner就可以了

13.9 总结 312


Thinking in Java 4th英文版的课后习题答案: http://greggordon.org/java/tij4/solutions.htm

第14章 类型信息 313

14.1 为什么需要RTTI 313

RTTI(Run-Time Type Identification),通过运行时类型信息程序能够使用基类指针或引用来检查这些指针或引用所指的对象的实际派生类型。—-百度百科

14.2 Class对象 314

14.2.1 类字面常量 318

14.2.2 泛化的Class引用 320
1
2
3
4
Class<?> class
Class<? extends Number> class
Class<? super Number> class
Class对象的newInstance()方法将返回该对象的确切类型(排除为不确定的超类)
14.2.3 新的转型语法 322
1
在强制转型报错的情况下仍需要转型,可以用Class类的cast()方法

14.3 类型转换前先做检查 322

cat instanceof Cat 判断某个对象是否属于某个类,返回布尔值

14.3.1 使用类字面常量 327
14.3.2 动态的instanceof 329
1
Class类的isInstance()方法:判断对象类型
14.3.3 递归计数 330
1
Class的isAssignableFeom()方法判断是否来自某个继承体系

14.4 注册工厂 331

14.5 instanceof 与 Class的等价性 333

14.6 反射:运行时的类信息 334

反射包含Field|Method|Constructor类

14.6.1 类方法提取器 335

其对应的getMethod()、getConstructor()、getField()方法获取相应数组

14.7 动态代理 337

1
Proxy.newProxyInstance()方法可以创建动态代理

14.8 空对象 341

不太理解

14.8.1 模拟对象与桩 346

14.9 接口与类型信息 346

通过反射技术,在提供对象、方法名时,可以实现调用任何修饰权限的方法

14.10 总结 350


第15章 泛型 352

需重读

15.1 与C++的比较 352

15.2 简单泛型 353

15.2.1 一个元组类库 354
1
2
3
4
5
写法为:
public class Demo<A,B>{
A,B两个成员变量
构造函数中传入AB,赋值
}
15.2.2 一个堆栈类 356
15.2.3 RandomList 357

15.3 泛型接口 358

  • 例子代码:

基本类型无法作为参数类型,但可以自动装箱

15.4 泛型方法 361

1
2
泛型参数列表置于返回值前:
public <T> void f(T t){}

15.4.1 杠杆利用类型参数推断 362

15.4.2 可变参数与泛型方法 363
1
public <T> void f(T... args){}
15.4.3 用于Generator的泛型方法 364

在生成器中用泛型是十分合适的

15.4.4 一个通用的Generator 364

15.4.5 简化元组的使用 366

15.4.6 一个Set实用工具 367

15.5 匿名内部类 369

内部类、匿名内部类也可用于泛型中

15.6 构建复杂模型 371

15.7 擦除的神秘之处 372

擦除:在泛型代码内部,无法获得任何有关泛型参数类型的信息

可用 <? extend Circle> 方式控制边界

15.7.1 C++的方式 373
15.7.2 迁移兼容性 375
15.7.3 擦除的问题 376
15.7.4 边界处的动作 377

15.8 擦除的补偿 380

15.8.1 创建类型实例 381
15.8.2 泛型数组 383

15.9 边界 386

15.10 通配符 389

15.10.1 编译器有多聪明 391
15.10.2 逆变 393
15.10.3 无界通配符 395
15.10.4 捕获转换 399

15.11 问题 400

15.11.1 任何基本类型都不能作为类型参数 400
15.11.2 实现参数化接口 401
15.11.3 转型和警告 402
15.11.4 重载 403
15.11.5 基类劫持了接口 404

15.12 自限定的类型 404

15.12.1 古怪的循环泛型 404
15.12.2 自限定 405
15.12.3 参数协变 407

15.13 动态类型安全 409

15.14 异常 410

15.15 混型 412

15.15.1 C++中的混型 412
15.15.2 与接口混合 413
15.15.3 使用装饰器模式 414
15.15.4 与动态代理混合 415

15.16 潜在类型机制 416

15.17 对缺乏潜在类型机制的补偿 420

15.17.1 反射 420
15.17.2 将一个方法应用于序列 421
15.17.3 当你并未碰巧拥有正确的接口时 423
15.17.4 用适配器仿真潜在类型机制 424

15.18 将函数对象用作策略 426

15.19 总结:转型真的如此之糟吗? 430

15.19.1 进阶读物 432

第16章 数组 433

16.1 数组为什么特殊 433

16.2 数组是第一级对象 434

对象数组保存的是引用,基本类型数组直接保存值

16.3 返回一个数组 436

16.4 多维数组 437

1
Arrays.deepToString()方法可以打印数组为字符串

16.5 数组与泛型 440

16.6 创建测试数据 442

16.6.1 Arrays.fill() 442

同一个值填充数组

16.6.2 数据生成器 443
16.6.3 从Generator中创建数组 447

16.7 Arrays实用功能 450

16.7.1 复制数组 450
1
System.arraycopy() 复制数组  比for循环要快  对于对象数组,复制属于浅复制(只复制引用)
16.7.2 数组的比较 451
1
Arrays.equals()
16.7.3 数组元素的比较 452
1
实现java.lang.Comparable接口
16.7.4 数组排序 454
1
Arrays.sort()
16.7.5 在已排序的数组中查找 455
1
在已排序的数组中查找,使用Arrays.binarySearch()

16.8 总结 457


第17章 容器深入研究 459

17.1 完整的容器分类法 459

17.2 填充容器 460

17.2.1 一种Generator解决方案 460
17.2.2 Map生成器 462
17.2.3 使用Abstract类 464

17.3 Collection的功能方法 470

17.4 可选操作 472

17.4.1 未获支持的操作 473

17.5 List的功能方法 474

17.6 Set和存储顺序 477

17.6.1 SortedSet 479

17.7 队列 480

17.7.1 优先级队列 481
17.7.2 双向队列 482

17.8 理解Map 483

17.8.1 性能 484
17.8.2 SortedMap 486
17.8.3 LinkedHashMap 487

17.9 散列与散列码 488

17.9.1 理解hashCode() 490
17.9.2 为速度而散列 492
17.9.3 覆盖hashCode() 495

17.10 选择接口的不同实现 499

17.10.1 性能测试框架 499
17.10.2 对List的选择 502
17.10.3 微基准测试的危险 507
17.10.4 对Set的选择 508
17.10.5 对Map的选择 509

17.11 实用方法 512

17.11.1 List的排序和查询 514
17.11.2 设定Collection或Map为不可修改 515
17.11.3 Collection或Map的同步控制 516

17.12 持有引用 518

17.12.1 WeakHashMap 519

17.13 Java 1.0/1.1 的容器 520

17.13.1 Vector 和 Enumeration 520
17.13.2 Hashtable 521
17.13.3 Stack 521
17.13.4 BitSet 522

17.14 总结 524


第18章 Java I/O系统 525

18.1 File类 525

18.1.1 目录列表器 525

18.1.2 目录实用工具 528

18.1.3 目录的检查及创建 532

18.2 输入和输出 533

18.2.1 InputStream类型 534

18.2.2 OutputStream类型 535

18.3 添加属性和有用的接口 535

18.3.1 通过FilterInputStream从InputStream

读取数据 535

18.3.2 通过FilterOutPutStream向Output-

Stream写入 536

18.4 Reader和Writer 537

18.4.1 数据的来源和去处 537

18.4.2 更改流的行为 538

18.4.3 未发生变化的类 539

18.5 自我独立的类:RandomAccessFile 539

18.6 I/O流的典型使用方式 539

18.6.1 缓冲输入文件 540

18.6.2 从内存输入 540

18.6.3 格式化的内存输入 541

18.6.4 基本的文件输出 542

18.6.5 存储和恢复数据 543

18.6.6 读写随机访问文件 544

18.6.7 管道流 545

18.7 文件读写的实用工具 545

18.7.1 读取二进制文件 548

18.8 标准I/O 548

18.8.1 从标准输入中读取 548

18.8.2 将System.out转换成PrintWriter 549

18.8.3 标准I/O重定向 549

18.9 进程控制 550

18.10 新I/O 551

18.10.1 转换数据 554

18.10.2 获取基本类型 556

18.10.3 视图缓冲器 557

18.10.4 用缓冲器操纵数据 560

18.10.5 缓冲器的细节 560

18.10.6 内存映射文件 563

18.10.7 文件加锁 566

18.11 压缩 568

18.11.1 用GZIP进行简单压缩 568

18.11.2 用Zip进行多文件保存 569

18.11.3 Java档案文件 570

18.12 对象序列化 571

18.12.1 寻找类 574

18.12.2 序列化的控制 575

18.12.3 使用“持久性” 581

18.13 XML 586

18.14 Preferences 588

18.15 总结 589


第19章 枚举类型 590

19.1 基本enum特性 590

19.1.1 将静态导入用于enum 591

19.2 向enum中添加新方法 591

19.2.1 覆盖enum的方法 592

19.3 switch语句中的enum 593

19.4 values()的神秘之处 594

19.5 实现,而非继承 596

19.6 随机选取 596

19.7 使用接口组织枚举 597

19.8 使用EnumSet替代标志 600

19.9 使用EnumMap 602

19.10 常量相关的方法 603

19.10.1 使用enum的职责链 606

19.10.2 使用enum的状态机 609

19.11 多路分发 613

19.11.1 使用enum分发 615

19.11.2 使用常量相关的方法 616

19.11.3 使用EnumMap分发 618

19.11.4 使用二维数组 618

19.12 总结 619


第20章 注解 620

20.1 基本语法 620

20.1.1 定义注解 621

20.1.2 元注解 622

20.2 编写注解处理器 622

20.2.1 注解元素 623

20.2.2 默认值限制 624

20.2.3 生成外部文件 624

20.2.4 注解不支持继承 627

20.2.5 实现处理器 627

20.3 使用apt处理注解 629

20.4 将观察者模式用于apt 632

20.5 基于注解的单元测试 634

20.5.1 将@Unit用于泛型 641

20.5.2 不需要任何“套件” 642

20.5.3 实现@Unit 642

20.5.4 移除测试代码 647

20.6 总结 649


第21章 并发 650

21.1 并发的多面性 651

21.1.1 更快的执行 651

21.1.2 改进代码设计 653

21.2 基本的线程机制 653

21.2.1 定义任务 654

21.2.2 Thread类 655

21.2.3 使用Executor 656

21.2.4 从任务中产生返回值 658

21.2.5 休眠 659

21.2.6 优先级 660

21.2.7 让步 661

21.2.8 后台线程 662

21.2.9 编码的变体 665

21.2.10 术语 669

21.2.11 加入一个线程 669

21.2.12 创建有响应的用户界面 671

21.2.13 线程组 672

21.2.14 捕获异常 672

21.3 共享受限资源 674

21.3.1 不正确地访问资源 674

21.3.2 解决共享资源竞争 676

21.3.3 原子性与易变性 680

21.3.4 原子类 684

21.3.5 临界区 685

21.3.6 在其他对象上同步 689

21.3.7 线程本地存储 690

21.4 终结任务 691

21.4.1 装饰性花园 691

21.4.2 在阻塞时终结 694

21.4.3 中断 695

21.4.4 检查中断 701

21.5 线程之间的协作 702

21.5.1 wait()与notifyAll() 703

21.5.2 notify()与notifyAll() 707

21.5.3 生产者与消费者 709

21.5.4 生产者-消费者与队列 713

21.5.5 任务间使用管道进行输入/输出 717

21.6 死锁 718

21.7 新类库中的构件 722

21.7.1 CountDownLatch 722

21.7.2 CyclicBarrier 724

21.7.3 DelayQueue 726

21.7.4 PriorityBlockingQueue 728

21.7.5 使用ScheduledExecutor的温室控

制器 730

21.7.6 Semaphore 733

21.7.7 Exchanger 735

21.8 仿真 737

21.8.1 银行出纳员仿真 737

21.8.2 饭店仿真 741

21.8.3 分发工作 744

21.9 性能调优 748

21.9.1 比较各类互斥技术 748

21.9.2 免锁容器 754

21.9.3 乐观加锁 760

21.9.4 ReadWriteLock 761

21.10 活动对象 763

21.11 总结 766

21.12 进阶读物 767


第22章 图形化用户界面 768

22.1 applet 769

22.2 Swing基础 769

22.2.1 一个显示框架 771

22.3 创建按钮 772

22.4 捕获事件 773

22.5 文本区域 774

22.6 控制布局 776

22.6.1 BorderLayout 776

22.6.2 FlowLayout 776

22.6.3 GridLayout 777

22.6.4 GridBagLayout 777

22.6.5 绝对定位 778

22.6.6 BoxLayout 778

22.6.7 最好的方式是什么 778

22.7 Swing事件模型 778

22.7.1 事件与监听器的类型 779

22.7.2 跟踪多个事件 783

22.8 Swing组件一览 785

22.8.1 按钮 785

22.8.2 图标 787

22.8.3 工具提示 788

22.8.4 文本域 789

22.8.5 边框 790

22.8.6 一个迷你编辑器 791

22.8.7 复选框 792

22.8.8 单选按钮 793

22.8.9 组合框 793

22.8.10 列表框 794

22.8.11 页签面板 796

22.8.12 消息框 796

22.8.13 菜单 798

22.8.14 弹出式菜单 802

22.8.15 绘图 803

22.8.16 对话框 805

22.8.17 文件对话框 808

22.8.18 Swing组件上的HTML 809

22.8.19 滑块与进度条 810

22.8.20 选择外观 811

22.8.21 树、表格和剪贴板 812

22.9 JNLP与Java Web Start 812

22.10 Swing与并发 816

22.10.1 长期运行的任务 816

22.10.2 可视化线程机制 822

22.11 可视化编程与JavaBean 823

22.11.1 JavaBean是什么 824

22.11.2 使用Introspector抽取出BeanInfo 825

22.11.3 一个更复杂的Bean 829

22.11.4 JavaBean与同步 831

22.11.5 把Bean打包 834

22.11.6 对Bean更高级的支持 835

22.11.7 有关Bean的其他读物 836

22.12 Swing的可替代选择 836

22.13 用Flex构建Flash Web客户端 836

22.13.1 Hello, Flex 837

22.13.2 编译MXML 838

22.13.3 MXML与ActionScript 838

22.13.4 容器与控制 839

22.13.5 效果与样式 840

22.13.6 事件 841

22.13.7 连接到Java 841

22.13.8 数据模型与数据绑定 843

22.13.9 构建和部署 843

22.14 创建SWT应用 844

22.14.1 安装SWT 845

22.14.2 Hello, SWT 845

22.14.3 根除冗余代码 847

22.14.4 菜单 848

22.14.5 页签面板、按钮和事件 849

22.14.6 图形 852

22.14.7 SWT中的并发 853

22.14.8 SWT还是Swing 855

22.15 总结 855

22.15.1 资源 855


书籍相关资源:

书中demo: https://github.com/BruceEckel/TIJ4-code
Thinking in Java 4th英文版的课后习题答案: http://greggordon.org/java/tij4/solutions.htm

附录A 补充材料 856

附录B 资源 859

索引 863