Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1966924
  • 博文数量: 606
  • 博客积分: 9991
  • 博客等级: 中将
  • 技术积分: 5725
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-17 19:07
文章分类

全部博文(606)

文章存档

2011年(10)

2010年(67)

2009年(155)

2008年(386)

分类:

2008-09-11 10:36:57

第四章 初始化于清理

 

方法重载

 

   涉及基本类型的重载

 

   如果插入的数据类型(实际参数类型)“小于方法中声明的形式参数类型,实际数据类型就会被提升。例如如果传入的类型是int,但是方法的参数类型是double,那么,插入的参数就是被提升doublechar行略有不同,如果无法找到瞧好接受char存书的方法,就会把char直接提升int型。

 

   如果传入的实际参数较大,就得载圆括号里写上类型名称,作必要的类型转换。例如传入的类型为float,而方法的参数类型为int,那么必须进行类型转换,(int)float如果不这样作,编译器就会报错。

 

  以返回值区分重载方法

   void f(){}

   int f(){}

 

   如果有一行程序为 f();此时Java不能理解调用的是哪一个f(),所以根据方法的返回值来区分重载方法是行不通的。

 

 

static方法没有this的方法。

 

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

  1)对象可能不被垃圾回收

  2)垃圾回收并不等于析构

  3)垃圾回收只与内存有关

 

   假定你的对象(并非使用new)获得了一块特殊的内存区域,由于垃圾回收器只知道释放那些由new分配的内存,所以它不知道该如何释放该对象的这块特殊内存。为了应对这种情况,Java允许载类中定义一个名为finalize()方法。它的工作原理假定是这样的:一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用其finalize()方法,并且载下一次垃圾回收动作发生时,才会真正回收对象占用的内存。

 

   之所以要有finalize(),是由于载分配内存时,可能采用了类似C语言的做法,而非Java的通常做法。在非Java代码中,也许会调用Cmalloc()函数系列来分配存储空间,而且除非电泳了free(),负责存储空间将得不到释放,从而造成内存泄漏。所以需要杂ifinalize()本地方法调用它。

  System.gc()用于强制进行终结动作(在写程序的时候这么作可以加速调试过程)。

 

垃圾回收器如何工作

 

   C++像一个院子,里面每个对象都负责管理自己的地盘。一段时间以后,对象可能被销毁,但地盘必须加以重用。

 

   Java虚拟机中,堆的实现截然不同,它更像一个传送带,每分配一个新对象,它就往前移动一格。这移位着对象存储空间的分配数度非常快。Java堆指针知识简单地移动到尚未分配的区域,其效率比得上C++堆栈分配空间的效率。事实上Java的堆未必完全像传送带那样工作。要真是那样的话,势必会导致频繁的内存页面调度(这极大地影响性能),并最终耗尽资源。其中的秘密在于垃圾回收器的介入。当它工作时,将一面回收空间,一面是堆这的对象紧凑排列,这样堆指针就可以很容易移动到更靠近传送带的开始处,也就尽量避免了页面错误。通过垃圾回收器对对象重新排列,实现了一种告诉的、有无限空间可供分配的堆模型。

 

成员初始化

  指定初始化(在C++不能这样做)

   class InitialValues{

     boolean b = true;

     char c = 'x';

     ......

   }

 

 构造器初始化

 

    1.初始化顺序

 

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


import com.bruceeckel.simpletest.*;

// When the constructor is called to create a

// Tag object, you'll see a message:

class Tag {
  Tag(int marker) {
    System.out.println("Tag(" + marker + ")");
  }
}

class Card {


  Tag t1 = new Tag(1);
// Before constructor

  Card() {
    
// Indicate we're in the constructor:
    System.out.println("Card()");
    t3 = new Tag(33);
// Reinitialize t3

  }


  Tag t2 = new Tag(2);
// After constructor

  void f() {
    System.out.println("f()");
  }


  Tag t3 = new Tag(3);
// At end

}

