- 浏览: 39482 次
- 性别:
- 来自: 唐山
文章分类
最新评论
一、第一章 对象导论
1、Alan Kay总结了面向对象的五个特性:
1) 万物皆为对象
2) 程序是对象的集合,它们通过发送消息来告知彼此所要做的
3) 每个对象都有自己的由其他对象所构成的存储
4) 每个对象都有其类型
5) 某一特定类型的所有对象都可以接收同样的消息
Booch的描述:对象具有状态、行为和标识。
2、UML:Unified Modelling Language, 统一建模语言。
UML结构
3、通过继承而产生的类型具有等价性,即:导出类与基类具有相同的类型。
4、使基类与导出类产生差异的两种方法:
1) 直接在导出类中添加新方法(is-like-a)
2) 改变现有基类的方法的行为--覆盖(overriding),这叫替代原则,即“纯粹替代”(is-a)
5、多态使用了“后期绑定”的概念,它通过“向上转型”(upcasting)来实现。
6、抽象方法(abstract)只能在抽象类内部创建,当该类被继承时,抽象方法必须被实现,否则继承类仍然是一个抽象类。
7、Java完全采用在被称为堆(heap)的内存池中动态地创建对象。每当想要创建新的对象时,就要使用new关键字来构建此对象的实例。与此不同的是,C++除了在堆中创建对象外,还可以在堆栈中创建对象。
8、Java的单根继承结构,使垃圾回收器的实现变得容易。
二、第二章 一切都是对象
1、存储数据的六个地方
1) 寄存器:编译器决定
2) 堆栈: 堆栈指针若向下移动,则分配新的内存;
若向上移动,则释放那些内存。
对象的引用而非对象存在此。
3) 堆:存放所有的Java对象;
4) 静态存储:RAM中固定的位置;
5) 常量存储:代码区内部;
6) 非RAM存储:如“流对象”和“持久化对象”。
2、虽然Java把一切都可视为对象,但基本类型却是一个特例,它与两种形式存活于Java中:基本类型和对象。
Java Data Type
3、Java基本类型所占存储空间的大小具有不变性,即不随机器硬件架构的变化而变化。
4、两个高精度计算类:BigInteger和BigDecimal。
5、数组也具有数组对象和基本类型数组两种。
6、Java不支持类似C/C++将一个较大作用域的变量“隐藏”起来的做法。
7、当变量作为类的成员使用时,Java才确保给定其默认值,以确保那些是基本类型的成员变量得到初始化,防止产生程序错误。但该规则不适用于局部变量。所以使用一个局部变量前必须对其初始化,否则Java会在编译时返回一个错误。
8、对于static方法,不能简单地通过调用其他非static成员或方法而没有指定某个命名对象,来直接访问非static成员或方法(因为非 static成员或方法必须与某一种特定对象关联)。
9、注释文档(javadoc): /** some comment */
(1) 使用javadoc的方式主要有两种:嵌入HTML和“文档标签”
(2) 文档标签:
独立文档标签:以”@”字符开头的命令,且要置于注释行的最前面(但是不算前导”*”之后的最前面);
行内文档标签:以”@”字符开头,括在花括号内,可以出现在javadoc注释中的内任何地方。
(3) 三种类型的注释文档:
·位于类定义之前
·位于变量定义之前
·位于方法定义之前
(4) javadoc只能为”public”和”protected”成员进行文档注释。”private”和包内可访问成员的注释会被忽略掉。
(5) 不要在嵌入式HTML中使用标题标签,如<hl>或<hr>,因为javadoc会插入自己的标题,而你的标题可能同它们发生冲突。
(6) 一些标签示例
<1>@see: 引用其他类。格式:
@see classname
@see fully-qualified-classname
@see fully-qualified-classname # method -name
<2>{@link package.class#member label} 功能同@see
<3>{@docRoot} 产生到文档根目录的相对路径,用于文档树页面的文档注释中。
<4>@version:
@version version-information
<5>@author:
@author author-information
<6>@since 该标签允许你指定程序代码最早使用的版本
<7>@param 该标签用于方法文档中,形式如下:
@param parameter-name description
<8>@return
@return description
<9>@throws: 描述抛出的异常
@throws fully-qualified-class-name description
<10>@deprecated:该标签用于指出一些旧特性已由改进的新特性所取代。
三、第三章 控制程序流程
1、当关系操作符作用于对象时(<,>,<=,>=,==,!=),关系比较的仅仅是对象的引用。
2、“与”、“或”、“非”操作只可应用于布尔值。不同于C/C++,不可将一个非布尔值当作布尔值在逻辑表达式中的使用。
3、移位操作符:
左移(<<):将操作符左边的操作数向左移动操作符右侧指定的位数(在低位补0)
|-“有符号”右移(>>):将操作符左边的操作数向右移动操作符右侧指定的位数。
| “符号扩展”:若符号为正,则在高位插入0;
右移(>>):< 若符号为负,则在高位插入1。
|
|-“无符号”右移(>>>):“零扩展”:无论正负,都在高位插0
左乘右除准则: 左移一位,相当于乘2^1
右移一位,相当于除2^1
4、非但变量、数值也可以进行类型转换
5、只有for循环才具备在控制表达式里定义变量的能力,其他任何条件语句或循环语句,都不可采用这种方法
6、break和continue语句的规则:
1)一般的continue会退回最内层循环的开头(顶部),并继续执行;
2)带标签的continue会到达标签的位置,并重新进入紧接在那个标签后面的循环;
3)一般的break会中断并跳出当前循环
4)带标签的break会中断并跳出标签所指定的循环,抵达该循环的末尾处。
7、在Java里需要使用标签的唯一理由就是因为有循环嵌套,而且你想从多层嵌套中break或continue。此外,标签要刚好处于要跳转到的循环之前,如:
label1:
outer_iteration{
inner_iteration{
//…
break; //1
//…
continue; //2
//…
continue label1; //3
//…
break label1; //4
}
}
8、switch语句中的“选择因子”的数据类型只能是int或char的整数值,其他类型(float,double,等switch语句将不会工作)。
9、将一个float或double值转型成整数值后,总是将小数部分“砍掉”,而不是四舍五入
10、Math.random()的输出值范围是[0,1)
11、在一个浮点数系统中,可表达的数的总数量是:2(M-m+1)b^(p-1)+1
其中: b-基数(通常是2)
p-精度(尾数中的位数)
M-指数的最大值
m-指数的最小值
IEEE754的规范: M=1023, m=-1022, p=53, b=2
所以能够表示的数的总个数有:
2(1023+1022+1)2^52 = 2((2^10-1) + (2^10-1))2^52
= (2^10-1)2^54
= 2^64 - 2^54
其中,一半的数(指数在[-1022,0]范围内)小于1(包括整数和负数)
第四章、初始化与清理
1、如果用户没有创建一个构造器,java编译器会自动创建一个缺省构造器;但如果用户定义了自己的构造器,编译器则不会再创建默认构造器
2、在构造器中调用构造器时,可以用this关键字调用一个构造器,但却不能同时调用两个。此外,必须将构造器置于最起始处,否则编译器会报错
3、除在构造器中调用外,编译器禁止在其他任何地方中调用构造器
4、finalize()方法(终结处理方法)的工作原理:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存
5、在C++中,对象一定会被销毁(如果程序中没有错误的话);而java里的对象却并非总是被垃圾回收,即:
1) 对象可能不被垃圾回收
2) 垃圾回收并不等于“析构”
3) 垃圾回收只与内存有关
6、java的垃圾回收器是一种“自适应的、分代的、停止-复制(stop-and-copy)、标记-清扫(mark-and-sweep)”式垃圾回收器
7、在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化
8、对象的创建过程:(假设有个名为Dog的类):
1) 当首次创建类型为Dog的对象时(构造器可以看成静态方法),或者Dog类的静态方法/静态字段首次被访问时,java解释器必须查找类路径,以定位 Dog.class文件
2) 然后载入Dog.class(将创建一个class对象),有关静态初始化的所有动作都会被执行。因此,静态初始化只在class对象首次加载的时候进行一次
3) 当用new Dog()创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间
4) 这块存储空间会被清零,这就自动地将Dog对象中的所有基本类型数据都设置成默认缺省值
5) 执行所有出现于字段定义处的初始化动作
6) 执行构造器
9、java允许将多个静态初始化动作组织成一个“静态块”进行,如:
class Cups {
static Cup c1;
static Cup c2;
static {
c1 = new Cup(1);
c2 = new Cup(2);
}
Cups() {
System.out.println(“Cups()”);
}
}
同样,对非静态实例初始化也可以采用这种“块”的形式
10、java中的数组有一个只读成员length,表示数组的长度。
第五章、隐藏具体实现
1、访问权限控制的等级,从最大权限到最小权限依次为:
public, protected, 包访问权限(没有关键词), private。
2、编译单元:一个java源代码文件,即.java文件。
3、每个编译单元只能有一个public类,其它类都是低于或等于“包访问权限”的类,用于为主public类提供支持。
4、package和import允许做的,是将单一的全局名字空间分割开,使得无论多少人使用Internet以及java开始编写类,都不会出现名字冲突问题。
5、java中,每个访问权限修饰词(public、protected、private)仅控制它所修饰的特定定义的访问权,而C++中可以控制其后的所有定义,除非另有访问权限修饰词的出现。
6、包访问权限(friendly):当前的包中的所有其他类对那个成员都有访问权限(该成员不指定权限修饰符),但对于这个包之外的所有类,这个成员都是private。
7、public:接口访问权限。
8、private:你无法访问:
除了包含该成员的类之外,其他任何类(包括继承类),都无法访问这个成员
9、protected:用来处理继承,它提供了包访问权限,也就是说,相同包内的其他类可以访问protected元素。而且还表明:就类用户而言,这是private的,但相对于任何继承于此类或其他任何位于同一个包内的类来说,它却可以访问。
10、为了清楚起见,可能会采用一种将public成员置于开头,后面跟着protected、包访问权限和private成员的创建类的形式。
11、类的访问权限:
除内部类外,类既不可以是private的,也不可以是protected的。所以,对于类的访问权限,仅有两个选择:包访问权限或public。
12、static方法就是没有this的方法。在static方法的内部不能调用非静态方法,反过来倒可以。但下面的例子例外:
//: c05: Lunch.java 《java编程思想》3th Edition
// Demonstrates class access specifiers. Make a class
// effectively private with private constructors:
class Soup {
private Soup() {}
//(1)Allow creation via static method:
public static Soup makeSoup() {
return new Soup(); // 注:这里的静态方法并不是调用“非静态成员”Soup(),而是用new关键字创建一个实例对象
}
//(2)Create a static object and return a reference
//upon request.(The “Singleton” pattern)
private static Soup ps1 = new Soup();
public static Soup access() { return ps1; }
public void f() {}
}
class Sandwich {
void f() { new Lunch(); }
}
//Only one public class allowed perfile:
public class Lunch {
void test() {
// Can’t do this! Private constractor:
// !Soup priv1 = new Soup();
Soup priv2 = Soup.makeSoup();
Sandwich f1 = new Sandwich();
Soup.access().f();
}
} ///:~
把所有的相应构造器指定为private,从而阻止任何人创建该类的对象,但一个例外是:可以在该类的static成员内部创建。
六、第六章
1、利用现有类型生成新类型(复用代码)的两种方法:组合和继承。
2、同一个编译单元中的每个类都可以创建一个main方法(一般建议这样做,以便测试),只有命令行所调用的那个类的main()方法会被调用(只要这个main()是public,其所属的类是否为public则不用考虑)。
3、编译器会强制你去初始化基类,并要求你要在构造器起始处就要这么做,但它并不监督你必须将成员对象也初始化。
4、垃圾回收器可能永远也无法被调用,即使被调用,它也可能以任何它想要的顺序来回收对象。最好的方法是除了内存以外,不要依赖垃圾回收器去做任何事情。如果需要进行清理,最好是编写你自己的清理方法,但不要依赖finalize()。
5、要使用组合还是继承,一个最清晰的判断办法就是取决于“是否需要从新类向基类进行向上转型”的答案,如果答案是“是”,则使用继承,否则使用组合。
6、final关键字(用到的三种情况:数据、方法和类):
1) final数据:
|作用于基本数据类型:恒定不变的值
a.<|
|作用于对象引用:恒定不变的引用(而非对象本身)
b.空白final:指被声明为final但又未给定初值的字段。但无论什么情况,编译器都确保空白final在使用前必须被初始化。使用空白 final能产生“一个类中的final字段可以做到根据对象而有所不同,却又保持其恒定不变的特性” 的效果。
c.final参数:使无法在方法中更改参数引用所指向的对象
2)final方法:
使用final方法的两个原因:
a.把方法锁定,以防止任何继承类修改它的含义,即确保在继承中使方法行为保持不变,并且不会被覆盖。
b.效率因素:如果将一个方法指明为final,就是同意编译器将针对该方法的所有调用都转为内嵌调用。但这只是提供一种可能性,执不执行内嵌调用由编译器决定
3)final类:
当将某个类的整体定义为final时(通过将关键字final置于它的定义之前),就表明了不能继承该类,即出于某种考虑,对类的设计永不需要做任何变动,或出于安全的考虑,不希望它有子类。
7、类中所有的private方法都隐式地指定为是final的。
8、“覆盖”只有在某种方法是基类的接口的一部分时才会出现,即必须能将一个对象向上转型为它的基本类型并调用相同的方法。因此,对基类的 private方法不存在“覆盖”行为,它已被有效的“隐藏”,可以当其是“透明”的。
七、第七章 多态
1、面向对象编程语言的三个核心本质:
·数据抽象化(data abstraction)
·继承(Inheritance)
·多态(polymorphism)
2、多态提供了“接口与实现分离”的另一个重要性,能将what(是什么)自how(怎么做)之中抽离。
3、封装(encapsulation)借着“将特征(characteristics)与行为(behaviors)结合在一起”而产生新的数据型别;
实现隐藏(implementation hidden)则籍由“将细目(details)声明为private”而分离出接口(interface)与实现(implementation);
多态则除去了型别之间的耦合关系。
4、java中除了static方法和final方法(private方法属于final方法)之外,其他所有方法都是后期绑定。
要牢牢记住private方法不能被后期绑定,而只能前期绑定。
5、对象类型的确定:(如: Shape s = new Circle)
对于后期绑定:所new的对象类型为具体类型,如Circle
对于前期绑定:声明时的类型,如Shape
6、抽象方法的声明(abstract method):
abstract void f();
抽象类的声明(abstract class):
abstract class class_name {
// …
}
7、对于C++程序员而言,abstract method相当于c++的纯虚函数(pure virtual function)。
8、 有抽象方法的抽象类:一个或多个抽象方法
无抽象方法的抽象类:不含任何抽象方法,仅表示不产生任何实体。
9、构造器的调用顺序:
1)为对象分配存储空间,并初始化为二进制0;
2)调用基类构造器。这个步骤会不断地反复递归下去,首先是构造这种层次结构的根,然后是下一层导出类,等等,直到最底层的导出类;
3)按声明顺序调用成员的初始化方法;
(调用到某类的构造器时进行(既包括基类,也包括导出类))
4)调用导出类构造器的主体。
写成递归的伪代码形式则是:
void constructorOrder(Object obj)
{
1.为对象obj分配存储空间,并将成员初始化为二进制0;
2.constructorOrder(obj.superclass);
3.根据成员的定义进行初始化;
//调用当前类的构造器主体
4.constructor();
}
10、若要作清理工作,则过程和构造时完全相反,即:
1)调用导出类,清理方法的主体;
2)按声明的逆顺序调用成员的清理方法;
3)调用基类的清理方法。
注:上面三个步骤是递归式进行
11、编写构造器时有一条有效的准则:“用尽可能简单的方法使对象进入正常状态;如果可以的话,避免调用其他方法”。
12、在构造器内唯一能够安全调用的那些方法是基类中的final方法(也适用于private方法,它们自动属于final方法)。
13、用继承进行设计时的一条通用的准则就是:“用继承表达行为间的差异,并用字段表达状态上的变化”。
14、向上转型(upcasting)总是安全的,但向下转型(dowcasting),则需使用类型转换:
如果所转类型是正确的类型,则转型成功;
否则,就会返回一个classCastException异常。
1、Alan Kay总结了面向对象的五个特性:
1) 万物皆为对象
2) 程序是对象的集合,它们通过发送消息来告知彼此所要做的
3) 每个对象都有自己的由其他对象所构成的存储
4) 每个对象都有其类型
5) 某一特定类型的所有对象都可以接收同样的消息
Booch的描述:对象具有状态、行为和标识。
2、UML:Unified Modelling Language, 统一建模语言。
UML结构
3、通过继承而产生的类型具有等价性,即:导出类与基类具有相同的类型。
4、使基类与导出类产生差异的两种方法:
1) 直接在导出类中添加新方法(is-like-a)
2) 改变现有基类的方法的行为--覆盖(overriding),这叫替代原则,即“纯粹替代”(is-a)
5、多态使用了“后期绑定”的概念,它通过“向上转型”(upcasting)来实现。
6、抽象方法(abstract)只能在抽象类内部创建,当该类被继承时,抽象方法必须被实现,否则继承类仍然是一个抽象类。
7、Java完全采用在被称为堆(heap)的内存池中动态地创建对象。每当想要创建新的对象时,就要使用new关键字来构建此对象的实例。与此不同的是,C++除了在堆中创建对象外,还可以在堆栈中创建对象。
8、Java的单根继承结构,使垃圾回收器的实现变得容易。
二、第二章 一切都是对象
1、存储数据的六个地方
1) 寄存器:编译器决定
2) 堆栈: 堆栈指针若向下移动,则分配新的内存;
若向上移动,则释放那些内存。
对象的引用而非对象存在此。
3) 堆:存放所有的Java对象;
4) 静态存储:RAM中固定的位置;
5) 常量存储:代码区内部;
6) 非RAM存储:如“流对象”和“持久化对象”。
2、虽然Java把一切都可视为对象,但基本类型却是一个特例,它与两种形式存活于Java中:基本类型和对象。
Java Data Type
3、Java基本类型所占存储空间的大小具有不变性,即不随机器硬件架构的变化而变化。
4、两个高精度计算类:BigInteger和BigDecimal。
5、数组也具有数组对象和基本类型数组两种。
6、Java不支持类似C/C++将一个较大作用域的变量“隐藏”起来的做法。
7、当变量作为类的成员使用时,Java才确保给定其默认值,以确保那些是基本类型的成员变量得到初始化,防止产生程序错误。但该规则不适用于局部变量。所以使用一个局部变量前必须对其初始化,否则Java会在编译时返回一个错误。
8、对于static方法,不能简单地通过调用其他非static成员或方法而没有指定某个命名对象,来直接访问非static成员或方法(因为非 static成员或方法必须与某一种特定对象关联)。
9、注释文档(javadoc): /** some comment */
(1) 使用javadoc的方式主要有两种:嵌入HTML和“文档标签”
(2) 文档标签:
独立文档标签:以”@”字符开头的命令,且要置于注释行的最前面(但是不算前导”*”之后的最前面);
行内文档标签:以”@”字符开头,括在花括号内,可以出现在javadoc注释中的内任何地方。
(3) 三种类型的注释文档:
·位于类定义之前
·位于变量定义之前
·位于方法定义之前
(4) javadoc只能为”public”和”protected”成员进行文档注释。”private”和包内可访问成员的注释会被忽略掉。
(5) 不要在嵌入式HTML中使用标题标签,如<hl>或<hr>,因为javadoc会插入自己的标题,而你的标题可能同它们发生冲突。
(6) 一些标签示例
<1>@see: 引用其他类。格式:
@see classname
@see fully-qualified-classname
@see fully-qualified-classname # method -name
<2>{@link package.class#member label} 功能同@see
<3>{@docRoot} 产生到文档根目录的相对路径,用于文档树页面的文档注释中。
<4>@version:
@version version-information
<5>@author:
@author author-information
<6>@since 该标签允许你指定程序代码最早使用的版本
<7>@param 该标签用于方法文档中,形式如下:
@param parameter-name description
<8>@return
@return description
<9>@throws: 描述抛出的异常
@throws fully-qualified-class-name description
<10>@deprecated:该标签用于指出一些旧特性已由改进的新特性所取代。
三、第三章 控制程序流程
1、当关系操作符作用于对象时(<,>,<=,>=,==,!=),关系比较的仅仅是对象的引用。
2、“与”、“或”、“非”操作只可应用于布尔值。不同于C/C++,不可将一个非布尔值当作布尔值在逻辑表达式中的使用。
3、移位操作符:
左移(<<):将操作符左边的操作数向左移动操作符右侧指定的位数(在低位补0)
|-“有符号”右移(>>):将操作符左边的操作数向右移动操作符右侧指定的位数。
| “符号扩展”:若符号为正,则在高位插入0;
右移(>>):< 若符号为负,则在高位插入1。
|
|-“无符号”右移(>>>):“零扩展”:无论正负,都在高位插0
左乘右除准则: 左移一位,相当于乘2^1
右移一位,相当于除2^1
4、非但变量、数值也可以进行类型转换
5、只有for循环才具备在控制表达式里定义变量的能力,其他任何条件语句或循环语句,都不可采用这种方法
6、break和continue语句的规则:
1)一般的continue会退回最内层循环的开头(顶部),并继续执行;
2)带标签的continue会到达标签的位置,并重新进入紧接在那个标签后面的循环;
3)一般的break会中断并跳出当前循环
4)带标签的break会中断并跳出标签所指定的循环,抵达该循环的末尾处。
7、在Java里需要使用标签的唯一理由就是因为有循环嵌套,而且你想从多层嵌套中break或continue。此外,标签要刚好处于要跳转到的循环之前,如:
label1:
outer_iteration{
inner_iteration{
//…
break; //1
//…
continue; //2
//…
continue label1; //3
//…
break label1; //4
}
}
8、switch语句中的“选择因子”的数据类型只能是int或char的整数值,其他类型(float,double,等switch语句将不会工作)。
9、将一个float或double值转型成整数值后,总是将小数部分“砍掉”,而不是四舍五入
10、Math.random()的输出值范围是[0,1)
11、在一个浮点数系统中,可表达的数的总数量是:2(M-m+1)b^(p-1)+1
其中: b-基数(通常是2)
p-精度(尾数中的位数)
M-指数的最大值
m-指数的最小值
IEEE754的规范: M=1023, m=-1022, p=53, b=2
所以能够表示的数的总个数有:
2(1023+1022+1)2^52 = 2((2^10-1) + (2^10-1))2^52
= (2^10-1)2^54
= 2^64 - 2^54
其中,一半的数(指数在[-1022,0]范围内)小于1(包括整数和负数)
第四章、初始化与清理
1、如果用户没有创建一个构造器,java编译器会自动创建一个缺省构造器;但如果用户定义了自己的构造器,编译器则不会再创建默认构造器
2、在构造器中调用构造器时,可以用this关键字调用一个构造器,但却不能同时调用两个。此外,必须将构造器置于最起始处,否则编译器会报错
3、除在构造器中调用外,编译器禁止在其他任何地方中调用构造器
4、finalize()方法(终结处理方法)的工作原理:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存
5、在C++中,对象一定会被销毁(如果程序中没有错误的话);而java里的对象却并非总是被垃圾回收,即:
1) 对象可能不被垃圾回收
2) 垃圾回收并不等于“析构”
3) 垃圾回收只与内存有关
6、java的垃圾回收器是一种“自适应的、分代的、停止-复制(stop-and-copy)、标记-清扫(mark-and-sweep)”式垃圾回收器
7、在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化
8、对象的创建过程:(假设有个名为Dog的类):
1) 当首次创建类型为Dog的对象时(构造器可以看成静态方法),或者Dog类的静态方法/静态字段首次被访问时,java解释器必须查找类路径,以定位 Dog.class文件
2) 然后载入Dog.class(将创建一个class对象),有关静态初始化的所有动作都会被执行。因此,静态初始化只在class对象首次加载的时候进行一次
3) 当用new Dog()创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间
4) 这块存储空间会被清零,这就自动地将Dog对象中的所有基本类型数据都设置成默认缺省值
5) 执行所有出现于字段定义处的初始化动作
6) 执行构造器
9、java允许将多个静态初始化动作组织成一个“静态块”进行,如:
class Cups {
static Cup c1;
static Cup c2;
static {
c1 = new Cup(1);
c2 = new Cup(2);
}
Cups() {
System.out.println(“Cups()”);
}
}
同样,对非静态实例初始化也可以采用这种“块”的形式
10、java中的数组有一个只读成员length,表示数组的长度。
第五章、隐藏具体实现
1、访问权限控制的等级,从最大权限到最小权限依次为:
public, protected, 包访问权限(没有关键词), private。
2、编译单元:一个java源代码文件,即.java文件。
3、每个编译单元只能有一个public类,其它类都是低于或等于“包访问权限”的类,用于为主public类提供支持。
4、package和import允许做的,是将单一的全局名字空间分割开,使得无论多少人使用Internet以及java开始编写类,都不会出现名字冲突问题。
5、java中,每个访问权限修饰词(public、protected、private)仅控制它所修饰的特定定义的访问权,而C++中可以控制其后的所有定义,除非另有访问权限修饰词的出现。
6、包访问权限(friendly):当前的包中的所有其他类对那个成员都有访问权限(该成员不指定权限修饰符),但对于这个包之外的所有类,这个成员都是private。
7、public:接口访问权限。
8、private:你无法访问:
除了包含该成员的类之外,其他任何类(包括继承类),都无法访问这个成员
9、protected:用来处理继承,它提供了包访问权限,也就是说,相同包内的其他类可以访问protected元素。而且还表明:就类用户而言,这是private的,但相对于任何继承于此类或其他任何位于同一个包内的类来说,它却可以访问。
10、为了清楚起见,可能会采用一种将public成员置于开头,后面跟着protected、包访问权限和private成员的创建类的形式。
11、类的访问权限:
除内部类外,类既不可以是private的,也不可以是protected的。所以,对于类的访问权限,仅有两个选择:包访问权限或public。
12、static方法就是没有this的方法。在static方法的内部不能调用非静态方法,反过来倒可以。但下面的例子例外:
//: c05: Lunch.java 《java编程思想》3th Edition
// Demonstrates class access specifiers. Make a class
// effectively private with private constructors:
class Soup {
private Soup() {}
//(1)Allow creation via static method:
public static Soup makeSoup() {
return new Soup(); // 注:这里的静态方法并不是调用“非静态成员”Soup(),而是用new关键字创建一个实例对象
}
//(2)Create a static object and return a reference
//upon request.(The “Singleton” pattern)
private static Soup ps1 = new Soup();
public static Soup access() { return ps1; }
public void f() {}
}
class Sandwich {
void f() { new Lunch(); }
}
//Only one public class allowed perfile:
public class Lunch {
void test() {
// Can’t do this! Private constractor:
// !Soup priv1 = new Soup();
Soup priv2 = Soup.makeSoup();
Sandwich f1 = new Sandwich();
Soup.access().f();
}
} ///:~
把所有的相应构造器指定为private,从而阻止任何人创建该类的对象,但一个例外是:可以在该类的static成员内部创建。
六、第六章
1、利用现有类型生成新类型(复用代码)的两种方法:组合和继承。
2、同一个编译单元中的每个类都可以创建一个main方法(一般建议这样做,以便测试),只有命令行所调用的那个类的main()方法会被调用(只要这个main()是public,其所属的类是否为public则不用考虑)。
3、编译器会强制你去初始化基类,并要求你要在构造器起始处就要这么做,但它并不监督你必须将成员对象也初始化。
4、垃圾回收器可能永远也无法被调用,即使被调用,它也可能以任何它想要的顺序来回收对象。最好的方法是除了内存以外,不要依赖垃圾回收器去做任何事情。如果需要进行清理,最好是编写你自己的清理方法,但不要依赖finalize()。
5、要使用组合还是继承,一个最清晰的判断办法就是取决于“是否需要从新类向基类进行向上转型”的答案,如果答案是“是”,则使用继承,否则使用组合。
6、final关键字(用到的三种情况:数据、方法和类):
1) final数据:
|作用于基本数据类型:恒定不变的值
a.<|
|作用于对象引用:恒定不变的引用(而非对象本身)
b.空白final:指被声明为final但又未给定初值的字段。但无论什么情况,编译器都确保空白final在使用前必须被初始化。使用空白 final能产生“一个类中的final字段可以做到根据对象而有所不同,却又保持其恒定不变的特性” 的效果。
c.final参数:使无法在方法中更改参数引用所指向的对象
2)final方法:
使用final方法的两个原因:
a.把方法锁定,以防止任何继承类修改它的含义,即确保在继承中使方法行为保持不变,并且不会被覆盖。
b.效率因素:如果将一个方法指明为final,就是同意编译器将针对该方法的所有调用都转为内嵌调用。但这只是提供一种可能性,执不执行内嵌调用由编译器决定
3)final类:
当将某个类的整体定义为final时(通过将关键字final置于它的定义之前),就表明了不能继承该类,即出于某种考虑,对类的设计永不需要做任何变动,或出于安全的考虑,不希望它有子类。
7、类中所有的private方法都隐式地指定为是final的。
8、“覆盖”只有在某种方法是基类的接口的一部分时才会出现,即必须能将一个对象向上转型为它的基本类型并调用相同的方法。因此,对基类的 private方法不存在“覆盖”行为,它已被有效的“隐藏”,可以当其是“透明”的。
七、第七章 多态
1、面向对象编程语言的三个核心本质:
·数据抽象化(data abstraction)
·继承(Inheritance)
·多态(polymorphism)
2、多态提供了“接口与实现分离”的另一个重要性,能将what(是什么)自how(怎么做)之中抽离。
3、封装(encapsulation)借着“将特征(characteristics)与行为(behaviors)结合在一起”而产生新的数据型别;
实现隐藏(implementation hidden)则籍由“将细目(details)声明为private”而分离出接口(interface)与实现(implementation);
多态则除去了型别之间的耦合关系。
4、java中除了static方法和final方法(private方法属于final方法)之外,其他所有方法都是后期绑定。
要牢牢记住private方法不能被后期绑定,而只能前期绑定。
5、对象类型的确定:(如: Shape s = new Circle)
对于后期绑定:所new的对象类型为具体类型,如Circle
对于前期绑定:声明时的类型,如Shape
6、抽象方法的声明(abstract method):
abstract void f();
抽象类的声明(abstract class):
abstract class class_name {
// …
}
7、对于C++程序员而言,abstract method相当于c++的纯虚函数(pure virtual function)。
8、 有抽象方法的抽象类:一个或多个抽象方法
无抽象方法的抽象类:不含任何抽象方法,仅表示不产生任何实体。
9、构造器的调用顺序:
1)为对象分配存储空间,并初始化为二进制0;
2)调用基类构造器。这个步骤会不断地反复递归下去,首先是构造这种层次结构的根,然后是下一层导出类,等等,直到最底层的导出类;
3)按声明顺序调用成员的初始化方法;
(调用到某类的构造器时进行(既包括基类,也包括导出类))
4)调用导出类构造器的主体。
写成递归的伪代码形式则是:
void constructorOrder(Object obj)
{
1.为对象obj分配存储空间,并将成员初始化为二进制0;
2.constructorOrder(obj.superclass);
3.根据成员的定义进行初始化;
//调用当前类的构造器主体
4.constructor();
}
10、若要作清理工作,则过程和构造时完全相反,即:
1)调用导出类,清理方法的主体;
2)按声明的逆顺序调用成员的清理方法;
3)调用基类的清理方法。
注:上面三个步骤是递归式进行
11、编写构造器时有一条有效的准则:“用尽可能简单的方法使对象进入正常状态;如果可以的话,避免调用其他方法”。
12、在构造器内唯一能够安全调用的那些方法是基类中的final方法(也适用于private方法,它们自动属于final方法)。
13、用继承进行设计时的一条通用的准则就是:“用继承表达行为间的差异,并用字段表达状态上的变化”。
14、向上转型(upcasting)总是安全的,但向下转型(dowcasting),则需使用类型转换:
如果所转类型是正确的类型,则转型成功;
否则,就会返回一个classCastException异常。
发表评论
-
Tomcat热部署原理
2012-05-19 20:49 1207一. ... -
java 并发实践
2012-03-23 11:02 0java并发编程实践笔记 1, 保证线程安全的三种方法: ... -
Map sort
2010-12-02 11:09 1826可能会遇到这样的情况,我可能要对Map<key,valu ... -
Java 解析 xml
2010-07-20 10:59 7001.介绍 1)DOM(JAXP Crimson解析器 ... -
java 编码
2010-07-01 22:06 665现代计算机采用的都是 ... -
Class文件格式解析
2010-07-01 21:40 894http://www.blogjava.net/javafan ... -
java中byte转换int时为何与0xff进行与运算
2010-07-01 21:29 917[转]java中byte转换int时为何与0xff进行与运算 ... -
java 的InputStream和OutputStream的理解
2010-06-21 15:10 1935(转)java 的InputStream和OutputStre ... -
java-email(转)
2010-03-23 15:50 933最近在项目中用到发送 ... -
UNICODE与 UTF-8的转换详解
2010-03-19 10:18 4812转载请注明出处: http://www.ins1000.cn/ ... -
java中hashcode()和 equals()的详解[转]
2010-03-18 14:34 722java中hashcode()和 equals() ... -
细说java的util中的集合类
2010-03-03 14:54 740线性表,链表,哈希表是常用的数据结构,在进行Java开发时,J ... -
String 创建
2010-03-01 10:52 780package com; import org.junit.T ... -
java字符串连接
2010-02-01 17:22 1549注:引用http://www.blogjava.net/nok ... -
java
2010-01-06 16:53 649【转】JNDI的详细介绍(09-03-27) 收藏 看到这篇关 ...
相关推荐
《Think in Java》是Java编程领域的一本经典著作,由Bruce Eckel撰写,深受程序员喜爱。这本书通过深入浅出的方式讲解了Java语言的核心概念和技术,包括面向对象编程、数据结构、算法以及网络编程等多个方面。"Think...
《Think in Java 中文文档》作为一本深入讲解Java编程语言的教材,不仅适合有志于深入学习Java的程序员,也适合那些希望拓展自己技术栈的初学者。本书通过系统性的结构和丰富的实例,帮助读者全面理解Java,并最终...
《Think in Java》是Bruce Eckel的经典编程教材,它深入浅出地讲解了Java语言的基础概念和高级特性。源码整理则为读者提供了实践和学习的机会,帮助理解书中的示例和理论。以下是对《Think in Java》源码中一些重要...
java think in java (英文第四版)至今为止 被认为是java教程之中权威作品之一
《Think in Java 3》是一本深受欢迎的Java编程指南,由Bruce Eckel撰写,它以其详尽的解释和丰富的示例闻名。这本书是许多Java初学者和专业开发者的重要参考资料,旨在帮助读者深入理解Java语言的核心概念和机制。...
《Think in Java》是 Bruce Eckel 的经典著作,它深入浅出地讲解了Java编程语言的核心概念和技术。这本书强调理解编程思想,而不仅仅是学习语法。练习题是学习过程中的重要部分,它们帮助我们巩固理论知识,提升实际...
《Think In Java 4》是Java编程领域里一本极具影响力的著作,由资深程序员 Bruce Eckel 编著。这本书以其深入浅出的讲解方式和全面的知识覆盖而闻名,被誉为Java学习者的经典读物。中文版的完美高清版本为国内读者...
Think in java 源码构建编译
Think in Java(美)Bruce Eckel 著 陈昊鹏 译 引言 同人类任何语言一样,Java为我们提供了一种表达思想的方式。如操作得当,同其他方式相 比,随着问题变得愈大和愈复杂,这种表达方式的方便性和灵活性会显露无遗。 ...
《Think in Java 中文第四版》是学习Java编程的经典之作,由Bruce Eckel撰写,它深入浅出地讲解了Java语言的核心概念和技术。本部分主要涵盖的是书籍的第二部分,通常涉及面向对象编程的深入探讨,包括类、对象、...
《Think in Java》是Java编程领域的一本经典之作,由Bruce Eckel撰写,中文版第四版更是深受广大Java程序员喜爱。这本书深入浅出地讲解了Java语言的核心概念和编程技术,旨在帮助读者不仅仅是学习语法,而是理解Java...
《Think in JAVA 编程思想》是Java编程领域的一本经典著作,由Bruce Eckel撰写。第四版作为该书的最新版本,包含了作者对Java语言深入的理解和丰富的编程经验,旨在帮助读者理解面向对象编程的核心理念,并提升编程...
think in java 第四版 源码以及作业 eclipse版本 包含jar包 可以直接导入eclipse
《Think in Java》是Java编程领域的一本经典著作,作者是Bruce Eckel。第11章的主题是“持有对象”,这一章主要探讨了如何在Java中创建和管理对象,包括对象的引用、对象的生命周期、类与对象的关系,以及如何通过...
java 教程 think in java,java 教程 think in java
think in java think in java think in java think in java think in java think in java
《Think in Java 4》是Java编程领域的一部经典之作,由Bruce Eckel撰写,它以其深入浅出的讲解方式和丰富的示例代码深受程序员喜爱。这个压缩包包含的就是这本书的全部源代码,旨在帮助读者更好地理解和实践书中所...
think in Java think in Java think in Java
抽象的进步 1.2 对象的接口 1.3 实现方案的隐藏 1.4 方案的重复使用 1.5 继承:重新使用接口 1.5.1 改善基础类 1.5.2 等价和类似关系 1.6 多形对象的互换使用 1.6.1 动态绑定 ...1.11 Java和因特网
《Think in Java》第四版是一本被广大Java程序员推崇的书籍,它被认为是每个Java开发者必读的经典之作。这本书不仅适合初学者,对有一定经验的程序员来说,也是一本很好的参考书籍。书中内容详尽,解释精准,例子...