Day15-49.Member initialization

成员初始化


Java尽力保证:所有变量在使用前都能得到恰当的初始化。

对于方法的局部变量,Java以编译时错误的形式来贯彻这种保证。所以写成:

void f(){
	int i;
	i++;//Error - -i not initialized
}


就会得到一条出错消息,告诉你i可能尚未初始化。

当然,编译器也可以为i赋一个默认值,但是未初始化的局部变量更有可能使程序员的疏忽。

所以采用默认值反而会掩盖这种失误。

因此强制程序员提供一个初始值,往往能够帮助找出程序里的缺陷。

要是类的数据成员(即字段)是基本类型,情况就会变得有些不同。

正如在”一切都是对象“一章中所看到的,类的每个基本类型数据成员保证都会有一个初始值。

下面的程序可以验证这类情况,并显示它们的值:

//: initialization/InitialValues.java
// Shows default initial values.
import static net.mindview.util.Print.*;

public class InitialValues {
  boolean t;
  char c;
  byte b;
  short s;
  int i;
  long l;
  float f;
  double d;
  InitialValues reference;
  void printInitialValues() {
    print("Data type      Initial value");
    print("boolean        " + t);
    print("char           [" + c + "]");
    print("byte           " + b);
    print("short          " + s);
    print("int            " + i);
    print("long           " + l);
    print("float          " + f);
    print("double         " + d);
    print("reference      " + reference);
  }
  public static void main(String[] args) {
    InitialValues iv = new InitialValues();
    iv.printInitialValues();
    /* You could also say:
    new InitialValues().printInitialValues();
    */
  }
} /* Output:
Data type      Initial value
boolean        false
char           [ ]
byte           0
short          0
int            0
long           0
float          0.0
double         0.0
reference      null
*///:~



可见尽管数据成员的初值没有给出,但它们确实有初值(char值为0,所以显示为空白)。

这样至少不会冒”为初始化变量“的风险。

在类里定义一个对象引用时,如果不将其初始化,此引用就会获得一个特殊值null。


Specifying initialization 

指定初始化


如果想为某个变量赋初值,该怎么做呢?

有一种很直接的办法,就是在定义类成员变量的地方为其赋值(注意在C++中不能这样做,尽管C++的新手们总想这么做)。

以下代码片段修改了InitialValues类成员变量的定义,直接提供了初值:

//: initialization/InitialValues2.java
// Providing explicit initial values.

public class InitialValues2 {
  boolean bool = true;
  char ch = 'x';
  byte b = 47;
  short s = 0xff;
  int i = 999;
  long lng = 1;
  float f = 3.14f;
  double d = 3.14159;
} ///:~



也可以用同样的方法初始化非基本类型的对象。

如果Depth是一个类,那么可以像下面这样创建一个对象并初始化它”

//: initialization/Measurement.java
class Depth {}

public class Measurement {
  Depth d = new Depth();
  // ...
} ///:~


如果没有为d指定初始值就尝试使用它,就会出现运行时错误,告诉你产生了一个异常。。

甚至可以通过调用某个方法来提供初值:

//: initialization/MethodInit.java
public class MethodInit {
  int i = f();
  int f() { return 11; }
} ///:~

这个方法也可以带有参数,但这些参数必须是已经被初始化了的。因此,可以这样写:


//: initialization/MethodInit2.java
public class MethodInit2 {
  int i = f();
  int j = g(i);
  int f() { return 11; }
  int g(int n) { return n * 10; }
} ///:~


但像下面这样写就不对了“

//: initialization/MethodInit3.java
public class MethodInit3 {
  //! int j = g(i); // Illegal forward reference
  int i = f();
  int f() { return 11; }
  int g(int n) { return n * 10; }
} ///:~


显然,上述程序的正确性取决于初始化的顺序,而与其编译方式无关。

所以,编译器恰当地对”向前引用“发出警告

这种初始化方法既简单又直观。

但有个限制:类initialValues的每个对象都会具有相同的初值。

有时,这正是所希望的,但有时却需要更大的灵活性。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值