java编程思想学习笔记(第五章:初始化与清理)

来源:互联网 发布:golang 协程数量控制 编辑:程序博客网 时间:2024/06/15 20:17

1,用构造器确保初始化

          构造器有利于减少错误,并使代码更易阅读。从概念上讲,“初始化”与“创建”是彼此独立的。在java中“初始化”和“创建”捆绑在一起,两者不能分离。

随堂练习1

        创建一个类,它包含一个未初始化的String引用。验证该应用被java初始化成null。

class TestInitial{String s;}class Main{public static void main(Stirng[] args){System.out.println(TestInitial.s);}}

随堂练习2

        创建一个类,包含定义时就初始化的String域,以及另一个通过构造方法初始化的String域。这两个方式有何差异?

class TestInitial{String s="nihaoma";String s1;  TestInitial(Stirng s1){   this.s1=s1;}}class Main{public static void main(Stirng[] args){TestInitial testInitial=new TestInitial("have a test");System.out.println(testInitial.s);System.out.println(testInitial.s1);}}

2,方法重载

        在java和c++中构造器是强制重载方法名的另一个原因。为了让方法名形同而形式参数不同的构造器同时存在,必须用到方法重载。


2.1区分重载方法

        每个重载方法都必须有独一无二的参数类型列表。

2.2涉及基本类型的重载


           基本类型能从一个小的类型自动提升为一个较大的类型,此过程一旦牵涉到重载,可能会造成一些混淆。如果传入的数据类型(实际参数类型)小于方法中声明的形式参数类型,实际数据类型就会被提升。

         如果传入的实际参数较大,就得通过类型转换来执行窄化转换。如果不这样做,编译器会报错

2.3以返回值区分重载方法

    

void f(){}int f(){}//如果这样调用f(),java无法判断该调用哪一个,所以用返回值作为重载方法的区分是行不通的。 

3,默认构造器

        默认构造器(又名“无参”构造器)是没有形式参数的---它的作用是创建一个“默认对象”。但是如果你已经定义了一个构造器(无论是否有参数),编译器就不会帮你自动创建默认构造器。

4,this关键字

        this关键字只能在方法内部使用,表示对“调用方法的那个对象”的引用。this的用法和其他对象引用并无不同。但要注意,如果在方法内部调用同一个类的另一个方法,就不必用this,直接调用即可。

4.1,在构造器中调用构造器


        可能一个类有多个构造器,有时想在一个构造器中调用另一个构造器,以避免重复代码。this关键字可以做到这一点。尽管可以用this调用一个构造器,但却在一个不能在构造器中同时调用两个。除构造器之外,编译器禁止在其他任何方法中调用构造器。

4.2,static的含义


      static方法就是没有this的方法。在static方法内部不能调用非静态方法,反过来倒是可以。

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


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

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

      2,垃圾回收并不等于“析构

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

5.1,finalize()用途何在?


5.2,你必须实施清理


       记住:无论是垃圾回收还是终结,都不保证一定会发生。如果java虚拟机并未面临内存耗尽的情形,它是不会浪费时间去执行垃圾回收以及恢复内存的。

5.3,终结条件


5.4,垃圾回收如何工作


6,成员初始化

6.1,指定初始化

在定义类成员变量的位置对其进行赋值。

7,构造器初始化


7.1,初始化顺序

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

//: initialization/OrderOfInitialization.java// Demonstrates initialization order.import static net.mindview.util.Print.*;// When the constructor is called to create a// Window object, you'll see a message:class Window {  Window(int marker) { print("Window(" + marker + ")"); }}class House {  Window w1 = new Window(1); // Before constructor  House() {    // Show that we're in the constructor:    print("House()");    w3 = new Window(33); // Reinitialize w3  }  Window w2 = new Window(2); // After constructor  void f() { print("f()"); }  Window w3 = new Window(3); // At end}public class OrderOfInitialization {  public static void main(String[] args) {    House h = new House();    h.f(); // Shows that construction is done  }} /* Output:Window(1)Window(2)Window(3)House()Window(33)f()*///:~

7.2,静态数据初始化

        无论创建多少个对象,静态数据都只占用一份存储区域。static关键字不能应用于局部变量,因此它只能作用于域。如果一个域是静态的基本类型域,且也没有对它进行初始化,那么它就会获得基本类型的标准初值。如果它是一个对象引用,它的默认初始化值就是null。

