-1

我对使用按值传递的 Java 概念有疑问。我用 C 语言做了很多编程,但我对 Java 非常缺乏经验,所以我一直在编写一些代码来了解更多关于它的知识。我已经阅读了许多关于是否存在任何按引用传递的堆栈溢出问题,答案似乎是 Java 总是使用按值传递(略有偏差是它按值传递对对象的引用)。

考虑到这一点,我设法正确地混淆了自己,我不明白以下示例如何成为按值传递的实例。对于我不理解的内部 Java 工作原理,我将不胜感激。

我有以下代码:

byte[] myByteArray = {23, 45, 67};
myHashMap.put(myKey, new TestClass(100, myByteArray, myOtherByteArray));
Arrays.fill(myByteArray, (byte)0);

myHashMapaConcurrentHashMapTestClass定义在哪里:

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变量被调用更改了,我的问题是......为什么?TestClassConcurrentHashMapArrays.fill

当实例化一个新的TestClass时,我不是myByteArray按值传递吗?

4

3 回答 3

2

所有对象都通过传递引用来使用,该引用本身是按值传递的,除非使用复制构造函数或 Cloneable 进行克隆clone(),在这种情况下,传递对新对象的引用的值。数组也是对象,因此也是以这种方式引用的对象。如果一个被修改,所有其他对它的引用都将反映这些变化。

于 2013-09-07T20:02:05.903 回答
0

你的困惑是因为你的问题的前提是有缺陷的——“数组”不能通过。数组是对象,而对象不是 Java 中的值。Java 中唯一的类型是原始类型和引用类型(注意:没有“对象类型”),因此 Java 中唯一的值是原始类型和引用。

当我使用调试器单步执行代码时,我可以看到存储在 TestClass(以及随后在 ConcurrentHashMap)中的 byte1 变量被 Arrays.fill 调用更改,我的问题是……为什么?

您的byte1变量尚未更改。byte1有一个引用类型;即它是一个参考。它的值是一个内存地址。这个值保持不变。

所指向的数组对象byte1的内容已更改。

实例化一个新的 TestClass 时,我不是按值传递 myByteArray 吗?

是的,你是。

于 2013-09-08T02:06:22.590 回答
0

Java 是按值传递的。

总是。

唯一棘手的部分是将参数传递给方法,这在堆栈溢出问题中进行了描述。

(以下重要答案的副本)


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
于 2013-09-08T01:29:15.580 回答