第四章读后感

来源:互联网 发布:心内事无人知的图片 编辑:程序博客网 时间:2024/05/23 19:14

Java中,“初始化”和“创建”被捆绑在一起,两者不能分离。

 

构造器是一种特殊类型的方法,因为它没有返回值,不会返回任何东西。New表达式确实返回了对新建对象的引用,但构造器本身并没有任何返回值。

 

类可以有两个以上的构造器,一个不带形式参数,另外的带有参数。

 

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

涉及基本类型的重载

基本类型能从一个“较小”的类型自动提升至一个“较大”的类型。如:

public class PrimitiveOverloading {

  void f1(char x) { System.out.println("f1(char)"); }

  void f1(byte x) { System.out.println("f1(byte)"); }

  void f1(short x) { System.out.println("f1(short)"); }

  void f1(int x) { System.out.println("f1(int)"); }

  void f1(long x) { System.out.println("f1(long)"); }

  void f1(float x) { System.out.println("f1(float)"); }

  void f1(double x) { System.out.println("f1(double)"); }

 

  void f2(byte x) { System.out.println("f2(byte)"); }

  void f2(short x) { System.out.println("f2(short)"); }

  void f2(int x) { System.out.println("f2(int)"); }

  void f2(long x) { System.out.println("f2(long)"); }

  void f2(float x) { System.out.println("f2(float)"); }

  void f2(double x) { System.out.println("f2(double)"); }

 

  void f3(short x) { System.out.println("f3(short)"); }

  void f3(int x) { System.out.println("f3(int)"); }

  void f3(long x) { System.out.println("f3(long)"); }

  void f3(float x) { System.out.println("f3(float)"); }

  void f3(double x) { System.out.println("f3(double)"); }

 

  void f4(int x) { System.out.println("f4(int)"); }

  void f4(long x) { System.out.println("f4(long)"); }

  void f4(float x) { System.out.println("f4(float)"); }

  void f4(double x) { System.out.println("f4(double)"); }

 

  void f5(long x) { System.out.println("f5(long)"); }

  void f5(float x) { System.out.println("f5(float)"); }

  void f5(double x) { System.out.println("f5(double)"); }

 

  void f6(float x) { System.out.println("f6(float)"); }

  void f6(double x) { System.out.println("f6(double)"); }

 

  void f7(double x) { System.out.println("f7(double)"); }

 

  void testConstVal() {

    System.out.println("Testing with 5");

    f1(5);f2(5);f3(5);f4(5);f5(5);f6(5);f7(5);

  }

  void testChar() {

    char x = 'x';

    System.out.println("char argument:");

    f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);

  }

  void testByte() {

    byte x = 0;

    System.out.println("byte argument:");

    f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);

  }

  void testShort() {

    short x = 0;

    System.out.println("short argument:");

    f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);

  }

  void testInt() {

    int x = 0;

    System.out.println("int argument:");

    f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);

  }

  void testLong() {

    long x = 0;

    System.out.println("long argument:");

    f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);

  }

  void testFloat() {

    float x = 0;

    System.out.println("float argument:");

    f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);

  }

  void testDouble() {

    double x = 0;

    System.out.println("double argument:");

    f1(x);f2(x);f3(x);f4(x);f5(x);f6(x);f7(x);

  }

  public static void main(String[] args) {

    PrimitiveOverloading p =

      new PrimitiveOverloading();

    p.testConstVal();

    p.testChar();

    p.testByte();

    p.testShort();

    p.testInt();

    p.testLong();

    p.testFloat();

    p.testDouble();

    }

} ///:~

输出结果

Testing with 5

f1(int)

f2(int)

f3(int)

f4(int)

f5(long)

f6(float)

f7(double)

char argument:

f1(char)

f2(int)

f3(int)

f4(int)

f5(long)

f6(float)

f7(double)

byte argument:

f1(byte)

f2(byte)

f3(short)

f4(int)

f5(long)

f6(float)

f7(double)

short argument:

f1(short)

f2(short)

f3(short)

f4(int)

f5(long)

f6(float)

f7(double)

int argument:

f1(int)

f2(int)

f3(int)

f4(int)

f5(long)

f6(float)

f7(double)

long argument:

f1(long)

f2(long)

f3(long)

f4(long)

f5(long)

f6(float)

f7(double)

float argument:

f1(float)

f2(float)

f3(float)

f4(float)

f5(float)

f6(float)

f7(double)

double argument:

f1(double)

f2(double)

f3(double)

f4(double)

f5(double)

f6(double)

f7(double)

Press any key to continue...

如果传入的数据类型小于方法中声明的形式参数类型,实际数据类型就会被提升Char类型略有不同,会被提升至int类型。

如果传入的实际参数类型大于重载方法声明的形式参数,就得在括号里面写上类型名称,做必要的类型转换,如下:

public class Demotion {

  static Test monitor = new Test();

  void f1(char x) { System.out.println("f1(char)"); }

  void f1(byte x) { System.out.println("f1(byte)"); }

  void f1(short x) { System.out.println("f1(short)"); }