//: initialization/StaticInitialization.java// Specifying initial values in a class definition.import static net.mindview.util.Print.*;class Bowl {  Bowl(int marker) {    print("Bowl(" + marker + ")");  }  void f1(int marker) {    print("f1(" + marker + ")");  }}class Table {  static Bowl bowl1 = new Bowl(1);  Table() {    print("Table()");    bowl2.f1(1);  }  void f2(int marker) {    print("f2(" + marker + ")");  }  static Bowl bowl2 = new Bowl(2);}class Cupboard {  Bowl bowl3 = new Bowl(3);  static Bowl bowl4 = new Bowl(4);  Cupboard() {    print("Cupboard()");    bowl4.f1(2);  }  void f3(int marker) {    print("f3(" + marker + ")");  }  static Bowl bowl5 = new Bowl(5);}public class StaticInitialization {  public static void main(String[] args) {    print("Creating new Cupboard() in main");    new Cupboard();    print("Creating new Cupboard() in main");    new Cupboard();    table.f2(1);    cupboard.f3(1);  }  static Table table = new Table();  static Cupboard cupboard = new Cupboard();} /* Output:Bowl(1)Bowl(2)Table()f1(1)Bowl(4)Bowl(5)Bowl(3)Cupboard()f1(2)Creating new Cupboard() in mainBowl(3)Cupboard()f1(2)Creating new Cupboard() in mainBowl(3)Cupboard()f1(2)f2(1)f3(1)*///:~

        由输出可见,静态初始化只有在必要时刻才会进行。如果不创建table对象,也不引用Table.b1或Table.b2,那么静态的Bowl b1和b2永远不会创建。只有在第一个Table对象被创建或者第一次访问静态数据时,它们才会被初始化。以后静态对象不会再被初始化。初始化顺序是先静态对象再非静态对象。

7.3,显示的静态初始化


  静态代码块只执行一次。

//: initialization/ExplicitStatic.java// Explicit static initialization with the "static" clause.import static net.mindview.util.Print.*;class Cup {  Cup(int marker) {    print("Cup(" + marker + ")");  }  void f(int marker) {    print("f(" + marker + ")");  }}class Cups {  static Cup cup1;  static Cup cup2;  static {    cup1 = new Cup(1);    cup2 = new Cup(2);  }  Cups() {    print("Cups()");  }}public class ExplicitStatic {  public static void main(String[] args) {    print("Inside main()");    Cups.cup1.f(99);  // (1)  }  // static Cups cups1 = new Cups();  // (2)  // static Cups cups2 = new Cups();  // (2)} /* Output:Inside main()Cup(1)Cup(2)f(99)*///:~

7.4非静态实例初始化

          java中也有被称为实例初始化的类似语法,用来初始化每一个对象的非静态变量。

//: initialization/Mugs.java// Java "Instance Initialization."import static net.mindview.util.Print.*;class Mug {  Mug(int marker) {    print("Mug(" + marker + ")");  }  void f(int marker) {    print("f(" + marker + ")");  }}public class Mugs {  Mug mug1;  Mug mug2;  {    mug1 = new Mug(1);    mug2 = new Mug(2);    print("mug1 & mug2 initialized");  }  Mugs() {    print("Mugs()");  }  Mugs(int i) {    print("Mugs(int)");  }  public static void main(String[] args) {    print("Inside main()");    new Mugs();    print("new Mugs() completed");    new Mugs(1);    print("new Mugs(1) completed");  }} /* Output:Inside main()Mug(1)Mug(2)mug1 & mug2 initializedMugs()new Mugs() completedMug(1)Mug(2)mug1 & mug2 initializedMugs(int)new Mugs(1) completed*///:~

练习15:编写一个含有字符串域的类,并采用实例初始化方式进行初始化。

class Main {      String s ;      {          s = "young for you";      }      public Main(){          System.out.println("s="+s);      }      public static void main (String args[]){          new Main();      }  }/*Output: s=young for you */

8,数组初始化

        数组只是相同的类型,用一个标识符名称封装到一起的一个对象序列或基本类型数据序列,数组是通过方括号下标符[ ]来定义和使用的。定义一个数组,只需要在类型名后加上一个空方括号就可以了,方括号也可以置于标识符后面

int[] a;int a[];
        编译器不允许指定数组大小。现在拥有的只是对数组的一个引用,并没有为数组分配内存空间

        数组初始化的三种方式:

a) String [] a=new String[length];b) String [] a=new String[] {,,,....};c) String [] a={,,,,,,......}; 
        三种定义的原理和效果基本一致。

        在java中可以将一个数组赋值给另一个数组,其实真正做的只是复制了一个引用。

        如果在编写程序时,并不能确定在数组里有多少个元素。可以直接用new在数组里创建元素。尽管创建的是基本数据类型,new任然可以工作(不能用new创建单个的基本类型数据)。

8.1,可变参数列表

       有了可变参数,就再也不用显式的编写数组语法了,当你指定参数时,编译器实际上会为你去填充数组。

9,枚举类型


       











阅读全文
0 0
原创粉丝点击