Java 对象之句柄

2018-02-27 11:50:26来源:oschina作者:晨猫人点击

分享

虽然在Java中一切皆对象,但实际上我们不直接操纵对象,而是用句柄来操纵对象。


句柄和对象的关系就像电视机和遥控器的关系,我们通过遥控器来操纵电视机,但它们两个是可以脱离对方独立存在的。其外,我们平时是拿着遥控器到处走动而不是电视机。


//创建句柄
String s;
//创建对象并和句柄链接
s = new String("abcd");

既然对象和句柄是可以独立存在的,那么就有作用域问题了:


Java中主类型的作用域的有效范围和C++一样,除了下面这种情况:


int x = 10;
{
int x = 0;
}

C++中此语法合法,即C++可以将一个变量隐藏在一个更大的作用域中;而Java中会认为重复定义报错。


但对象的作用域和主类型不同:Java中用new创建对象,它会超出作用域的范围。例如:


{
String s = new String("a string");
}

句柄s会在括号外消失,但s指向的对象不会消失(两者是相互独立的)。这种情况若在C++中,不主动释放对象空间的话可能发生内存溢出,但Java有“垃圾收集器”,会在某个时间自动回收对象空间。


创建对象数组时,实际上是创建的句柄数组,每个句柄会初始化为一个特殊值并有自己的关键字null, 试图使用为null的句柄,则会报错。


类由数据成员(字段)和成员函数(方法)组成。


若某个主数据类型属于一个类成员,那么即使不明确(显式)进行初始化,也可以保证它们获得一个默认 值。



但这种保证不适用于变量不属于类成员的情况。若变量并非一个类的字段,如在一个方法中定义一个没有初始化的变量,它会随机获得一个值而非默认值,在一些编译器中会将这种情况报错(如eclipse)。



Java方法中参数传递是值传递,这意味着数组是传递的数组的引用,对象是传递的对象的句柄。如当把对象赋值给另一个对象或作为方法的参数传递时,都会产生别名现象,和数组一样。


static(静态)关键字:一旦将什么东西设为static,数据或方法就不会同那个类的任何对象实例联系到一 起。我们可以通过实例出来的对象访问该静态数据或方法,更重要的是也可以直接通过类名访问。对方法来说,static 一项重要的用途就是帮助我们在不必创建对象的前提下调用那个方法,这一点是至关重要的——特别是在定义程序运行入口方法 main()的时候。


几乎所有运算符都只能操作基本数据类型(主类型)。唯一的例外是“=”、“==”和“!=”,它们能操作所有对象。除此以外,String 类支持“+”和“+=”。


注意:“==”和“!=”比较对象时是比较对象的句柄,如下:


Integer l1 = new Integer(11);
Integer l2 = new Integer(11);
System.out.println(l1 == l2);
System.out.println(l1 != l2);

虽然两个对象的值完全相同,但因为是比较句柄,所以实际上输出的结果先false, 后true. 如果真的想比较对象是否相同,应该用equals()方法。System.out.println(l1.equals(l2));


但如果你创建了新类,必须重写equals()方法,因为equals()方法默认是比较句柄。大多数Java类库都实现了equals()方法用来比较对象的内容,如上述代码中的Integer类。

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台