  void f1(int x) { System.out.println("f1(int)"); }

  void f1(long x) { System.out.println("f1(long)"); }

  void f1(float x) { System.out.println("f1(float)"); }

  void f1(double x) { System.out.println("f1(double)"); }

 

  void f2(char x) { System.out.println("f2(char)"); }

  void f2(byte x) { System.out.println("f2(byte)"); }

  void f2(short x) { System.out.println("f2(short)"); }

  void f2(int x) { System.out.println("f2(int)"); }

  void f2(long x) { System.out.println("f2(long)"); }

  void f2(float x) { System.out.println("f2(float)"); }

 

  void f3(char x) { System.out.println("f3(char)"); }

  void f3(byte x) { System.out.println("f3(byte)"); }

  void f3(short x) { System.out.println("f3(short)"); }

  void f3(int x) { System.out.println("f3(int)"); }

  void f3(long x) { System.out.println("f3(long)"); }

 

  void f4(char x) { System.out.println("f4(char)"); }

  void f4(byte x) { System.out.println("f4(byte)"); }

  void f4(short x) { System.out.println("f4(short)"); }

  void f4(int x) { System.out.println("f4(int)"); }

 

  void f5(char x) { System.out.println("f5(char)"); }

  void f5(byte x) { System.out.println("f5(byte)"); }

  void f5(short x) { System.out.println("f5(short)"); }

 

  void f6(char x) { System.out.println("f6(char)"); }

  void f6(byte x) { System.out.println("f6(byte)"); }

 

  void f7(char x) { System.out.println("f7(char)"); }

 

  void testDouble() {

    double x = 0;

    System.out.println("double argument:");

    f1(x);f2((float)x);f3((long)x);f4((int)x);

    f5((short)x);f6((byte)x);f7((char)x);

  }

  public static void main(String[] args) {

    Demotion p = new Demotion();

    p.testDouble();

    monitor.expect(new String[] {

      "double argument:",

      "f1(double)",

      "f2(float)",

      "f3(long)",

      "f4(int)",

      "f5(short)",

      "f6(byte)",

      "f7(char)"

    });

  }

}

 

 

如果没有定义构造器,编译器回帮你自动创建一个缺省构造器。但是,如果已经定义了一个构造器(无论有无参数),编译器就不会帮你自动创建缺省构造器,如:

class Hat{

        Hat (int i){}

        Hat(double d){}

}

现在,如果你这样写:   new Hat();         就会报错。

 

对象可能不被垃圾回收;垃圾回收并不等于“析构”;垃圾回收只与内存有关。无论垃圾回收还是终结,都不保证一定会发生,如果Java虚拟机并未面临内存耗尽的情形,它是不会浪费时间去执行垃圾回收以恢复内存的。

Finalize()方法会在垃圾回收器清除对象之前被调用,但不要依赖它回收任何短缺资源,因为不确定该方法何时被调用。

之所以要有finalize()方法,是由于在分配内存时可能采用了类似c语言中的做法,这种情况主要发生在使用“本地方法”的情况下。本地方法是在Java中调用非Java代码的方式(目前只支持c/c++)。

 

书中对垃圾回收器如何工作进行了详细的讲解,可以好好看看。

 

类的每个基本类型数据成员保证都会有一个初始值,如果没有指定,会赋给默认值;单对于定义于方法内部的局部变量,必须指定初始值,否则会报错。

对于非基本类型的对象,在初始化之前不能使用,否则会报错。

Class CInit{

Int j = g(i);

Int I = f();}            这样写就不对了,该程序的正确性取决于初始化的顺序。

 

对于所以基本类型和对象引用,包括在定义时已经指定初始值的变量,无法组织自动初始化的进行,它将在构造器被调用之前发生。

 

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

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()"

    });

  }

} ///:~              t3被初始化两次,一次在调用构造器之前,一次在调用期间。

 

对于静态数据的初始化,就有点复杂了:

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();

} ///:~

这里面需要注意的是:

1.       如果不创建Table对象,则Table{……}中的语句不会执行,同理cupboard

2.       初始化的顺序是先“静态”对象,后“非静态” 对象

3.       静态对象的初始化只执行一次:当首次生成这个类的一个对象时,或者首次访问属于那个类的静态数据成员时

 

数组的初始化

 

import com.bruceeckel.simpletest.*;

public class Arrays {

  static Test monitor = new Test();

  public static void main(String[] args) {

    int[] a1 = { 1, 2, 3, 4, 5 };

    int[] a2;

    a2 = a1;           //a2a1指向同一个地址

    for(int i = 0; i < a2.length; i++)

      a2[i]++;              //可以改变数组元素状态

    for(int i = 0; i < a1.length; i++)

      System.out.println(

        "a1[" + i + "] = " + a1[i]);

    monitor.expect(new String[] {

      "a1[0] = 2",

      "a1[1] = 3",

      "a1[2] = 4",

      "a1[3] = 5",

      "a1[4] = 6"

    });

  }} ///:~

原创粉丝点击