【问题标题】:How does Java Object reference works?Java 对象引用是如何工作的?
【发布时间】:2013-04-18 17:37:13
【问题描述】:

我遇到了一个情况,我很困惑。请帮帮我。 假设我有这样的代码。

MyClass obj1 = null;

List<MyClass> testList = new ArrayList<MyClass>();

testList.add(obj1);//after this line of code, testList will have a "null" at first node

obj1 = new MyClass();//after this line of code, testList still have a "null"
                     //at first node...
                     //What I want is that testList's first node will become a new 
                     //MyClass object

这是我理解的步骤(可能不正确......):

  1. obj1 存储指向空的指针...
  2. testList 存储指向保存“new ArrayList()”的内存的指针
  3. testList 在其集合中添加 obj1 的指针。
  4. obj1 存储指向“new MyClass()”的指针
  5. 因此,testList中的obj1应该自动指向“new MyClass()”

对不起,我是编程新手... 任何帮助表示赞赏!

【问题讨论】:

  • 在将对象添加到列表之前调用new。查找 java pass by value 以回答您的所有问题。
  • testList.add(obj1); // testList[0] 和 obj1 都引用同一个对象。 obj1 = new MyClass(); // 更改 obj1 以引用新对象。这不会导致对原始对象的所有其他引用都被更改。
  • 非常感谢...我想我现在明白了...
  • 第三步将指针(呃,“引用”)的VALUE添加到列表中。在该点之后对指针本身的任何修改都不会影响存储在列表中的值。 (当然,向多种复合对象添加空指针是无效的。)
  • 请记住,“引用”(或“指针”)只是一个(非常大的)整数,其值表示某物的存储位置。当您将引用/指针作为参数传递时,您将传递该数值,如果您将对象添加到列表中,这就是存储的内容。甚至没有传递指向原始引用变量的链接,只传递了值。

标签: java object pointers reference


【解决方案1】:

这里解释了为什么 testList 在这些代码之后的第一个节点仍然有一个“null”

testList.add(obj1);//after this line of code, testList will have a "null" at first node

obj1 = new MyClass();//after this line of code, testList still have a "null"
                     //at first node...
                     //What I want is that testList's first node will become a new 
                     //MyClass object

第一步

MyClass obj1 = null;

这一行为 MyClass 引用变量(位持有者 作为参考值),但不会创建实际的 Myclass 对象。

第 2 步

List<MyClass> testList = new ArrayList<MyClass>();

创建了一个列表testList,它可以包含MyClass类型的对象

第 3 步

testList.add(obj1);//after this line of code, testList will have a "null" at first node

testList 第一个节点现在将引用 null 但不是 MyClass 对象。

第 4 步

obj1 = new MyClass();

在堆上创建一个新的 MyClass 对象并将新创建的 MyClass 对象分配给引用变量 obj1。

所以现在列表将如何更新它仍然持有一个 null 但不是 MyClass 对象。

所以现在如果你想让testList的第一个节点成为一个新的MyClass对象

然后在obj1 = new MyClass();之后写这段代码

testList.set(0, obj1);

所以现在之后的完整代码将是

MyClass obj1 = null;

List<MyClass> testList = new ArrayList<MyClass>();

testList.add(obj1);//after this line of code, testList will have a "null" at first node

obj1 = new MyClass();

testList.set(0, obj1);

据我了解,这就是您的问题。

【讨论】:

  • @user2296188 我想我已经给出了更恰当的解释。希望这能帮助你理解。
  • @user2296188 乐于助人。
【解决方案2】:
MyClass obj1 = null;

MyClass 类型的名为 obj1 的引用变量不引用任何内容(NULL)。

List<MyClass> testList = new ArrayList<MyClass>();

我们声明一个名为 testList 类型为 List 的引用变量,并将其分配给堆中一些新创建的 ArrayList 对象。

testList.add(obj1);

List testList 的第一个元素被分配了与 obj1 当前持有的相同的引用,即。空。

obj1 = new MyClass();

我们在堆中创建了一个新的MyClass 对象,并为 obj1 分配了它的引用。但是我们没有为List testList 的第一个元素分配任何新的引用,它被分配了 NULL 引用,所以它仍然没有指向任何地方。

【讨论】:

    【解决方案3】:

    当您向ArrayList 添加对象时,对象不会被添加到ArrayList,但指向该对象的指针会被添加。

    所以如果你这样做:

    Object obj1 = new Object() // [location: x1234]
    list.add(obj1); // first index in list points to location x1234
    obj1 = new Object(); // [location: x2345];
    

    现在数组的指针仍然指向旧位置。

    null 也是如此。尽管您将 obj1 的链接更改为新位置,但数组仍指向旧位置 null

    【讨论】:

      【解决方案4】:
      1. obj1 不指向任何东西,指针不存在
      2. 您创建一个新列表,testList 指向该列表
      3. 你没有在列表中添加任何内容,因为你的 obj1 点为空,因此不存在
      4. 您创建的新对象,obj 现在有一个有效指针

      您的列表仍然是空的。

      【讨论】:

      • 不完全是,您的列表只有一个元素,null
      【解决方案5】:

      Java 严格按值传递

      你的大部分困惑来自于

      testList.add(obj1); // makes you think that you've added a pointer to the list
      

      现在如果你修改指针为

      obj1 = new MyClass(); // it would reflect at testList.get(0) as well.. NO!!
      

      如果 Java 是“通过引用传递”就会出现这种情况,但因为它不是 testList.add(obj1); 实际上转换为 testList.add(null); 复制值和设置Array 的第一个索引位置(支持此 ArrayList)为 null

      Java 不像 C 和 C++ 那样使用指针。通过 EDIT 简化事情是它的设计目标之一:删除指针、它们的算术、多重继承、运算符重载等等。

      为了更清楚,如果你修改你的程序如下:

      MyClass obj1 = new MyClass("Object 1"); // modify the constructor to take an id
      List<MyClass> testList = new ArrayList<MyClass>();
      testList.add(obj1);
      obj1 = new MyClass("Object 2");
      System.out.println(testList.get(0).toString()); // implement toSting() to id MyClass
      

      testList 将包含 "Object 1" 而不是 "Object 2"

      【讨论】:

      • 其实绝大多数C/C++参数也是值参数。在 C/C++ 中,您有传递引用参数的选项,但这不是简单 C 代码的标准,只有在大量使用更复杂对象的 C++ 代码中才常见。 (进行指针运算的能力与通过引用与值传递无关。)
      • @HotLicks 与 C/C++ 相比,Java 不支持指针、它们的算术、多重继承等。为了简化事情,这是一个一般性声明。
      • 虽然那是一段修正主义的历史。请记住,Java 是为编程机顶盒而发明的,而“简化”只是为了产生一种简约的语法/语义来完成这项工作。 “Java 哲学”是后来“发现”的。 C 的早期版本更加简单。
      • 如果我在这里触动了神经,我深表歉意。但我非常尊重所有语言。只是我现在不太擅长 C/C++!和平:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-15
      • 2017-09-18
      • 2020-01-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多