是Java“通过
我一直认为Java是通过引用 。 不过,我见过一些博客文章(例如,这个博客),声称它不是。 我不认为我理解他们的区别。
什么是解释?
Java始终是按值传递的 。 不幸的是,他们决定将对象的位置称为“参考”。 当我们传递一个对象的值时,我们将引用传递给它。 这对初学者来说很混乱。
它是这样的:
public static void main(String[] args) {
Dog aDog = new Dog("Max");
// we pass the object to foo
foo(aDog);
// aDog variable is still pointing to the "Max" dog when foo(...) returns
aDog.getName().equals("Max"); // true, java passes by value
aDog.getName().equals("Fifi"); // false
}
public static void foo(Dog d) {
d.getName().equals("Max"); // true
// change d inside of foo() to point to a new Dog instance "Fifi"
d = new Dog("Fifi");
d.getName().equals("Fifi"); // true
}
在上面的例子中, aDog.getName()
仍然会返回"Max"
。 在函数foo
, Dog
"Fifi"
没有改变main
的值aDog
,因为对象引用是按值传递的。 如果它通过引用传递,那么在调用foo
之后, main
的aDog.getName()
将返回"Fifi"
。
同样:
public static void main(String[] args) {
Dog aDog = new Dog("Max");
foo(aDog);
// when foo(...) returns, the name of the dog has been changed to "Fifi"
aDog.getName().equals("Fifi"); // true
}
public static void foo(Dog d) {
d.getName().equals("Max"); // true
// this changes the name of d to be "Fifi"
d.setName("Fifi");
}
在上面的例子中, Fifi
是调用foo(aDog)
之后的狗的名字,因为该对象的名字是在foo(...)
。 任何foo
在d
上执行的操作都是这样的,为了所有实际目的,它们都是在aDog
本身上执行的(除非将d
更改为指向不同的Dog
实例,如d = new Dog("Boxer")
)。
我只是注意到你引用了我的文章。
Java Spec说,Java中的所有东西都是按值传递的。 Java中没有“传递参考”这样的东西。
理解这一点的关键是类似的东西
Dog myDog;
不是狗; 它实际上是一个指向狗的指针。
这意味着什么,当你有
Dog myDog = new Dog("Rover");
foo(myDog);
你基本上把创建的Dog
对象的地址传递给foo
方法。
(我说的本质上是因为Java指针不是直接地址,但最简单的方法就是这样想)
假设Dog
对象驻留在内存地址42上。这意味着我们将42传递给该方法。
如果方法被定义为
public void foo(Dog someDog) {
someDog.setName("Max"); // AAA
someDog = new Dog("Fifi"); // BBB
someDog.setName("Rowlf"); // CCC
}
让我们看看发生了什么。
someDog
被设置为值42 someDog
Dog
跟随它指向的Dog
(地址42处的Dog
对象) Dog
(地址42处的Dog
)被要求将他的名字改为Max Dog
被创建。 假设他在地址74 someDog
分配给74 Dog
跟随它指向的Dog
(地址为74的Dog
对象) Dog
(地址为74的那个)被要求将他的名字改为Rowlf 现在让我们考虑一下在该方法之外发生的事情:
myDog
是否改变了?
有关键。
记住myDog
是一个指针,而不是真正的Dog
,答案是NO。 myDog
仍然有值42; 它仍然指向原来的Dog
(但请注意,因为“AAA”行,它的名字现在是“最大” - 仍然是狗; myDog
的值没有改变。)
遵循地址并改变结尾是完全有效的; 但不会改变变量。
Java的工作方式与C完全一样。您可以指定一个指针,将指针传递给方法,跟随方法中的指针并更改指向的数据。 但是,您无法更改指针指向的位置。
在C ++,Ada,Pascal和其他支持通过引用的语言中,您实际上可以更改传递的变量。
要是Java传递by-reference语义中, foo
我们在上面定义的方法会改变其中myDog
指着时分配someDog
上线BBB。
将引用参数看作是传入变量的别名。当分配了别名时,传入的变量也是如此。
Java总是通过值传递参数而不是通过引用。
让我通过一个例子来解释这一点:
public class Main{
public static void main(String[] args){
Foo f = new Foo("f");
changeReference(f); // It won't change the reference!
modifyReference(f); // It will modify the object that the reference variable "f" refers to!
}
public static void changeReference(Foo a){
Foo b = new Foo("b");
a = b;
}
public static void modifyReference(Foo c){
c.setAttribute("c");
}
}
我将逐步解释这一点:
声明一个名为f
的Foo
类型的引用,并将其赋值给一个具有属性"f"
Foo
类型的新对象。
Foo f = new Foo("f");
在方法方面,声明了一个名为a
Foo
类型的引用,并且它的初始null
。
public static void changeReference(Foo a)
在调用方法changeReference
,引用a
将被分配给作为参数传递的对象。
changeReference(f);
声明一个名为b
的Foo
类型的引用,并将其赋值给一个具有属性"b"
Foo
类型的新对象。
Foo b = new Foo("b");
a = b
将引用a
NOT f
重新分配给其属性为"b"
的对象。
当您调用modifyReference(Foo c)
方法时,会创建一个引用c
并将其分配给具有属性"f"
的对象。
c.setAttribute("c");
将改变引用c
点的对象的属性,并且引用f
指向它的是同一个对象。
我希望你现在能理解如何将对象作为参数传递给Java。
链接地址: http://www.djcxy.com/p/49.html上一篇: Is Java "pass