C++引入了构造器的概念,JAVA在此基础上,额外提供了“垃圾回收器”。
5.1 用构造器确保初始化
由于构造器的名称必须与类名相同,所以“每个方法首字母小写”的编码风格并不适用于构造器。
从概念上讲,“初始化”与“创建”是彼此独立的,而在JAVA中,“初始化”与“创建”捆绑在一起。
构造器是一种特殊类型的方法,因为它没有返回值。这与返回值为空(void)明显不同。对于空返回值,尽管方法本身不会自动返回什么,但仍然可选择让它返回别的东西。构造器则不会返回任何东西(new表达式确实返回了对新建对象的引用,但构造器本身并没有返回值)
5.2 方法重载
的确,方法重载对于构造器来说是必须的,所以《Thinking in Java》这本书很合理地将方法重载的内容安排在了构造器之后。
5.2.1 区分重载方法
每个重载的方法都必须有一个独一无二的参数类型列表。即,靠参数类型列表的不同来区分同名的不同方法。甚至参数顺序的不同也可以区分,但这样会使得代码难以阅读和维护。
5.2.2 涉及基本类型的重载
基本类型能从一个“较小”的类型自动提升至一个“较大”的类型,基于此情形,对于方法重载,如果传入的数据类型(实际参数类型)小于方法中声明的形式参数类型,实际数据类型就会被提升。Char类型略有不同,如果无法找到恰好接受char参数的方法,就会把char直接提升至int型。
如果传入的实际参数大于重载方法声明的形式参数,则需要做显式的窄化转换。
5.2.3-“以返回值区分重载方法是行不通的”。
5.3默认构造器(略)
5.4 this关键字
This关键字表示对当前对象的引用,只能在方法内部使用。
若要在构造器中调用其他的构造器,可用this。
通常this表示对当前对象的引用,而在构造器中,如果为this添加了参数列表,那么就有不同的含义。这将产生对符合此参数列表的某个构造器的明确调用。
但,尽管可以用this调用一个构造器,却不能调用两个。此外必须将调用置于起始处,否则编译器会报错。
并且,构造器只能从另一个构造器内部调用,构造器以外的方法不可以调用构造器。
在staitc方法的内部不能调用非静态方法。
5.5 清理:终结处理和垃圾回收
finalize()方法在垃圾回收之前执行。但并非析构函数。JAVA中并没有析构函数。
注意一下三点:
1.对象可能不被垃圾回收;
2.垃圾回收并不等于“析构”;
3.垃圾回收只与内存有关
System.gc()用于强制进行终结动作。
5.6成员的初始化
JAVA尽力保证:所有变量在使用前都能得到恰当的初始化。对于方法的局部变量,Java以编译时错误的形式来贯彻这种保证。(类成员用默认值)
如:
void
f()
{
int i;
i++; // Error
}
//
错误,i未被初始化。
若类的数据成员是基本数据类型,会有默认初始值。
5.6.1 指定初始化:
如:
int
i
=
999
;
byte
b
=
47
;
short
s
=
0xff
;
也可以通过调用某个方法来提供初始值,但要注意参数的初始化顺序,即方法的参数必须已经初始化了。
5.7 构造器的初始化
可以利用构造器进行成员的初始化,但要牢记:无法阻止自动初始化的进行,它将在构造器被调用之前发生。
5.7.1 初始化顺序
我觉得这一部分是重点!
在类的内部,变量定义的先后顺序决定了初始化的顺序。而即使变量定义散布于方法啊定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。
5.7.2 静态数据的初始化
无论创建多少个对象,静态数据都只占有一份存储区域——再次提醒。
静态对象会在非静态对象之前得到初始化。
总结一下对象的创建过程,假设有个名为Dog的类:
1、 当要创建Dog对象,或者Dog类的静态方法、静态域被访问时,Java解释器先定位Dog.class文件;
2、 载入Dog.class(这将创建一个Class对象),有关静态初始化的所有动作执行。因此,静态初始化只在Class对象首次加载的时候进行一次;
3、 当用new Dog()创建对象时,首先将堆上为Dog对象分配足够的空间;
4、 这块空间被清零;
5、 执行处于字段定义处的初始化;
6、 执行构造器。
5.7.3 显式的静态初始化
public
class
Spoon
{
static int i;
static{
i = 47;
}
}
5.7.4 非静态实例初始化
与上例显示的静态初始化一样,只是少了static关键字
5.8 数组初始化
一直对数组有一种畏惧心理,数组究竟是什么?书上第98页下面有一句话精确的给出了描述:“数组只是相同类型的、用一个标识符名称封装到一起的一个对象序列活基本类型数据序列。数组是通过方括号下标操作符[]来定义和使用的”。——忘记曾经学的哪门子语言了,用的是圆括号,似乎是VB,导致我混淆了很长一段时间。
要定义一个数字,只需在类型名后加上一个方括号即可:int[] a1;
在定义的时候不允许指定数组的大小,因为到现在为止,定义的只是对数组的引用,为数组在堆上分配空间必须写初始化表达式,如int[] a1 = {1, 2, 3, 4};
将数组赋值给另一个数组实际上赋值的是引用。
所有的数组都有一个固定的成员length,而下标是从0 ~ length – 1。
使用new创建数组元素:int[] a = new int[4] //尽管int是基本数据类型
如果创建的是一个非基本数据类型的数组,则是一个引用数组。
另外几种创建方式:
Integer[] a
=
{new Integer(1), new Integer(2), 3,}
;
Integer[] b
=
new
Integer[]
{new Integer(1), new Integer(2), 3,}
;
5.8.1可变参数列表
如:static void printArray(Object… args){
…
}
这是Java SE5 之后的新特性,等同于原先的用数组作为的参数:static void printArray(Object[] args){}
有了这种可变参数,就不需要显式地编写数组语法了,当你指定参数时,编译器会为你去填充数组。所以最终或得的仍然是一个数组!
5.9 枚举类型
enum 也是Java SE5 的一个新特性。
public
enum
Spiciness
{
NOT, MILD, MEDIUM , HOT, FLAMING
}
这里创建了一个名为Spiciness的枚举类型,具有5个具名值。
enum会自动创建toString()方法,ordinal()方法:表示某个特定enum常量的声明顺序,以及static values()
enum与switch语句绝配,减弱了switch本身的选择因子必须是int 或 char 那样的整数值的限制。
5.1 用构造器确保初始化
由于构造器的名称必须与类名相同,所以“每个方法首字母小写”的编码风格并不适用于构造器。
从概念上讲,“初始化”与“创建”是彼此独立的,而在JAVA中,“初始化”与“创建”捆绑在一起。
构造器是一种特殊类型的方法,因为它没有返回值。这与返回值为空(void)明显不同。对于空返回值,尽管方法本身不会自动返回什么,但仍然可选择让它返回别的东西。构造器则不会返回任何东西(new表达式确实返回了对新建对象的引用,但构造器本身并没有返回值)
5.2 方法重载
的确,方法重载对于构造器来说是必须的,所以《Thinking in Java》这本书很合理地将方法重载的内容安排在了构造器之后。
5.2.1 区分重载方法
每个重载的方法都必须有一个独一无二的参数类型列表。即,靠参数类型列表的不同来区分同名的不同方法。甚至参数顺序的不同也可以区分,但这样会使得代码难以阅读和维护。
5.2.2 涉及基本类型的重载
基本类型能从一个“较小”的类型自动提升至一个“较大”的类型,基于此情形,对于方法重载,如果传入的数据类型(实际参数类型)小于方法中声明的形式参数类型,实际数据类型就会被提升。Char类型略有不同,如果无法找到恰好接受char参数的方法,就会把char直接提升至int型。
如果传入的实际参数大于重载方法声明的形式参数,则需要做显式的窄化转换。
5.2.3-“以返回值区分重载方法是行不通的”。
5.3默认构造器(略)
5.4 this关键字
This关键字表示对当前对象的引用,只能在方法内部使用。
若要在构造器中调用其他的构造器,可用this。
通常this表示对当前对象的引用,而在构造器中,如果为this添加了参数列表,那么就有不同的含义。这将产生对符合此参数列表的某个构造器的明确调用。
但,尽管可以用this调用一个构造器,却不能调用两个。此外必须将调用置于起始处,否则编译器会报错。
并且,构造器只能从另一个构造器内部调用,构造器以外的方法不可以调用构造器。
在staitc方法的内部不能调用非静态方法。
5.5 清理:终结处理和垃圾回收
finalize()方法在垃圾回收之前执行。但并非析构函数。JAVA中并没有析构函数。
注意一下三点:
1.对象可能不被垃圾回收;
2.垃圾回收并不等于“析构”;
3.垃圾回收只与内存有关
System.gc()用于强制进行终结动作。
5.6成员的初始化
JAVA尽力保证:所有变量在使用前都能得到恰当的初始化。对于方法的局部变量,Java以编译时错误的形式来贯彻这种保证。(类成员用默认值)
如:
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
若类的数据成员是基本数据类型,会有默认初始值。
5.6.1 指定初始化:
如:
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
也可以通过调用某个方法来提供初始值,但要注意参数的初始化顺序,即方法的参数必须已经初始化了。
5.7 构造器的初始化
可以利用构造器进行成员的初始化,但要牢记:无法阻止自动初始化的进行,它将在构造器被调用之前发生。
5.7.1 初始化顺序
我觉得这一部分是重点!
在类的内部,变量定义的先后顺序决定了初始化的顺序。而即使变量定义散布于方法啊定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。
5.7.2 静态数据的初始化
无论创建多少个对象,静态数据都只占有一份存储区域——再次提醒。
静态对象会在非静态对象之前得到初始化。
总结一下对象的创建过程,假设有个名为Dog的类:
1、 当要创建Dog对象,或者Dog类的静态方法、静态域被访问时,Java解释器先定位Dog.class文件;
2、 载入Dog.class(这将创建一个Class对象),有关静态初始化的所有动作执行。因此,静态初始化只在Class对象首次加载的时候进行一次;
3、 当用new Dog()创建对象时,首先将堆上为Dog对象分配足够的空间;
4、 这块空间被清零;
5、 执行处于字段定义处的初始化;
6、 执行构造器。
5.7.3 显式的静态初始化
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
5.7.4 非静态实例初始化
与上例显示的静态初始化一样,只是少了static关键字
5.8 数组初始化
一直对数组有一种畏惧心理,数组究竟是什么?书上第98页下面有一句话精确的给出了描述:“数组只是相同类型的、用一个标识符名称封装到一起的一个对象序列活基本类型数据序列。数组是通过方括号下标操作符[]来定义和使用的”。——忘记曾经学的哪门子语言了,用的是圆括号,似乎是VB,导致我混淆了很长一段时间。
要定义一个数字,只需在类型名后加上一个方括号即可:int[] a1;
在定义的时候不允许指定数组的大小,因为到现在为止,定义的只是对数组的引用,为数组在堆上分配空间必须写初始化表达式,如int[] a1 = {1, 2, 3, 4};
将数组赋值给另一个数组实际上赋值的是引用。
所有的数组都有一个固定的成员length,而下标是从0 ~ length – 1。
使用new创建数组元素:int[] a = new int[4] //尽管int是基本数据类型
如果创建的是一个非基本数据类型的数组,则是一个引用数组。
另外几种创建方式:
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
5.8.1可变参数列表
如:static void printArray(Object… args){
…
}
这是Java SE5 之后的新特性,等同于原先的用数组作为的参数:static void printArray(Object[] args){}
有了这种可变参数,就不需要显式地编写数组语法了,当你指定参数时,编译器会为你去填充数组。所以最终或得的仍然是一个数组!
5.9 枚举类型
enum 也是Java SE5 的一个新特性。
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
这里创建了一个名为Spiciness的枚举类型,具有5个具名值。
enum会自动创建toString()方法,ordinal()方法:表示某个特定enum常量的声明顺序,以及static values()
enum与switch语句绝配,减弱了switch本身的选择因子必须是int 或 char 那样的整数值的限制。