第五章:初始化与清理
初始化和清理是涉及程序安全的两个问题。Java构造器用于新建对象时的初始化,而垃圾回收器则进行清理。
构造器的名称必须与类名一样,虽然构造器是一种特殊的方法,但是每个方法首字母小写的编码风格并不适合用于构造器。
构造器是没有返回值的,但是new表达式却返回了对新建对象的引用。
方法重载是构造器所必须的。每个重载方法都必须独一无二的参数列表。甚至参数顺序的不同,也足以区分两个方法。不过一般不建议这么做,因为这会使代码难以维护。当传入的数据类型小于方法中声明的形式参数类型,实际数据类型就会被提升。但是boolean不能转换,char也比较特殊,提升至int。如果反过来,传入大于声明,则必须进行强转,否则报错。(注意,根据返回值的不同来区分方法是不成立的。)
各参数类型大小顺序排列:boolean:1/8;byte:1;char:2(一个字符可以存储一个中文汉字);short:2;int:4;float:4;long:8;double:8。(单位:字节)
this关键字:只能在方法内部使用,表示对"调用方法的那个对象"的引用。只有在需要明确指出对当前对象的引用时,才有必要使用this。如果在方法内部使用同一个类中的另一个方法,就不用使用this。return this表示返回当前引用。
通常写this的时候,都是指"这个对象"或者"那个对象",而且它本身表示对当前对象的引用。在构造器中,如果this添加了参数列表,那么就有了不同的含义。这将产生对符合此参数列表的某个构造器的明确调用。通过下面的代码示例将会理解的更加深刻。
public class Flower { int petalCount = 0; String s = "initial value"; Flower(int petals){ petalCount = petals; System.out.println("Constructor w/ int arg only,petalCount=" + petalCount); } Flower(String ss){ System.out.println("Constructor w/ String arg only,s=" + ss); s = ss; } Flower(String s,int petals){ this(petals);
//this(s)//错误,不能在一个构造器里面调用两次构造器 this.s = s;//因为成员名字和参数S的名称一致,所有采用这种写法加以区分。 System.out.println("String & int args"); } Flower(){ this("hi",47); System.out.println("default constructor(no args)"); } void printPetalCount(){
//this(11);//错误,不能在非构造器方法里通过this调用构造器。 System.out.println("petalCount =" + petalCount + " s=" + s); } public static void main(String[] args){ Flower x = new Flower(); x.printPetalCount(); } }
output:
Constructor w/ int arg only,petalCount=47
String & int args
default constructor(no args)
petalCount =47 s=hi
关于static的补充:
static方法不能包含this,即不能调用非静态方法。反过来倒是可以。而且在没有创建对象的时候,单依靠对象本身就可以对static方法进行调用。这实际上是static的主要作用。这很像全局方法,Java中禁止使用全局方法,但你在类中置入static方法,就可以访问其他的static方法和static域。
有些人认为static方法不是"面向对象"的,因为他们的确具有全局函数的含义,使用static方法时,由于并不是通过this来向对象发送信息。的确,要是代码中存在大量的static,就应该重新考虑自己的设计。然而static的概念有其实用之处,许多时候都要用到它,至于是不是面向对象,不是我们说了算的。
关于终结处理和垃圾回收,将在后面的博文中详细介绍。
Java尽力保证:所有变量在使用前必须得到恰当的初始化。
对于类中基本成员(即字段)是基本类型的,会自动为这些成员初始化。但是方法中的局部变量则不会,必须强制程序员赋予初始值,否则编译报错。
成员初始化的三种情况:
(1)类中基本成员变量:直接在定义的地方为其赋值。(C++中不可以)
(2)非基本类型的对象:
class Depth{}
public class Measurement {
Depth d = new Depth();
}
(3)通过调用某个方法来提供初值,这个方法也可以带有参数,但是这些参数必须是应景被初始化了的:
public calss MethodInit2{
int i = f();
int j = g(i);
int f(){
return 11;
}
int g(int n){
return n * 10;
}
}