【问题标题】:What's the most elegant workaround for inability to pass by reference in Java?在 Java 中无法通过引用传递的最优雅的解决方法是什么?
【发布时间】:2011-11-01 23:44:42
【问题描述】:

我有很深的嵌套结构,“remove(<Something>)”、“contains(<Something>)”等方法依赖于访问原始引用以将其删除等(引用的副本不会这样做) .

人们如何最好地解决这个问题,以便他们仍然可以方便地在不同的任意方法和构造函数等中添加、删除、测试他们想要的对象等,而不会增加任何不必要的复杂性或任何不必要的性能损失?

【问题讨论】:

  • 你能澄清一下吗?也许举个问题的例子? Java 通过引用传递除原始类型(int、char、boolean ...)之外的任何内容。只有原始类型通过值传递。
  • @G_H 是错误的 错误的。 Java 按值、句点传递所有内容。
  • @G_H 我强烈反对。 Java 通过值传递所有内容。您所说的按引用传递实际上是按引用传递值。
  • Java 传递引用的值; )
  • 不,它没有。按值传递引用是 PASS BY VALUE。仅仅因为java调用引用引用并不意味着它使用引用传递。如果 java 中的引用被称为 hojongs,java 将不会被 hojong 传递。

标签: java reference pass-by-reference contains


【解决方案1】:

removecontains 这样的方法可以很好地通过值传递。原因是即使引用被复制,它们复制的值与原始值相同。只需查看 Collections API。如果你做类似(伪代码)

List list = new List();
list.add(object1) // assume you have an object1 reference

然后你做

myRemove(list, object1);

listobject 1 都是按值传递的,因此在 myRemove 方法中它们是原始引用的副本。如果在myRemove 你这样做了

list.remove(object1);

对象仍然从列表中删除没有问题。此外,由于两个作用域中的listobject1 引用都指向相同的底层对象,因此调用作用域中的列表引用指的是已删除对象的列表。

唯一需要通过引用传递语义的情况是,如果您想修改方法中的引用并将修改应用于调用该方法的范围。

所以如果你想这样做

List myList = new List(); 
changeList(myList); 

并让changeList 更改 myList 在调用范围内的指向,如果没有一些技巧,它将无法工作。这个诡计被称为double indirection。基本上,您创建一个对象,该对象具有您希望能够通过引用传递语义访问的实例,然后传递容器对象。

所以

class MyContainer {
    List list
}

现在您可以将MyContainer 的实例传递给方法,并更改列表值,并在list 点将被更改的调用范围内。请注意,您在这里没有做任何特别的事情,一切仍然是按值传递。

【讨论】:

  • 传递产生的参考副本是否也符合与原始参考的“==”相等性?在所有情况下?
  • 如果你很懒,你可以只使用 1 元素数组而不是自定义容器类
【解决方案2】:

人们如何最好地解决这个问题......

通过使用成员字段(用于处理引用,而不是副本)以及使用继承和接口(用于处理嵌套结构)。

【讨论】:

    猜你喜欢
    • 2023-03-30
    • 2014-02-09
    • 2011-03-31
    • 1970-01-01
    • 2014-04-28
    • 1970-01-01
    • 2021-10-18
    • 2010-11-28
    • 1970-01-01
    相关资源
    最近更新 更多