第5章 初始化与清理

第5章 初始化与清理

标签(空格分隔): Java编程思想 初始化与清理


1 用构造器确保初始化

  • 构造器与类名相同
    注意:由于构造器的名称必须与类名完全相同,所以”每个方法首字母小写”的编码风格并不适用与构造器。
  • 构造器是一种特殊的方法,所以它没有返回值。

2 方法重载

为了使方法名相同而参数列表不同的构造器同时存在,必须用到方法重载。
重写:即做不同的事,输入相同,产生不同的结果。
重载:信息输入不同(参数列表不同)。
每个重载的方法必须有一个独一无二的参数类型列表。甚至参数顺序不同也足以区分两个方法,但一般别这么做,因为这会使代码难以维护。

涉及基本类型的重载:
基本类型能从一个较小的类型自动提升到一个较大的类型。
char型略有不同,如果无法找到恰好接受char参数的方法,就自动把char直接提升至int型。
在这里方法接受较小的基本类型作为参数。如果传入的实际参数较大,就得通过类型转换来执行窄化转换。如果不这样做,编译器会报错。

3 默认构造器

若写的类中没有构造器,则编译器会自动帮你创建一个默认构造器。但是如果你已经定义了一个构造器(无论是否有参数),编译器就不会帮你自动创建默认构造器,调用默认构造器会报错。

4 this关键字

this关键字只能在方法内部使用,表示对”调用方法的那个对象”的引用。但要注意如果在方法内部调用同一个类的另一个方法,就不必使用this,直接调用即可。只有当需要明确指出对当前对象的引用时,才需要使用this关键字。

1. 在构造器中调用构造器

通常写this的时候,都是指“这个对象”或者“当前对象”,而且本身表示对当前对象的引用。在构造器中,如果为this添加了参数列表,那么就有了不同的含义。这将产生对符合此参数列表的某个构造器的明确调用;这样调用构造器就有了直接途径。

注意:

  • this可以调用一个构造器,但却不能调用两个构造器,此外,必须将构造器调用置于最起始处,否则编译器会报错。
  • 如果参数s的名称和数据成员s的名字相同,会产生歧义。使用this.s来代表数据成员就能解决这个问题
  • 除构造器之外,编译器禁止在其他任何方法中调用构造器。

2. static含义

static方法就是没有this的方法。在static方法中不能调用非静态方法,反过来倒可以。而且可以在没有创建任何对象的前提下,仅仅通过类本身来调用static方法。

5 清理:终结处理和垃圾回收

假定你的对象(并非使用new)获得了一块“特殊”的内存区域,由于垃圾回收器只知道释放那些由new分配的内存,所以它不知道该如何释放该对象的这块“特殊”内存。

Java允许在类中定义一个finalize()方法。它的工作原理“假定”是这样的:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法,并且在下一次垃圾回收器动作发生时,才会真正回收对象占用的内存。所以要是打算调用finalize(),就能在垃圾回收时做一些重要的清理工作。

Java里的对象并非总是被垃圾回收:

  1. 对象可能不被垃圾回收。
  2. 垃圾回收并不等于“析构”。
  3. 垃圾回收只与内存有关。
    使用垃圾回收器的唯一原因是为了回收程序不再使用的内存。对于与垃圾回收有关的任何行为来说(尤其是finalize()方法),它们也必须同内存及其回收有关。
    不要过多地使用finalize(),它确实不是进行普通清理工作。

终结条件
System.gc()用于强制进行终结动作。
应该总是假设积累版本的finalize()也要做某些重要的事情,因此要使用super来调用它 super.finalize()。

6 成员初始化

类的每个基本类型数据成员都会有一个默认的初始值。

7 构造器初始化

无法阻止自动初始化的进行,它将在构造器被调用前发生。

1. 初始化顺序

在类内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散布于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。

2. 静态数据的初始化

无论创建多少个对象,静态数据都只占用一份存储区域。
static关键爱你子不能应用于局部变量,它只能作用于域。

初始化顺序:
先域初始化(先static后非static)—>再构造器初始化—>调用方法
先静态对象,(如果它们尚未因前面的对象创建过程而被初始化),而后是“非静态”初始化对象。
总结一下对象创建过程,假设有个名为Dog的类:
1. 即使没有显式使用static关键字,构造器实际上也是静态方法。因此,当首次创建类为Dog的对象时,(构造器可以看成是静态方法),或者Dog类的静态方法/静态域首次被访问时,Java解释器必须查找类路径,以定位Dog.class文件。
2. 然后载入Dog.class(后面学到,这将创建一个Class对象),有关静态初始化的所有动作都会执行。因此,静态初始化值在Class对象首次加载的时候进行一次。
3. 当用new Dog()创建对象的时候,首先将在堆上为Dog对象分配足够的存储空间。
4. 这块存储空间会被清零,这就自动地将Dog对象中的所有基本类型数据都设置成默认值。(对数字来说就是0,对布尔值和字符型也相同),而引用则被设置成了null。
5. 执行所有出现于字段定义处的初始化动作。
6. 执行构造器。

3. 显式的静态初始化

Java允许将多个静态初始化动作组织成一个特殊的静态子句(静态块)。

    static{
        ...
        ...
    }

这段代码只执行一次:当首次生成类的一个对象时,或者首次访问属于这个类的静态数据成员时(即使从未生成过那个类的对象)。

4. 非静态实例初始化

与静态初始化类似,只是没有static修饰,会执行多次。实例初始化子句在构造器之前执行。

8 数组初始化

编译器不允许指定数组的大小。

int[] a;
或
int a1[];

对于数组,初始化动作可以出现在代码的任何地方,但也可以使用一种特殊的初始化表达式,它必须在创建数组的地方出现。这种特殊的初始化是由一对花括号括起来的值组成的。

int[] a={1,2,3,4,5,6};

在Java中可以将一个数组赋值给另一个数字

a1=a2

其实只是赋值了一个引用,由于a2和a1是相同数组的别名,因此通过a2所做的修改在a1中也可以看到。

注意:
数组中基本类型值会自动初始化成空值(0或者false),但对非基本类型值则不会自动初始化。

可变参数列表

void f(int... args){
    //代码
}

应该总是在重载方法的一个版本上使用可变参数列表,或者压根就不用它。

9 枚举类型

由于枚举类型的实例是常量,因此按照命名规范它们都用大写字母表示(如果在一个名字中有多个单词,用下划线隔开)。

public enum Season{
    SPRING,SUMMER,AUTUMN,WINTER
}

Season spring=Season.SPRING;

enum的values()用来按照enum常量的声明顺序,产生由这些常量值构造成的数组。
enum的ordinal()方法用来表示某个特定enum常量的声明顺序。
由于switch的选择因子必须是char或者int这样的整型值,所以可以配合enum使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值