我对使用pass-by-value的Java概念有疑问。我在C中做了很多编程,但是我对Java非常缺乏经验,所以我一直在编写一些代码来学习更多关于它的知识。我已经阅读了许多关于是否存在任何pass-by-reference的堆栈溢出问题,答案似乎是Java总是使用pass-by-value(稍有偏差是它通过值传递对象的引用)。 / p>
考虑到这一点,我设法正确地混淆了自己,我不明白以下示例如何成为传值的实例。我很感激对我不理解的内部Java工作的解释。
我有以下代码:
byte[] myByteArray = {23, 45, 67};
myHashMap.put(myKey, new TestClass(100, myByteArray, myOtherByteArray));
Arrays.fill(myByteArray, (byte)0);
其中myHashMap
是ConcurrentHashMap
且TestClass
已定义:
public class TestClass
{
public final int number;
public final byte[] byte1;
public final byte[] byte2;
public TestClass(int a, byte[] b, byte[] c)
{
number = a;
byte1 = b;
byte2 = c;
}
}
当我使用调试器逐步执行代码时,我可以看到存储在byte1
中的TestClass
变量(随后在ConcurrentHashMap
中)被{{1}更改打电话,我的问题是......为什么?
在实例化新的Arrays.fill
时,我没有按值传递TestClass
吗?
答案 0 :(得分:2)
所有对象都通过传递一个引用来使用,该引用本身是通过值传递的,除非使用复制构造函数或Cloneable的clone()
进行克隆,在这种情况下,传递对新对象的引用值。数组也是对象,因此就是这样的对象。如果修改了一个,则保留的所有其他引用都将反映这些更改。
答案 1 :(得分:0)
Java是按值传递的。
始终
唯一棘手的部分是将参数传递给方法,这在this堆栈溢出问题中有所描述。
(下面重要答案的副本)
Java始终是按值传递的。困难的是可以理解Java将对象作为引用传递,并且这些引用是按值传递的。
它是这样的:
public void foo(Dog d) {
d.getName().equals("Max"); // true
d = new Dog("Fifi");
d.getName().equals("Fifi"); // true
}
Dog aDog = new Dog("Max");
foo(aDog);
aDog.getName().equals("Max"); // true In this example aDog.getName() will still return "Max". d is not overwritten in the function as the object reference is passed by value.
同样地:
public void foo(Dog d) {
d.getName().equals("Max"); // true
d.setName("Fifi");
}
Dog aDog = new Dog("Max");
foo(aDog);
aDog.getName().equals("Fifi"); // true
答案 2 :(得分:0)
你的困惑是因为你的问题的前提是有缺陷的 - “数组”不能通过。数组是对象,对象不是Java中的值。 Java中唯一的类型是基本类型和引用类型(注意:没有“对象类型”),因此Java中唯一的值是基元和引用。
当我使用调试器逐步执行代码时,我可以看到 存储在TestClass中的byte1变量(随后在 ConcurrentHashMap由Arrays.fill调用改变,我的问题是 ......为什么?
您的byte1
变量未已被更改。 byte1
有一个引用类型;即它是一个参考。它的值是一个内存地址。这个值保持不变。
byte1
指向的数组对象的内容已更改。
当实例化一个新的TestClass时,我没有按值传递myByteArray吗?
是的,你是。