java基础教程-对象的传递与返回
对象的传递与返回
现在,我们应该已经相当适应这样的概念了:当你
“
传递
”
对象的时候,实际上是在传递对象的引用。
对许多编程语言而言,只需按
“
正规
”
方式传递对象,就能处理绝大多数情况。然而总有些时候,需要以不太正规的方式处理。于是,事情突然变得复杂起来(在
C++
中,会变得相当复杂),
Java
也不例外。因此,确切理解在传递对象的时候发生了什么,就显得很重要了。
“Java
中是否有指针
”
?有些人认为,指针既难掌握又很危险,所以指针很糟糕。既然
Java
全部都是优点,还能减轻你的编程负担,所以它不可能包含指针。然而,确切地说,
Java
有指针。事实上,
Java
中(除了基本类型)每个对象的标识符就是一个指针。但是它们受到了限制,有编译器和运行期系统监视着它们。或者换个说法,
Java
有指针,但是没有指针的相关算法。我们
称之为
“
引用(
reference
)
”
,你也可以将它们看作
“
安全的指针
”
,就像小学生的安全剪刀,它不尖锐,不故意使劲通常不会伤着人,但是使用起来不但慢而且麻烦。
传引用
将一个引用传入某个方法之后,它仍然指向原来的对象。可以用一个简单的试验证明:
// Passing references around.
public class PassReferences {
public static void main(String[] args) {
PassReferences p = new PassReferences();
System.out.println("p inside main(): " + p);
f(p);
}
public static void f(PassReferences h) {
System.out.println("h inside f(): " + h);
}
}
打印语句自动调用
toString()
方法,而继承自
Object
的
PassReferences
类没有重新定义
toString()
方法。所以使用的是
Object
的
toString()
方法,它打印出类名以及存储对象的地址(不是引用,而是实际的对象)。输出看起来像这样:
p inside main(): PassReferences@ad3ba4
h inside f(): PassReferences@ad3ba4
可以看到,
p
和
h
都指向同一个对象。像这样只是发送一个参数给方法,比复制一个新的
PassReferences
对象效率要高很多。但它也引出了一个重要的话题。
别名效应
“
别名效应
”
是指,多个引用指向同一个对象,参见前例。当某人修改那个对象时,别名带来的问题就会显现出来。例如,如果此对象还有其他的引用指向它,而使用那些引用的人,根本没想到对象会有变化,定然会对此感到十分诧异。
克隆对象
需要使用对象的局部拷贝的最可能的原因是:你必须修改那个对象,但又不希望改动调用者的对象。如果你决定要制做一份局部拷贝,可以使用
clone()
方法。这是定义在
Object
类中的
protected
方法。如果要使用它,必须在子类中以
public
方式重载此方法。例如,标准类库中的
ArrayList
类就重载了
clone()
,所以我们才能由
ArrayList
调用
clone()
方法:
// The clone() operation works for only a few
// items in the standard Java library.
import java.util.*;
class Int {
private int i;
public Int(int ii) {
i = ii;
}
public void increment() {
i++;
}
public String toString() {
return Integer.toString(i);
}
}
public class Cloning {
public static void main(String[] args) {
ArrayList v = new ArrayList();
for (int i = 0; i < 10; i++) {
v.add(new Int(i));
}
System.out.println("v: " + v);
ArrayList v2 = (ArrayList) v.clone();
for (Iterator e = v2.iterator(); e.hasNext();) {
((Int) e.next()).increment();
}
System.out.println("v: " + v);
}
}
clone()
方法只能生成
Object
,之后必须将其转型为合适的类型。此例演示了
ArrayList
的
clone()
方法,它并不自动克隆
ArrayList中包含的每个对象。克隆的ArrayList只是将原ArrayList中的对象别名化。这通常称为浅层拷贝(shallow copy
),因为它只复制对象
“
表面
”
的部分。实际的对象由以下几部分组成:对象的
“
表面
”
,由对象包含的所有引用指向的对象,再加上这些对象又指向的对象,等等。通常称之为
“
对象网
”
。将这些全部复制即为深层拷贝(
deep copy
)。
可以由输出看到浅层拷贝的效果,对
v2
的操作影响了
v
:
v: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
v: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
不自动对
ArrayList
包含的所有对象执行
clone()
是正确的,因为不能保证那些对象都是可克隆的(
cloneable
)。
返回值方面
用打印对象的方式测试一下?