【问题标题】:Groovy (or Java) - Pass by reference into a wrapper objectGroovy(或 Java) - 通过引用传递到包装器对象
【发布时间】:2014-10-09 08:48:11
【问题描述】:

在 Java(或 Groovy)中是否可以通过引用将对象传递给包装对象(即:List 或 Map)?

示例代码(在 Groovy 中):

def object = null
def map = [object: object]
object = new Object()

不幸的是 map.object 保持为 null 即使 object 变量没有,所以很明显地图的原始创建是通过值而不是通过引用完成的。

是否可以通过引用创建 List 或 Map,以便当 List 或 Map 之外的对象发生更改时,更改会反映在包装对象内?

【问题讨论】:

  • 不,那不可能

标签: java groovy wrapper pass-by-reference pass-by-value


【解决方案1】:

不,你真的不能那样做。根据您真正想要做的事情,这样的事情可能会有所帮助:

class MyWrapper {
    def wrappedValue
}

def object = new MyWrapper()
def map = [object: object]

object.wrappedValue = 'This is a new value'
assert map.object.wrappedValue == 'This is a new value'

那当然是 Groovy 代码。你可以在 Java 中做同样的事情,只是需要更多的代码。想法是一样的。

【讨论】:

  • AtomicReference 是一个通用且线程安全的 JDK 结构,它允许这种包装。
  • @GPI 他的描述中没有足够的上下文来了解线程安全是否是一个问题。如果所有这些都发生在一个方法中,并且没有任何一个方法逃脱该方法,那么线程安全可能不会产生任何影响。使用您自己的包装器,或由 JDK 提供的包装器或由其他库提供的包装器,当然所有这些都是选项。
  • 我展示的代码演示了一种方法来做原始问题似乎感兴趣的事情是在 Map 中放置一些对实际值有参考的东西。
【解决方案2】:

您可以使用闭包,但需要调用它们:

def object = null
def map = [object: { object }]
object = new Object()

assert map.object() != null

【讨论】:

    【解决方案3】:

    在 Java 中(我也假设在 Groovy 中),当您传递一个对象时 - 您传递 对它的引用的值

    例如当你这样做时:

    Object reference1 = new Object();
    // reference1 now equals some adress in memory, e.g. 0001
    Object reference2 = reference1;
    // reference2 now equals the value of reference1 - i.e. 0001
    

    现在,当我们这样做时:

    reference1 = new Dog();
    // reference1 is now assigned a new value, which is the memory adress
    // of the new Dog object.
    

    没有理由影响reference2reference2 仍然持有地址 0001。这正是你正在做的事情。

    让我们检查一下您发布的代码中发生了什么:

    def object = null
    

    创建了一个名为object 的新引用,并且没有分配地址,即null。 (没有创建对象,只有一个引用)。

    def map = [object: object]
    

    创建了一个名为map 的新引用。它被分配了一个新的地图对象,其中有一个名为object 的条目。地图被传递名为object的引用的值

    您还记得,object 引用的值当前是 null。所以这个值被传递(即按值传递)到映射对象中的引用,现在它也包含null

    object = new Object()
    

    主程序中的引用object 被分配了一个新值——一个新的Object。它现在保存 新对象的地址,例如0001.

    执行此操作时,您在 object 变量中输入了一个值 - 您输入了一个对象的地址(之前是 null)。

    如果您考虑一下,没有理由影响地图。该地图具有完全不同的参考。只是因为之前两个引用都持有相同的地址内存,即引用了相同的对象(或者在这种情况下,没有对象,因为地址是null),并不意味着当一个引用的值发生变化时(即它被分配内存中的不同值),另一个的值也必须改变。

    这是对象和引用之间的重要区别。

    【讨论】:

    • 不正确,groovy 似乎总是通过引用传递,您上面的示例确实修改了主要对象。在 groovy 控制台中查看这个简单示例 def g = ["1","2","3"]; println g; def r = g; r.remove('1'); println r; println g​​​​​​​​​​​
    猜你喜欢
    • 2011-12-12
    • 2011-09-27
    • 2017-09-11
    • 1970-01-01
    • 1970-01-01
    • 2018-04-03
    • 2014-02-08
    相关资源
    最近更新 更多