《Java编程思想》学习笔记(三)——初始化与清理

时间:2023-02-26 18:45:34
一、初始化
      初始化其实就是为变量分配内存空间,并确定其初始值的过程。想了解Java中初始化的各种情况,首先要了解Java中变量的类型。根据自己的理解,将Java中的变量类型分成以下几种,虽然可能不太准确,但只是为了方便理解把握:
      (1)局部变量:内存空间被分配在堆栈上;一般是在方法中定义的变量;其初始化操作是必须的,否则编译器会报错,初始化操作有两种方式:一种是在定义的时候初始化其值,另一种是定义和初始化值分开,如下面所示:
   
   
   
int a = 6 ;
// 或者
int a;
a
= 6 ;
      (2)静态成员变量(static变量或者类变量):内存空间被分配在堆上,而且只占一份存储区域,即多个实例共享一个static变量;局部变量不能被声明为静态变量;它的初始化操作是可选的,如果不人为对其进行初始化,它将会被自动初始化,人为初始化操作是在定义时对其进行赋值;其初始化过程只在类第一次实例化或者第一次调用静态方法的时候完成的。
      (3)非静态成员变量(普通成员变量):内存空间被分配在堆上;初始化操作也是可选的,如果不人为初始化则会被自动初始化,初始化操作是在定义时对其赋值。
      (4)引用变量(对象变量):即类的实例;是通过new的方式在堆上分配内存空间的;与C++不同,Java中不允许有局部对象变量;在被new完后,类的构造器被调用,从而完成初始化过程;如果在定义类时没有定义构造器,则默认构造器会在初始化过程中被调用,构造器还可以被重载,通过参数列表的不同来区分不同的构造器。
      Java中,类在实例化后,其初始化的顺序通过下面的例子来直观说明:
   
   
   
package com.exercise;

import java.awt.peer.SystemTrayPeer;

class A {
public A( int i) {
System.out.println(
" A " + i + " was created! " );
}
}

class B {
public B( int i) {
System.out.println(
" Static B " + i + " was created! " );
}
}

class BaseClass {
A a
= new A( 1 );
static {
System.out.println(
" BaseClass's first static block was execute! " );
}
static B b = new B( 2 );
static {
System.out.println(
" BaseClass's second static block was execute! " );
}
public BaseClass() {
System.out.println(
" BaseClass's constructor was called! " );
}
A aa
= new A( 3 );
static B bb = new B( 4 );
}

class ChildClass extends BaseClass {
A aaa
= new A( 5 );
static {
System.out.println(
" ChildClass's first static block was execute! " );
}
static B bbb = new B( 6 );
static {
System.out.println(
" ChildClass's second static block was execute! " );
}
public ChildClass() {
System.out.println(
" ChildClass's constructor was called! " );
}
A aaaa
= new A( 7 );
static B bbbb = new B( 8 );
}

public class Test {

/**
*
@param args
*/
public static void main(String[] args) {
System.out.println(
" Enter the main function! " );
ChildClass childClass
= new ChildClass();
System.out.println(
" Leave the main function! " );
}

}
运行结果如下:
   
   
   
Enter the main function !
BaseClass
' s first static block was execute!
Static B2 was created !
BaseClass
' s second static block was execute!
Static B4 was created !
ChildClass
' s first static block was execute!
Static B6 was created !
ChildClass
' s second static block was execute!
Static B8 was created !
A1 was created
!
A3 was created
!
BaseClass
' s constructor was called!
A5 was created !
A7 was created
!
ChildClass
' s constructor was called!
Leave the main function !
      根据运行结果可以看出,初始化顺序是
      1、父类静态成员变量和静态初始化块,按在代码中出现的先后顺序
      2、子类静态成员变量和静态初始化块,按在代码中出现的先后顺序
      3、父类非静态成员变量,按在代码中出现的先后顺序
      4、父类构造器
      5、子类非静态成员变量,按在代码中出现的先后顺序
      6、子类构造器
二、清理
      Java中提供了垃圾回收器用于自动回收在程序中通过new创建的内存空间,垃圾回收不能保证不用的内存空间立刻就能得到释放,如果程序对性能要求较高的话,可能要自己创建清理函数,然后在需要的时候调用。
      除了通过new方式分配内存空间,有时候可能调用了“本地方法”分配了内存空间(如调用C语言中的malloc()),针对类似的情况,Java中提供了finalize()方法来处理这类情况的内存回收,一般finalize()有用武之地的情况是,用于验证对象终结条件,从而发现潜在的缺陷。例如如下代码(摘自《Java编程思想》):
   
   
   
class Book {
boolean checkedOut = false ;
Book(
boolean checkOut) {
checkedOut
= checkOut;
}

void checkIn() {
checkedOut
= false ;
}

protected void finalize() {
if (checkedOut)
System.ouy.println(
" Error:checked out " );
// Normally,you'll also do this:
// super.finalize(); // Call the base-class version
}
}


public class TerminatoinCondition {
public static void main(String[]args) {
Book novel
= new Book( true );
// Proper cleanup:
novel.checkIn();
// Drop the reference,forget to clean up:
new Bool( true );
// Force garbage collection & finalization:
System.gc();
}
}