Java编程思想 第5章 初始化与清理
来源:互联网 发布:cpu网络营销策划书 编辑:程序博客网 时间:2024/05/17 02:22
Java编程思想 第5章 初始化与清理
标签(空格分隔): JAVA学习
- Java编程思想 第5章 初始化与清理
- 1 用构造器确保初始化
- 2 方法重载
- 21 区分重载方法
- 22 涉及基本类型的重载
- 23 以返回值区分重载方法
- 3 默认构造器
- 4 this关键字
- 41 在构造器中调用构造器
- 42 static的含义
- 5 清理终结处理和垃圾回收
- 6 成员初始化
- 61 指定初始化
- 7 构造器初始化
- 71 初始化顺序
- 72 静态数据的初始化
- 73 显示的静态初始化
- 74 非静态实例初始化
- 8 数组初始化
- 81 可变参数列表转载
- 9 枚举类型
5.1 用构造器确保初始化
不接受任何参数的构造器叫做默认构造器,构造器的名称必须与类名完全相同。
如果类中没有构造器,编译器会自动创建一个默认构造器。
如果已经定义了一个构造器(无论是否有参数),编译器则不会自动创建默认构造器。
class Rock { Rock() { System.out.print("Rock "); }}class Rock2 { Rock2(int i) { System.out.print("Rock2 " + i + " "); }}public class SimpleConstructor { public static void main(String[] args) { for (int i = 0; i < 10; i++) { new Rock(); } System.out.println(""); for (int i = 0; i < 8; i++) { new Rock2(i); } }}
Output:Rock Rock Rock Rock Rock Rock Rock Rock Rock Rock Rock2 0 Rock2 1 Rock2 2 Rock2 3 Rock2 4 Rock2 5 Rock2 6 Rock2 7
5.2 方法重载
方法重载:方法名相同,形参不同。
class Tree { int height; Tree() { System.out.println("Planting a seedling"); height = 0; } // 重载的构造器 Tree(int initialHeight) { height = initialHeight; System.out.println("Creating new Tree that is " + height + " feet tall"); } void info() { System.out.println("Tree is " + height + " feet tall"); } // 重载的方法 void info(String s) { System.out.println(s + ": Tree is " + height + " feet tall"); }}public class Overloading { public static void main(String[] args) { for (int i = 0; i < 5; i++) { Tree t = new Tree(i); t.info(); t.info("overloaded method"); System.out.println(""); } System.out.println(""); new Tree(); }}/* Output:Creating new Tree that is 0 feet tallTree is 0 feet talloverloaded method: Tree is 0 feet tallCreating new Tree that is 1 feet tallTree is 1 feet talloverloaded method: Tree is 1 feet tallCreating new Tree that is 2 feet tallTree is 2 feet talloverloaded method: Tree is 2 feet tallCreating new Tree that is 3 feet tallTree is 3 feet talloverloaded method: Tree is 3 feet tallCreating new Tree that is 4 feet tallTree is 4 feet talloverloaded method: Tree is 4 feet tallPlanting a seedling*/
5.2.1 区分重载方法
区分规则:每个重载的方法都必须有一个独一无二的参数类型列表(参数顺序不同也足以区分两个方法,但会使代码难以维护)。
注意:参数类型列表相同,根据返回值来区分重载方法是行不通的。
5.2.2 涉及基本类型的重载
实参类型 < 重载方法声明的形参类型
- 基本类型能从一个“较小”的类型自动提升至一个“较大”的类型
- char类型略有不同,如果无法找到恰好接受char参数的方法,就会把char直接提升至int型。
实参类型 > 重载方法声明的形参类型
必须通过类型转换来执行“窄化转换”,否则编译器会报错。
5.2.3 以返回值区分重载方法
根据返回值来区分重载方法是行不通的。
5.3 默认构造器
不接受任何参数的构造器叫做默认构造器,构造器的名称必须与类名完全相同。
如果类中没有构造器,编译器会自动创建一个默认构造器。
如果已经定义了一个构造器(无论是否有参数),编译器则不会自动创建默认构造器。
5.4 this关键字
this关键字只能在方法内部使用,表示对“调用方法的那个对象”的引用。但要注意,如果在方法内部调用同一个类的别一个方法,就不必使用this。只有当明确指出对当前对象的引用时,才需要使用this关键字。
this关键字对于将当前对象传递给其他方法也很有用:
class Person { public void eat(Apple apple) { Apple peeled = apple.getPeeled(); System.out.println("Yummy"); }}class Peeler { static Apple peel(Apple apple) { // ... remove peel return apple; // Peeled }}class Apple { Apple getPeeled() { // 将自身对象传递给其他方法 return Peeler.peel(this); }}public class PassingThis { public static void main(String[] args) { new Person().eat(new Apple()); }}*/ Output:Yummy*/
5.4.1 在构造器中调用构造器
- 尽管可以用this调用一个构造器,但却不能调用两个。
- 必须将构造器调用置于最起始处。
- 除构造器外,编译器禁止在其他任何方法中调用构造器。
public class Flower { int petalCount = 0; String s = "initial value"; Flower(int petals) { petalCount = petals; System.out.println("Constructor w/ int arg only, petalCount = " + petalCount); } Flower(String ss) { System.out.println("Constructor w/ String arg only, s = " + ss); s = ss; } Flower(String s, int petals) { this(petals); // 可以用this调用一个构造器,但却不能调用两个。// this(s); // Can't call two! this.s = s; System.out.println("String & int args"); } Flower() { // 必须将构造器调用置于最起始处。 this("hi", 47); System.out.println("default constructor (no args)"); } void printPetalCount() { // 除构造器外,编译器禁止在其他任何方法中调用构造器。// this(11); // Not inside non-constructor System.out.println("petalCount = " + petalCount + " s = " + s); } public static void main(String[] args) { Flower x = new Flower(); x.printPetalCount(); }}/* Output:Constructor w/ int arg only, petalCount = 47String & int argsdefault constructor (no args)petalCount = 47 s = hi*/
5.4.2 static的含义
- static方法就是没有this的方法,可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。
- 在static方法的内部不能调用非静态方法,反过来可以。
5.5 清理:终结处理和垃圾回收
5.6 成员初始化
- 方法中的局部变量必须提供初始值
void f() { int i; i++; // Error -- i not initialized}
- 类的每个基本类型数据成员默认都会有初始值
- 在类里定义一个对象的引用(如下面的InitialValues)时,如果不将其初始化,此引用就会获得一个特殊值null。
public class InitialValues { boolean t; char c; byte b; short s; int i; long l; float f; double d; InitialValues reference; void printInitialValues() { System.out.println("Data type Initial value"); System.out.println("boolean " + t); System.out.println("char " + c); System.out.println("byte " + b); System.out.println("short " + s); System.out.println("int " + i); System.out.println("long " + l); System.out.println("float " + f); System.out.println("double " + d); System.out.println("InitialValues " + reference); } public static void main(String[] args) { InitialValues iv = new InitialValues(); iv.printInitialValues(); }}/* Output:Data type Initial valueboolean falsechar [] byte 0short 0int 0long 0float 0.0double 0.0InitialValues null*/
5.6.1 指定初始化
1、在定义类成员变量的地方为其赋值。
class Depth {}public class InitialValues { boolean t = true; char c = 'x'; byte b = 47; short s = 0xff; int i = 999; long l = 1; float f = 3.14f; double d = 3.14159; // 初始化非基本类型的对象 Depth d = new Depth();}
2、调用某个方法来提供初值
public class MethodInit { int i = f(); int f() { return 11; }}
3、调用某个方法来提供初值,方法可以带参数,但参数必须已经被初始化
5.7 构造器初始化
5.7.1 初始化顺序
在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。
class Window { Window(int marker) { System.out.println("Window(" + marker + ")"); }}class House { Window w1 = new Window(1); House() { System.out.println("House()"); w3 = new Window(33); } Window w2 = new Window(2); void f() { System.out.println("f()"); } Window w3 = new Window(3);}public class OrderOfInitialization { public static void main(String[] args) { House h = new House(); h.f(); }}/* Output:Window(1)Window(2)Window(3)House()Window(33)f()*/
5.7.2 静态数据的初始化
无论创建多少个对象,静态数据都只占用一份存储区域。
static关键字不能应用于局部变量(即不用应用于方法或构造器中),因此它只能作用于域。
初始化的顺序是先静态对象,而后是“非静态”对象。
类中的非静态数据成员在每次创建新的对象时会进行初始化(如下面代码中的7,9,11,bowl3初始化了3次),而静态数据成员只有在第一次创建对象时才会进行初始化。
class Bowl { Bowl(int marker) { System.out.println("Bowl(" + marker + ")"); } void f1(int marker) { System.out.println("f1(" + marker + ")"); }}class Table { // 2. 创建Bow1(1)对象 static Bowl bowl1 = new Bowl(1); Table() { System.out.println("Table()"); bowl2.f1(1); } void f2(int marker) { System.out.println("f2(" + marker + ")"); } // 3. 创建Bowl(2)对象 static Bowl bowl2 = new Bowl(2);}class Cupboard { // 7. 创建Bowl(3)对象 // 9. 再创建Bowl(3)对象 // 11. 第三次创建Bowl(3)对象 Bowl bowl3 = new Bowl(3); // 5. 创建Bowl(4)对象 static Bowl bowl4 = new Bowl(4); Cupboard() { System.out.println("Cupboard"); bowl4.f1(2); } void f3(int marker) { System.out.println("f3(" + marker + ")"); } // 6. 创建Bowl(5)对象 static Bowl bowl5 = new Bowl(5);}public class StaticInitialization { public static void main(String[] args) { System.out.println("Creating new Cupboard() in main"); // 8. 创建Cupboard对象 new Cupboard(); System.out.println("Creating new Cupboard() in main"); // 10. 创建Cupboard对象 new Cupboard(); table.f2(1); cupboard.f3(1); } // 1. 创建Table对象 static Table table = new Table(); // 4. 创建Cupboard对象 static Cupboard cupboard = new Cupboard();}/* Output:Bowl(1)Bowl(2)Table()f1(1)Bowl(4)Bowl(5)Bowl(3)Cupboardf1(2)Creating new Cupboard() in mainBowl(3)Cupboardf1(2)Creating new Cupboard() in mainBowl(3)Cupboardf1(2)f2(1)f3(1)*/
5.7.3 显示的静态初始化
Java允许将多个静态初始化动作组织成一个特殊的“静态子句”,有时也叫做“静态块”。
public class Spoon { static int i; static { i = 47; }}
5.7.4 非静态实例初始化
与静态初始化子句一样,只是少了static关键字。
5.8 数组初始化
声明数组的两种方式:
int[] a; // recommendint a[];
声明数组时不能指定其长度(数组中元素的个数)
数组初始化
通过上边的定义,我们只是得到了一个数组的引用。这时已经为引用分配了存储空间,但是还没有给数组对象本身分配任何空间。想要给数组对象分配存储空间,必须使用初始化表达式。
初始化:
1.动态初始化:数组定义与为数组分配空间和赋值的操作分开进行;
int[] a = new int[5];for (int i = 0; i < a.length; i++) { a[i] = i;}
2.静态初始化:在定义数字的同时就为数组元素分配空间并赋值;
int[] a1 ={1, 2, 3, 4, 5}; // 在数组创建的地方进行初始化int[] a2 = new int[]{1, 2, 3, 4, 5}; // 该方法更灵活
3.默认初始化:数组是引用类型,它的元素相当于类的成员变量,因此数组分配空间后,每个元素也被按照成员变量的规则被隐士初始化。
int[] a = new int[5];
在Java中可以将一个数组赋值给另一个数组,所以可以这样:
int[] a1 = {1, 2, 3, 4, 5}; // 在数组创建的地方进行初始化int[] a2;a2 = a1; // 只是复制了一个引用,对a2的修改也会修改到a1
public class ArraysOfPrimitives { public static void main(String[] args) { int[] a1 = {1, 2, 3, 4, 5}; int[] a2; a2 = a1; for (int i = 0; i < a2.length; i++) { a2[i]++; } for (int i = 0; i < a1.length; i++) { System.out.println("a1[" + i + "] = " + a1[i]); } }}
所有的数组都有一个固定成员length,通过它可以知道数组元素的个数。
Output:
a1[0] = 2a1[1] = 3a1[2] = 4a1[3] = 5a1[4] = 6
5.8.1 可变参数列表(转载)
下图标出了参数列表的使用方式、格式和对传入参数的要求。
- 列表参数类型可以不同的情况
可变参数类型为Object,因为所有的类都直接或间接的继承自Object类,可以向上转型为Object,因此参数列表中的类型可以不一致。
输出如下图: - 列表参数类型必须相同的情况
当然可变参数参数列表也可以作为函数的一个参数传入,如下图。这里的参数列表中的参数类型为string,则所有的参数必须是string类型,与上面的程序不同。 - 可变参数列表中的参数可以是任何类型,包括基本类型
- 可变参数列表和自动包装机制
- 可变参数列表与函数重载
在上面的所有带参数的函数调用,编译器都会使用自动包装机制来匹配重载的方法,然后调用最匹配的方法。但是不使用使用参数来f()时,编译器会二义性错误:
Exception in thread “main” java.lang.Error: Unresolved compilation problem:
The method f(Character[]) is ambiguous for the type OverloadingVarargs
at thingjinjava.OverloadingVarargs.main(OverloadingVarargs.java:25)
那么,如何解决这个问题呢?
可以尝试着在方法中都增加一个非可变参数来解决该问题。
你应该总是只在重载方法的一个版本上使用可变参数列表,或者压根就不用它。
5.9 枚举类型
Java SE5中添加了enum关键字
enum Spiciness { NOT, MILD, MEDIUM, HOT, FLAMING}public class SimpleEnumUse { public static void main(String[] args) { Spiciness howHot = Spiciness.MEDIUM; System.out.println(howHot); for (Spiciness s : Spiciness.values()) { System.out.println(s + ", ordinal " + s.ordinal()); } }}
这里创建了一个名为Spiciness的枚举类型,它具有5个具名值。由于枚举类型的实例是常量,因此按照命名惯例它们都用大写字母表示。
enum有一个特别实用的特性,即它可以在switch语句中使用:
public class Burrito { Spiciness degree; public Burrito(Spiciness degree) { this.degree = degree; } public void describe() { System.out.println("This burrito is "); switch (degree) { case NOT: System.out.println("not spicy at all. "); break; case MILD: case MEDIUM: System.out.println("a little hot"); break; case HOT: case FLAMING: default: System.out.println("maybe too hot"); } } public static void main(String[] args) { Burrito plain = new Burrito(Spiciness.NOT), greenChile = new Burrito(Spiciness.MEDIUM), jalapeno = new Burrito(Spiciness.HOT); plain.describe(); greenChile.describe(); jalapeno.describe(); }}
Output:
This burrito is not spicy at all. This burrito is a little hotThis burrito is maybe too hot
- Java编程思想第5章:初始化与清理
- Java编程思想 第5章 初始化与清理
- 《Java 编程思想》-第5章 初始化和清理 笔记
- 《Java编程思想》--初始化和清理--第5章
- 5初始化与清理-Java编程思想
- 控制执行流程,初始化与清理-java编程思想-第4、5章
- Java编程思想学习笔记(四) 第5章 初始化与清理
- [学习笔记][Java编程思想]第5章:初始化与清理
- 初始化与清理【java编程思想杂记】
- <Java编程思想> 初始化与清理
- 《JAVA编程思想》笔记-初始化与清理
- 【Java编程思想】(1)初始化与清理
- Java编程思想之清理与初始化
- Java编程思想之初始化与清理
- java 编程思想--初始化与清理
- Java编程思想-05初始化与清理
- Java编程思想初始化与清理
- JAVA编程思想笔记--初始化与清理
- NS2初学笔记(五)之 数据包流初探
- asp.net中的按钮点击事件
- JDK1.5以后有关classpath环境变量的讨论
- CS231n课程翻译系列
- oralce归档日志的手动删除
- Java编程思想 第5章 初始化与清理
- c++函数模板和类模板
- Java基础语法(二)—基本数据类型转换
- MD算法
- Java编程思想 第6章 访问权限控制
- kotlin 链接视频和api中文
- OpenMP 并行区域之间的工作共享方法
- Java编程思想 第7章 复用类
- Python列表推导式