【问题标题】:Getting an object from its address从地址获取对象
【发布时间】:2018-10-19 03:33:38
【问题描述】:

这只是一般知识,我很确定这可能是不可能的,但我很想知道。

假设我有一个学生类对象s1,并将它作为myFunc(s1.toString()) 传递给函数。我没有覆盖toString() 函数。当参数到达函数时,我可以仅通过地址引用回原始对象吗?

代码:

public static void main(){
    Student s1;
    myFunc(s1.toString());
}
public static myFunc(String address){
    Student s2;
    s2 = //get s1 object from address string
}

【问题讨论】:

  • 没有,但是Java一般都是传值,所以你可以直接传Student对象,从方法中操作,修改应该“坚持”。
  • 这是不可能的。你在默认的 toString 中看到的不是地址。
  • @Tim 不,Java 总是按值传递。
  • @TimBiegeleisen java 将引用作为值传递,因此它是按值传递的。
  • @Tim 不会使用地址,也不会使用默认的 toString。

标签: java oop pointers memory reference


【解决方案1】:

虽然常见实现中的默认哈希码确实使用对象地址来生成它,但它是不可逆的(并且所使用的地址是实现细节,而不是指定的功能)。

即使有可能,对象的地址也可以在运行时更改(而默认哈希码不会),因此即使有办法反转它也不是可行的方法。

【讨论】:

  • 所以你的意思是,如果我们知道它是什么类对象并且我们有哈希码/地址,那么可能有办法做到这一点?
  • @MohdNaved 如果你真的付出努力,很少有事情是不可能的。把精力放在愚蠢的事情上并不是很有用。
  • @Sweeper GC 进行内存碎片整理/内务管理,因此在长时间运行的程序中,对象的原始地址不太可能相同。
  • 还需要注意的是,虽然 Unsafe 实际上被广泛使用,但它并不是 Java 的一部分,Oracle 已宣布打算将其删除。
  • @chrylis 是的,看看结果如何会很有趣。对于 Unsafe 会发生什么以及何时发生(例如blog.dripstat.com/…),目前还不是很清楚。
【解决方案2】:

您要求做的事情是不可能的设计,而留在 Java 语言中。与像 C 这样简单地将内存区域的任意控制权交给程序的语言相比,JVM 使用 capability 模型,其中安全性和某种正确性度量取决于引用可以't be forged(由用户定义的数据(如字符串)而不是由 VM 本身生成)——获取对象引用的唯一官方方法是通过 @ 创建该对象987654321@ 或复制现有参考。

【讨论】:

  • 我明白你在解释什么。如果我是对的,如果这种预定义的功能是可能的,它将与 C 中的指针概念相同。仍然如您所见,@AndyTurner 的答案可以为您提供一种方法。虽然这是一种解决方法,但仍然有可能。我并不是要反对你的回答。但是有一些可能的解决方法,这就是增加我们的知识和经验的原因。感谢您的详细解释。
【解决方案3】:

最简单的方法是在创建 Student 的所有实例时注册它们:

class Student {
  private static final Map<String, Student> registry = new HashMap<>();

  Student() {
    registry.put(this.toString(), this);
  }

  static Student fromString(String address) {
    return registry.get(address);
  }
}

然后您可以使用Student.fromString(address) 在您的方法中获取实例。

但是有很多理由不这样做:

  • 它会泄漏内存,因为 Student 实例永远无法被 GC,因为它们可以通过注册表访问。
  • 它不安全地发布实例
  • 这意味着您不能在构造函数之后更改toString() 的值,如果您想稍后提供自定义实现
  • 它是可变的全局状态,这绝不是一个好主意
  • 由于上一点,很难测试
  • 哈希码不是唯一的,所以Student的多个实例可能有相同的toString;在这种情况下,这里的实现将返回最后创建的带有给定字符串的实例。

作为一些帮助您入门。

简而言之,这样做是不可取的。

有一些替代方法来实现注册表,可以避免部分或全部这些问题,但它会重新发明轮子。

您不需要通过字符串引用实例:使用引用来引用它们。

【讨论】:

  • toString() 应该被重写以确保两个对象具有不同的 toString() 值。因为 Object.toString() 使用 ObjectIdentityHashCode 作为默认值,这在两个不同的对象之间可能是相同的。
  • @user9761865 也是如此; OP 没有指定他/她是否希望该方法在面对 toString 冲突时执行。上榜的另一个原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-16
  • 2012-12-18
  • 1970-01-01
  • 2021-02-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多