《think in java》第四章阅读笔记

第四章 初始化和清除

4.1用构造器自动初始化

1、一旦创建一个对象,就会分配相应的存储空间,并调用构造器。

4.2方法重载

1、方法的参数为基本类型时,只能用小范围的基本类型做参。例如public void test(short i),调用只能用test((short)5),如果用test(5)则会编译报错。如果用public void test(int i),调用则能用test(5),也能用test((short)5)。

public void test(short i){...}

test(1);//程序将编译报错

test((short)1);//程序正常执行


public void test(int i){...}

test(1);//程序将正常执行

test((short)1);//程序将正常执行

2、构造器调用其他构造器,采用this关键字。

public  class Test {

        public Test(int i){}

        public Test(){
            this(5);
        }

}

4.3清除:收尾和垃圾收集

1、java的垃圾回收器可以回收不再使用的对象占据的内存,但是只能回收用new创建的对象。

2、java提供了finalized()方法,一旦垃圾收集器准备释放对象的存储空间时,会首先调用finalized(),并且只有在下一次垃圾收集过程中,才会真正回收对象内存。它可以帮助我们在垃圾收集期间进行一些重要的清除或清扫工作。主要是用来清除c或c++在java中的固有方法。

3、有时对象的存储空间可能永远都不会释放。因为随着程序的结束,资源会返还给操作系统。而且垃圾收集本身也要消耗一些开销,如永远都不用它,那么永远也不用支出这部分开销。

4、垃圾收集只和内存有关,存在的唯一原因是为了回收程序不再使用的内存。

5、对象里面的对象所占内存也会被垃圾收集一并清除。

6、system.gc()建议虚拟机进行垃圾回收。何时执行,是否执行并不确定。

4.4成员初始化

1、对象初始化的过程

  (1)类dog首次创建时,或是类内部的static方法/变量首次访问时,java解释器必须找到dog.class(实现设好的类路径下搜索)。

  (2)找到dog.class后,会创建一个class对象,所有的static初始化模块都会运行。

  (3)创建一个new Dog()时,dog对象的构建进程首先会在内存堆(heap)里为一个dog对象分配足够的内存。

  (4)对dog类中所有基本类型设为他们的默认值。

  (5)字段定义时,所有的初始化都会完成。(例如有个参数 Cat cat = new Cat(),则会初始化cat对象)

  (6)执行构造器。

  简单来说:

  第一次new一个子类的执行顺序:(父类静态代码块父类静态全局变量)(子类静态代码块子类静态全局变量)(父类非静态代码块父类非静态全局变量)→父类构造函数→(子类非静态代码块子类非静态全局变量)→子类构造函数

  第二次及以后N次new一个子类的执行顺序:(父类非静态代码块父类非静态全局变量)→父类构造函数→(子类非静态代码块子类非静态全局变量)→子类构造函数

  即优先级:静态>非静态父类>子类。其余基本按顺序执行。

例子:

class A {
    static {
        System.out.println("this is A static");
    }
    
    public A() {
        System.out.println("this is A construct");
    }
    
    public A(int i) {
        System.out.println("A("+i+")");
    }
}
class Bowl extends A{
    static {
        System.out.println("this is bowl static");
    }
    
    public Bowl() {
        System.out.println("this is bowl construct");
    }
    
    static A a = new A(1);
    A a1 = new A(2);
    
    public Bowl(String i) {
        System.out.println("bowl("+i+")");
    }
}

class Table extends Bowl{
    static {
        System.out.println("this is table static");
    }
    
    static Bowl b1 = new Bowl("0");
    Bowl b = new Bowl("1");
    
    public Table() {
        System.out.println("this is table construct");
    }
}

执行方法

public static void main(String[] args) {
    System.out.println("--------------------------------");
    Table b = new Table();
    System.out.println("---------------------------------");
}

执行结果

--------------------------------
this is A static//main方法中执行到new Table(),首先进入顶级父类A类,查找是否有静态代码块,如果有则执行(这里有,所以执行)。然后查找是否有静态全局变量(这里没有,因此A类静态部分执行完毕)。
this is bowl static//然后进入次级父类Bowl类,执行方式同上,首先执行静态代码块
A(1)//然后执行静态全局变量,同时Bowl类静态部分执行完毕
this is table static//然后进入子类Table类,首先执行静态代码块
this is A construct//这里其实是执行静态全局变量Bowl b = new Bowl("0")。需要注意的是,new Bowl("0")是初始化一个Bowl类,因此首先进入Bowl类的顶级父类,即A类,此时A类和Bowl类里的静态部分已经全部被初始化,因此不再重复执行,并且A类中没有全局变量,所以直接执行A类的构造函数
A(2)//A类构造函数执行后,进入Bowl类,该类中的静态变量也已全部初始化,于是初始化非静态变量
bowl(0)//最后调用Bowl类的构造函数
//至此三个父子类中的静态部分已经全部执行完毕,开始执行非静态部分的行为。以后不论执行多少个new Table(),都只会执行以下部分。
this is A construct//每初始化一个类,都是从上往下初始化。顶级父类A类中没有成员变量,所以直接调用A类的构造函数。
A(2)//次级父类Bowl中存在非静态全局变量,每生成一个对象都会初始化一次。
this is bowl construct//Bowl类中的全局变量初始化完毕,执行构造方法
this is A construct//这里其实是执行Bowl b = new Bolw("1")。即初始化一个新的Bowl类,因此需要从Bowl类的父类A类开始执行。A类中没有未初始化的成员变量,直接调用构造函数。
A(2)//Bowl类中存在非静态成员变量,对其初始化
bowl(1)//最后调用构造函数。
this is table construct//以上部分全部完成,最后调用类的构造函数。
---------------------------------

  第一次new一个子类的执行顺序:父类静态代码块→父类静态全局变量→子类静态代码块→子类静态全局变量→父类非静态代码块→父类非静态全局变量→父类构造函数→子类非静态代码块→子类非静态全局变量→子类构造函数

  第二次及以后N次new一个子类的执行顺序:父类非静态代码块→父类非静态全局变量→父类构造函数→子类非静态代码块→子类非静态全局变量→子类构造函数

  通过main方法执行程序,首先会在入口类(带有main方法的类)中寻找该类中的静态全局变量,然后初始化,由于main方法是静态方法,所以此时非静态全局变量不会被初始化,然后执行main方法。

  注意:静态变量初始化一次后,不会再执行第二次。因此可以用作单例模式的线程安全。

2、静态全局变量只会被初始化一次,会在第一次new一个新的对象,或者是第一次被调用的时候初始化。

推荐一个描写类生命周期的文章http://blog.csdn.net/zhengzhb/article/details/7517213

4.5数组初始化

1、数组的定义方法:int[] a和int a[]。推荐使用前一种。它更能直接的表示这是一个int类型的数组。

2、数组的初始化表达式:int[] a = {1,2,3,4};int[] a = new int[5];int[] a = new int[]{1,2,3,4};

3、创建多维数组至少需要确定第一维的长度。int[][][] i = new int[5][][];此时输出int[2],会打印null.

posted @ 2017-06-13 11:58  一响贪欢  阅读(137)  评论(0)    收藏  举报