public class OrderOfInitialization {
  static Test monitor = new Test();
  public static void main(String[] args) {
    Card t = new Card();
    t.f();
// Shows that construction is done

    monitor.expect(new String[] {
      "Tag(1)",
      "Tag(2)",
      "Tag(3)",
      "Card()",
      "Tag(33)",
      "f()"
    });
  }
}
///:~

 

  

  2.静态数据的初始化

 

   静态初始化只有在必要时刻才会进行。如果不创建Table对象,也不引用Table.b1Table.b2,那么静态的Bow1 b1b2永远不会被创建。只有在第一个Table对象被创建(或者第一次访问静态数据)的时候,他们才会被初始化。此后,静态对象不会再次被初始化。

 

   初始化的顺序是先静态对象(如果他们尚未因前面的对象创建过程而被初始化),而后是非静态对象。

 

import com.bruceeckel.simpletest.*;

class Bowl {
  Bowl(int marker) {
    System.out.println("Bowl(" + marker + ")");
  }
  void f(int marker) {
    System.out.println("f(" + marker + ")");
  }
}

class Table {
  static Bowl b1 = new Bowl(1);
  Table() {
    System.out.println("Table()");
    b2.f(1);
  }
  void f2(int marker) {
    System.out.println("f2(" + marker + ")");
  }
  static Bowl b2 = new Bowl(2);
}

class Cupboard {
  Bowl b3 = new Bowl(3);
  static Bowl b4 = new Bowl(4);
  Cupboard() {
    System.out.println("Cupboard()");
    b4.f(2);
  }
  void f3(int marker) {
    System.out.println("f3(" + marker + ")");
  }
  static Bowl b5 = new Bowl(5);
}

public class StaticInitialization {
  static Test monitor = new Test();
  public static void main(String[] args) {
    System.out.println(
      "Creating new Cupboard() in main");
    new Cupboard();
    System.out.println(
      "Creating new Cupboard() in main");
    new Cupboard();
    t2.f2(1);
    t3.f3(1);
    monitor.expect(new String[] {
      "Bowl(1)",
      "Bowl(2)",
      "Table()",
      "f(1)",
      "Bowl(4)",
      "Bowl(5)",
      "Bowl(3)",
      "Cupboard()",
      "f(2)",
      "Creating new Cupboard() in main",
      "Bowl(3)",
      "Cupboard()",
      "f(2)",
      "Creating new Cupboard() in main",
      "Bowl(3)",
      "Cupboard()",
      "f(2)",
      "f2(1)",
      "f3(1)"
    });
  }
  static Table t2 = new Table();
  static Cupboard t3 = new Cupboard();
}
///:~ 



  3.静态句子

    与其他静态初始化动作一样,代码仅执行一次:但首次生成这个类的一个对象时,或者首次访问属于那个类的静态数据成员时(即便从未生成过那个类的对象)。例如:

 

import com.bruceeckel.simpletest.*;

class Cup {
  Cup(int marker) {
    System.out.println("Cup(" + marker + ")");
  }
  void f(int marker) {
    System.out.println("f(" + marker + ")");
  }
}

class Cups {
  static Cup c1;
  static Cup c2;
  static {
    c1 = new Cup(1);
    c2 = new Cup(2);
  }
  Cups() {
    System.out.println("Cups()"); //没有运行此句,因为没有new创建对象,只是访问成员里的数据成员


  }
}

public class ExplicitStatic {
  static Test monitor = new Test();
  public static void main(String[] args) {
    System.out.println("Inside main()");
    Cups.c1.f(99); // (1)


    monitor.expect(new String[] {
      "Inside main()",
      "Cup(1)",
      "Cup(2)",
      "f(99)"
    });
  }
  // static Cups x = new Cups(); // (2)


  // static Cups y = new Cups(); // (2)


} ///:~


 

  数组初始化

 

  Java的数组有一个length成员,表示数组的长度。

 

  Java数组有下标越界控制

 
 
阅读(496) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~