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

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 main
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(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 initialized
Mugs()
new Mugs() completed
Mug(1)
Mug(2)
mug1 & mug2 initialized
Mugs(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,枚举类型


       











评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值