编程红宝书(珍藏版) ava 完金自学手册 第8章对象的初始化和清理 在Java中一切皆为对象,所以在涉及到初始化和清理时必 然提及对象,即对象的初始化和对象的清理。对象的初始 化完成对象初始状态的设定,如初始化一些参数,构造 个新的对象等。对象的清除涉及到内存的操作,即对象在 不使用时必须有适当的机制释放该对象占用的内存,否则 内存中累积的对象很快会耗尽内存资源。 Java在创建一个新对象时引入了构造函数的概念,并且在 对象清除中引入了“垃圾回收器”,垃圾回收器可以自动 释放系统不再使用的内存资源,从而不会出现内存泄露的 问题,相比于C+语言而言更安全,程序员在编写代码时不 必考虑释放资源的代码,垃圾回收器完成内存资源释放工 作。本章讨论对象的初始化和对象的清理,本章的知识点 会显得零散,但是认真研究每节所讨论的问题,会对初始 化和清理有一个完整而清晰的认识 Q想桃工业出隙社
第8章 对象的初始化和清理 • 在Java中一切皆为对象,所以在涉及到初始化和清理时必 然提及对象,即对象的初始化和对象的清理。对象的初始 化完成对象初始状态的设定,如初始化一些参数,构造一 个新的对象等。对象的清除涉及到内存的操作,即对象在 不使用时必须有适当的机制释放该对象占用的内存,否则 内存中累积的对象很快会耗尽内存资源。 • Java在创建一个新对象时引入了构造函数的概念,并且在 对象清除中引入了“垃圾回收器”,垃圾回收器可以自动 释放系统不再使用的内存资源,从而不会出现内存泄露的 问题,相比于C++语言而言更安全,程序员在编写代码时不 必考虑释放资源的代码,垃圾回收器完成内存资源释放工 作。本章讨论对象的初始化和对象的清理,本章的知识点 会显得零散,但是认真研究每节所讨论的问题,会对初始 化和清理有一个完整而清晰的认识
编程红宝书(珍藏版) ava 完金自学手册 8.1构造函数 构造函数是Java中一种特殊的函数,通过构造函数可以顺利的完成对象的初始化工作,当创建一个 新的对象时,Java首先调用构造函数确保对象得到适当的初始化。 构造函数与普通函数有不同之处 (1)构造函数没有返回值,其实也不需要返回值,虽然创建对象时确实返回了对象引用,但是构 造函数本身不允许返回任何数据类型。 (2)构造函数的名称必须和其相应的类具有相同的名字,大小写完全一样。因为构造函数的调用 是Java完成的,所以必须让编译器知道如何找到构造函数,而编译器在加载类时就已经知道了构造 函数的“样子”了,所以很容易在类中找到该函数而初始化一些参数。 (3)构造函数在每次创建新对象时被编译器自动调用。 代码是带有构造函数的类的例子 代码带有构造函数的类示例 1 class Treef 2建构造函数,函数名与类回名,构造函数没有返回值。 System. out printing Tree is creating) 5 7 public class Simple Constructor public static void main(Stringl args for(int=0;1<6++ 建Tree对象,此时纳译册自动调用构适函数 TreeO,完成对象的初始化工作, 13} 141 Q想桃工业出隙
8.1 构造函数 • 构造函数是Java中一种特殊的函数,通过构造函数可以顺利的完成对象的初始化工作,当创建一个 新的对象时,Java首先调用构造函数确保对象得到适当的初始化。 • 构造函数与普通函数有不同之处: • (1)构造函数没有返回值,其实也不需要返回值,虽然创建对象时确实返回了对象引用,但是构 造函数本身不允许返回任何数据类型。 • (2)构造函数的名称必须和其相应的类具有相同的名字,大小写完全一样。因为构造函数的调用 是Java完成的,所以必须让编译器知道如何找到构造函数,而编译器在加载类时就已经知道了构造 函数的“样子”了,所以很容易在类中找到该函数而初始化一些参数。 • (3)构造函数在每次创建新对象时被编译器自动调用。 • 代码是带有构造函数的类的例子
编程红宝书(珍藏版) ava 完金自学手册 8.1.1默认构造函数 默认构造函数是用户没有定义的情况下,系统自动调用的构造函数,任何一个 类在创建新对象时都是需要构造函数完成初始化的,如果用户没有定义构造函 数,编译器就认为用户同意按照系统默认的方式构造该对象了。但是这个调用 用户看不见,是系统的内部行为。是潜在的一种函数调用 代码默认构造函数的示例程序可以说明这种情况。 代码默认构造函数示例 class Tree t 2 public void setHeighto( 3 System. out. println("set the height of the tree 46754 7 public class SimpleConstructor I public static void main(String[] args)i ∥/创建新对象,并赋予对象引用tree,此时调用默认构造函 数 Tree tree new Tree o tree. setHeighto Q想桃工业出隙社
8.1.1 默认构造函数 • 默认构造函数是用户没有定义的情况下,系统自动调用的构造函数,任何一个 类在创建新对象时都是需要构造函数完成初始化的,如果用户没有定义构造函 数,编译器就认为用户同意按照系统默认的方式构造该对象了。但是这个调用 用户看不见,是系统的内部行为。是潜在的一种函数调用。 • 代码默认构造函数的示例程序可以说明这种情况。 • 代码 默认构造函数示例 • 1 class Tree{ • 2 public void setHeight(){ • 3 System.out.println(“set the height of the tree!”); • 4 } • 6 } • 7 public class SimpleConstructor{ • 5 public static void main(String[] args){ • 4 //创建新对象,并赋予对象引用tree,此时调用默认构造函 数 • 11 Tree tree = new Tree(); • 12 tree.setHeight(); • 13 } • 14 }
编程红宝书(珍藏版) ava 完金自学手册 8.1.2自定义构造函数 Java提供了另一种构造函数的定义方式,即用户自定义的构造函数。这种思想很容易理解,对象的 创建一定满足需求,而对象的初始化自然不能千篇一律的按照固定的模式。这样用户依据需求分析 设计的类在初始化时自然具有多样性。用户自定义的构造函数分为有参数的构造函数和无参数的构 造函数。 Java也允许一个类具有多个构造函数,在创建对象时编译器根据构造函数的参数类型和参数个数来 分辨调用哪个构造函数(这里涉及到函数重载的概念),代码展示了一个类具有多个构造函数的情 如代码默认构造函数示例 class Tree int treeheight Treet ∥创建无参数构造函数 23456789012构34 System. out println(“初始化无参数Tree); Tree(int heig ∥刨建有参数构造函数,参数设置Tree的高度 treeheight = height System. out. println(“初始化有参数Tree); public static void main(Stringl args new TreeO ∥创建Tree对象,系统调用无参数构造函数 new Tree(12) ∥刨建Tree对象,系统调用有参数 造函数 Q想桃工业出隙社
8.1.2 自定义构造函数 • Java提供了另一种构造函数的定义方式,即用户自定义的构造函数。这种思想很容易理解,对象的 创建一定满足需求,而对象的初始化自然不能千篇一律的按照固定的模式。这样用户依据需求分析 设计的类在初始化时自然具有多样性。用户自定义的构造函数分为有参数的构造函数和无参数的构 造函数。 • Java也允许一个类具有多个构造函数,在创建对象时编译器根据构造函数的参数类型和参数个数来 分辨调用哪个构造函数(这里涉及到函数重载的概念),代码展示了一个类具有多个构造函数的情 况。 • 如代码 默认构造函数示例 • 1 class Tree{ • 2 int treeheight ; • 3 Tree(){ //创建无参数构造函数 • 4 System.out.println(“初始化无参数Tree”); • 5 } • 6 Tree(int height){ //创建有参数构造函数,参数设置Tree的高度 • 7 treeheight = height; • 8 System.out.println(“初始化有参数Tree”); • 9 } • 10 public static void main(String[] args){ • 11 new Tree(); //创建Tree对象,系统调用无参数构造函数 • 12 new Tree(12); //创建Tree对象,系统调用有参数 构造函数 • 13 } • 14 }
编程红宝书(珍藏版) ava 完金自学手册 8.2函数的重载 函数是对象的行为特性,或者说是一种动作,为函数起名 字相当于为行为取名字,这样的名字要求具有实际意义, 易于理解和维护。如定义一个读数据库的方法 Readdatabase(,这样的函数名字就易于理解,也很好的 说明了行为的内容是读数据库信息。但是同样的读数据库 信息的方法也有区别,如一个系统有多个数据库,有本地 数据库和网络数据库,那到底是读本地数据库呢还是读取 网络数据库的信息呢,所以为了区别具有相同行为内容却 又有差异的函数,Java提供了函数重载的概念 我们可以设置如上的 ReadDataBase o方法的参数来区分到 底读哪个数据库的信息,如果是读取本地数据库的信息, 可以传入一个本地数据库链接的字符串,或不用参数,如 果是链接网络数据库可以传入一个网络地址,这样具有同 名的方法通过形式参数的不同而实现了方法重载,在构造 函数中我们提到过重载的概念,这里通过一个例子说明构 造函数重载和普通函数重载的实现。 Q想桃工业出隙社
8.2 函数的重载 • 函数是对象的行为特性,或者说是一种动作,为函数起名 字相当于为行为取名字,这样的名字要求具有实际意义, 易于理解和维护。如定义一个读数据库的方法 ReadDataBase(),这样的函数名字就易于理解,也很好的 说明了行为的内容是读数据库信息。但是同样的读数据库 信息的方法也有区别,如一个系统有多个数据库,有本地 数据库和网络数据库,那到底是读本地数据库呢还是读取 网络数据库的信息呢,所以为了区别具有相同行为内容却 又有差异的函数,Java提供了函数重载的概念。 • 我们可以设置如上的ReadDataBase()方法的参数来区分到 底读哪个数据库的信息,如果是读取本地数据库的信息, 可以传入一个本地数据库链接的字符串,或不用参数,如 果是链接网络数据库可以传入一个网络地址,这样具有同 名的方法通过形式参数的不同而实现了方法重载,在构造 函数中我们提到过重载的概念,这里通过一个例子说明构 造函数重载和普通函数重载的实现
编程红宝书(珍藏版) ava 8.3数据成员初始化 Java提供了一种安全机制,可以保证所有的数据成员都得到适当得初始化。对于基本类型的数据成 员,Java不要求必须为其赋予有意义的初始值,但是为了保证安全性提供了一个默认值,所有的基 本类型的数据在被方法调用前都会得以适当的初始化,如果用户没有为数据成员赋值,编译器就使 用默认值为其完成初始化。 可以通过代码基本数据初始化示例看到这些默认值 如代码基本数据初始化示例 short b 4 float d 6 7 byte f 8 ch lbic static void (String[ args)( System. out. println(" System. out. println(short b: " +b) printIn( System.out. printIn(“ float d:”+d) System. out. println("Boolean e: +e) 15 System. out. println( byte f: +f) System. out. printin(“ char g:”+g) Q想桃工业出隙 18
8.3 数据成员初始化 • Java提供了一种安全机制,可以保证所有的数据成员都得到适当得初始化。对于基本类型的数据成 员,Java不要求必须为其赋予有意义的初始值,但是为了保证安全性提供了一个默认值,所有的基 本类型的数据在被方法调用前都会得以适当的初始化,如果用户没有为数据成员赋值,编译器就使 用默认值为其完成初始化。 • 可以通过代码基本数据初始化示例看到这些默认值。 • 如代码 基本数据初始化示例 • 1 class InitValues{ • 2 int a; • 3 short b • 4 long c; • 5 float d; • 6 boolean e; • 7 byte f; • 8 char g; • 9 public static void main(String[] args){ • 10 System.out.println(“int a :”a); • 11 System.out.println(“short b :”+b); • 12 System.out.println(“long c :”+c); • 13 System.out.println(“float d :”+d); • 14 System.out.println(“Boolean e :”+e); • 15 System.out.println(“byte f :”+f); • 16 System.out.println(“char g :”+g); • 17 } • 18 }
编程红宝书(珍藏版) ava 完金自学手册 8.4 static成员的初始化 由 static关键字修饰的成员的初始化与基本类型的数据成员的初始化基本 致。如果 static修饰的是基本类型而没有赋予初始值,就采用默认值。 如果 static修饰的是对象引用,若引用没有类的实例初始化则为nu1l。该 问题。代吗 static成员初始化示例移 Static成员初始化中需要注意的 对象引用无法使用。通过下面的例子说明 cAc: \YINNT\systen 32\cmd D: \source code \ch8code>javac StaticIni jau :\source code\h8code >java StaticIni kage) MyRoon) in main ting new My Roon Q想桃工业出隙社 taic成员初始化示例的执行结果
8.4 static成员的初始化 • 由static关键字修饰的成员的初始化与基本类型的数据成员的初始化基本 一致。如果static修饰的是基本类型而没有赋予初始值,就采用默认值。 如果static修饰的是对象引用,若引用没有类的实例初始化则为null。该 对象引用无法使用。通过下面的例子说明static成员初始化中需要注意的 问题。代码static成员初始化示例程序
编程红宝书(珍藏版) ava 完金自学手册 8.5对象的清理 Java的对象清理与C艹+不同,在C++所有的对象清理工作 都由程序员自己处理,即编写对应的析构函数释放对象占 用的资源,如果程序员没有编写释放资源的代码则肯定会 造成内寻泄露。而在Java中,不再采用这种方式来释放资 源,而是采用了垃圾回收机制(GC)实现对象资源的释放, 这就极大的提高了编程的效率,让程序员可以集中精力于 问题模型的解决上 垃圾回收机制在实现对象资源释放时只管理使用new关键字 创建的对象所占用的内存资源。所以,对于其他对象占用 的资源垃圾回收机制无法管理,所以严格的说垃圾回收机 制可以有效的管理内存资源,保证不发生内存的资源泄露 但是却无法保证其他资源的泄露,Java提供了一个 final1y 关键字,使某些代码总是可以执行来避免其他资源的泄露 发生。如果没有 finally,问题会很复杂。这里只要求初学 者知道这个问题,至于更具体的解释读者可以自己学习 可以参考[美] Peter Haggar著的 Practical Java,该书的 很多主题对于初学者而言都有很好的指导作用。Q想出盐
8.5 对象的清理 • Java的对象清理与C++不同,在C++中所有的对象清理工作 都由程序员自己处理,即编写对应的析构函数释放对象占 用的资源,如果程序员没有编写释放资源的代码则肯定会 造成内寻泄露。而在Java中,不再采用这种方式来释放资 源,而是采用了垃圾回收机制(GC)实现对象资源的释放, 这就极大的提高了编程的效率,让程序员可以集中精力于 问题模型的解决上。 • 垃圾回收机制在实现对象资源释放时只管理使用new关键字 创建的对象所占用的内存资源。所以,对于其他对象占用 的资源垃圾回收机制无法管理,所以严格的说垃圾回收机 制可以有效的管理内存资源,保证不发生内存的资源泄露。 但是却无法保证其他资源的泄露,Java提供了一个finally 关键字,使某些代码总是可以执行来避免其他资源的泄露 发生。如果没有finally,问题会很复杂。这里只要求初学 者知道这个问题,至于更具体的解释读者可以自己学习, 可以参考[美]Peter Haggar著的Practical Java,该书的 很多主题对于初学者而言都有很好的指导作用
编程红宝书(珍藏版) ava 完金自学手册 8.6本章习题 学完本章中,读者需要回答: (1)什么叫函数重载?重载的意义何在?如何实现函数重载 的? (2)详细说明数据成员初始化的方法和数据成员初始化的顺 序 (3) Static的含义,在对象的初始化中为什么需要首先初始 化 static成员。 (4)创建一个带无参数构造函数的类,并在构造函数中打印 条信息。同时为该类创建一个对象 (5)创建一个带参数的构造函数的类,其接受一个字符串参 数,在构造函数中打印这个字符串。 (6)创建一个没有构造函数的类,并在main(中创建对象, 验证编译器是否真的自动加入了缺省构造函数。 (7)分析代码8-7中如下代码的执行过程 56 static MyRoom t3= new MyRoomO ·可以参考对象的创建过程分析 Q想桃工业出隙社
8.6 本章习题 • 学完本章中,读者需要回答: • (1)什么叫函数重载?重载的意义何在?如何实现函数重载 的? • (2)详细说明数据成员初始化的方法和数据成员初始化的顺 序。 • (3)Static的含义,在对象的初始化中为什么需要首先初始 化static成员。 • (4)创建一个带无参数构造函数的类,并在构造函数中打印 一条信息。同时为该类创建一个对象。 • (5)创建一个带参数的构造函数的类,其接受一个字符串参 数,在构造函数中打印这个字符串。 • (6)创建一个没有构造函数的类,并在main()中创建对象, 验证编译器是否真的自动加入了缺省构造函数。 • (7)分析代码8-7中如下代码的执行过程: • 56 static MyRoom t3 = new MyRoom(); • 可以参考对象的创建过程分析