Java编程思想第三版摘录
===========
Chap1
对象简介
1.
抽象的过程
Alan Kay
总结了
Smalltalk
的五项基本特征。这些特征代表了纯的面向对象的编程方法:
(1).
万物皆对象。将对象想成一种特殊的变量;它存储数据,而且还可以让你“提要求”,命令它进行某些操作。从理论上讲,你可以把所有待解决的问题中的概念性组件(狗,建筑,服务等)都标识成程序里的对象。
(2).
程序就是一组相互之间传递消息的对象。你只要向那个对象“发一个消息”,就能向它提出要求。更确切的说,你可以这样认为,消息是调用专属某个对象的方法的请求。
(3).
每个对象都利用别的对象来组建它自己的记忆。换言之,你通过将已有的对象打成一个包,来创建新的对象。由此,你可以将程序的复杂性,隐藏在对象的简单性之下。
(4).
对象都有类型。任何对象都是某个类的实例
(instance of a class)
。用以区分类的最突出的特点就是“你能传给它什么消息?”
(5).
所有属于同一类型的对象能接受相同的消息。这种互换性
(substitutability)
是
OOP
最强大的功能之一。
Booch
还给对象下了个更为简洁的定义:
对象有状态,行为和标识。
这就是说,对象可以有内部数据(状态),有方法(因而产生了行为),以及每个对象都能同其它对象区分开来--具体而言,每个对象在内存里都有唯一的地址。
这句话或许有点太过了。因为对象还能存在于另一台及其上以及不同的内存空间中,此外还能保存在硬盘上。在这种情况下,对象的身份就不能用内存地址,而必须要用别的方法来确定。
2.
可凭借多态性相互替换的对象
非
OOP
的编译器的做法称为前绑定
(early binding)
。编译器会产生那个名字的函数的调用,而连接器负责将这个调用解析成须执行的代码的绝对地址。在
OOP
中,不到运行的时候,程序没法确定代码的地址,所以向泛型对象发送一个消息的时候,就要用到一些特别的手段。
OOP
语言用了后绑定
(late binding)
的概念。当你向某个对象送了一个消息后,不到运行时,系统不能确定到底该调用哪段代码。编译器只保证这个方法存在,并且检查参数和返回值的类型(不这么做的语言属于弱类型
weakly typed
),但是它并不知道具体执行的是哪段代码。
在有些语言中,你必须明确申明,某个方法要用到后绑定的灵活性(
C++
用
virtual
关键字)。在这些语言中,方法不是默认地动态绑定的。而动态绑定是
Java
的缺省行为,因此无需添加什么额外的关键词就能获得多态性。
将派生类当作它的基类来用的过程称为上传(
upcast
),反之称为下传(
downcast
)。下传所需的运行时检查会引起程序运行效率的降低,也加重了编程的负担。解决方案就是参数化类型
(parameterized type)
机制,即泛型。
3.Collection
和迭代器
ArrayList
和
LinkedList
,都是简单的线性序列,具有相同的接口和外部行为。对于
ArrayList
,随机访问是一种时间恒定的操作。然而对于
LinkedList
,随机访问和选取元素的代价会很大。另一方面,如果要在序列中插入元素,
LinkedList
的效率会比
ArrayList
的高出许多。
=============
Chap2
万物皆对象
1.
数据存在哪里
数据可以存储在以下六个地方:
(1).
寄存器
(registers)
。这是反应最快的存储,因为它处在
CPU
里。但寄存器数量有限,由编译器分配,你不能直接控制。
(2).
栈
(stack)
。位于常规内存区里,
CPU
可以通过栈指针对它进行直接访问。栈指针下移就创建新的存储空间,上移就释放内存空间。这是仅次于寄存器的最快、最有效率的分配内存的方法。由于
Java
编译器必须生成能控制栈指针上下移的代码,所以程序编译的时候,那些将被存储在栈中的数据的大小和生命周期必须是已知的。
Java
把对象的
reference
存放在栈里。
(3).
堆
(heap)
。这是一段多用途的内存池,所有
Java
对象都保存在这里。在堆中分配空间时,编译器无需知道该分配多少空间,或数据会在堆里待多长时间。但是其速度比分配栈的慢些。
(4).
静态存储
(static storage)
。这里“静态”的意思是“在固定的位置”
(
尽管还是在
RAM
里面
)
。静态存储里面的数据在整个程序运行期间都能访问到。可以用
static
关键词指明对象的某个元素是静态的,但是
Java
对象本身是决不会放到静态存储中去的。
(5).
固定存储
(constant storage)
。常量值通常直接放在程序里。有时常量还能为自己设置界限,这样在嵌入式系统中,就能选择是不是把它们放到
ROM
里面去。
(6).
非内存的存储
(Non-RAM storage)
。如果数据完全独立于程序,那么即使程序不运行,它也应该还在。对象被转化成某种能保存在其它介质上的东西,要用的时候,又能在内存里重建。
Java
提供了轻量级
persistence
的支持。
特例:
primitive
类型
primitive(
原始
)
类型的变量直接保存值,并且存储在栈中。
高精度的数值
Java
还包括两个能进行高精度算术运算的类:
BigInteger
和
BigDecimal
。
作用域
int x = 12;
{
int x = 100;//illegal
}
2.
创建新的数据类型:类
只有在“变量被用作类的成员”时,
Java
才能确保它获得默认值。本地变量,没有这种保障。
不管在哪种情况下,
Java
在传递对象的时候,实际上是在传递
reference
。
============
Chap3
控制程序流程
1.
运算符
逗号运算符
Java
里面,唯一一个把逗号当运算符用的地方是
for
循环。
String
的
+
运算符
加号
(+)
用在
String
上的时候,如果表达式中有
String
,那么
Java
编译器会把其他的操作数都转换成
String
。
Java
没有
sizeof
C
和
C++
的
sizeof()
用于获取数据要占用多少字节的内存,需要
sizeof
的主要原因是为了移植。相同的数据类型在不同的机器上占用的内存长度可能会不一样。
Java
没有移植的问题,因此不需要
sizeof
,所有数据类型在所有的机器上都是相同的。
运算符的总结
在进行数学运算或混和赋值的时候,
char
,
byte
,
short
,都会先进行提升,运算结果也是
int
。如果要把结果赋给原先那个变量,就必须明确地进行类型转换。
除了
boolean
之外,所有的
primitive
类型都能被转换成其它的
primitive
类型。
2.
执行控制
Java
不允许把数字当作
boolean
用,尽管
C
和
C++
允许这么做(非零值表示
true
,零表示
false
)。
Java
里,唯一能放标签的地方,就是在循环语句的外面。而且必须直接放--在循环语句和标签之间不能有任何东西。而这么做的唯一理由就是,你会嵌套多层循环或选择。因为通常情况下
break
和
continue
关键词只会中断当前循环,而用了标签后,就会退到
label
所在的地方。
label1:
outer-iteration{
inner-iteration{
break;//
中断内循环,退到外循环
continue;//
中断本次内循环,重新移到内循环开始处,执行下次内循环
continue label1;//
中断本次外循环,移到外循环开始处,重新执行下次外循环
break label1;//
退出外循环,执行循环以后的语句
}
}
如果退出循环或选择的同时,还要退出方法,可以直接使用
return
。
continue
,
break
以及
label
的规则:
(1).
普通的
continue
会退到内部循环的最开始,然后继续执行内部循环。
(2).
带标签的
continue
会跳转到标签,并且重新进入直接跟在标签后面的循环。
(3).break
会从循环的“底部溜出去”。
(4).
带标签的
break
会从由这个标签标识的循环的“底部溜出去”。
在
Java
里能使用标签的唯一理由就是,在嵌套循环的同时要用
break
和
continue
退出多层循环。
3.switch
switch
会根据整数表达式的值(可以是
char
)决定应该运行哪些代码。
找到匹配的值后,就会执行相应的
case
语句,不会再进行比较。通常
case
语句应该以
break
结束。否则会直接执行下一个
case
语句,而不会再次进行匹配。如果没有匹配的
case
,则执行
default
语句。
计算细节
span







评论排行榜