6

This is just for general knowledge and I am pretty sure it may not be possible, but I am curious to know.

Suppose I have a Student class object s1 and I pass it to a function as myFunc(s1.toString()). I haven't overrided toString() function. When the parameter will reach to the function, can I reference back to the original object just by it's address?

code:

public static void main(){
    Student s1;
    myFunc(s1.toString());
}
public static myFunc(String address){
    Student s2;
    s2 = //get s1 object from address string
}
Allan
  • 12,117
  • 3
  • 27
  • 51
Mohd Naved
  • 448
  • 6
  • 20

3 Answers3

6

What you are asking to do is impossible by design while staying within the Java language. In contrast to languages like C that simply hand over arbitrary control over a region of memory to a program, the JVM uses a capability model, where both security and some measure of correctness depend on the fact that references can't be forged (manufactured from user-defined data such as a string instead of generated by the VM itself)--the only official way to get a reference to an object is to create that object via new or to copy an existing reference.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
  • I understand what you are explaining. If I'm right, If this kind of predefined functionality would be possible it will be same like concept of Pointers in C. Still as you can see there is @AndyTurner's answer which can give you a way to do it. It is a workaround though but still somehow it's possible. I am not saying to oppose your answer. But there are workarounds possible, that's what increase our knowledge and experience. I appreciate your detailed explanation. – Mohd Naved May 09 '18 at 06:03
5

While the default hashcode in the common implementations does use the object address to generate it, it's not reversible (and the address being used is an implementation detail, not a specified functionality).

Even if it were possible, the address of an object can change during the runtime (whereas the default hashcode doesn't), so it wouldn't be a viable approach even if there were a way to reverse it.

Kayaman
  • 72,141
  • 5
  • 83
  • 121
  • So you're implying that there MAY be a way to do it, if we know what class object it is and we have the hashcode/address? – Mohd Naved May 09 '18 at 05:44
  • Wow, I never knew the address could change! Can you explain how it does that a bit more? – Sweeper May 09 '18 at 05:44
  • 4
    @MohdNaved very few things are impossible if you really put effort in it. It's just not very useful to put effort into silly things. – Kayaman May 09 '18 at 05:46
  • @Kayaman well it is curiosity that always give rise to doubts. I appreciate the help – Mohd Naved May 09 '18 at 05:47
  • 1
    @Sweeper the GC does memory defragmentation/housekeeping, so the original address of an object is highly unlikely to be the same in a long running program. – Kayaman May 09 '18 at 05:48
  • @MohdNaved you could look at what Unsafe has to offer, but getting the address has to be done in a reliable way and not based on the hashcode. – Kayaman May 09 '18 at 05:51
  • 1
    It's also important to note that while widely used in fact, *`Unsafe` is not part of Java*, and Oracle has announced an intention to remove it. – chrylis -cautiouslyoptimistic- May 09 '18 at 05:52
  • 1
    @chrylis yeah, it will be interesting to see how that plays out. It hasn't been exactly crystal clear on what will happen with Unsafe and when (e.g. https://blog.dripstat.com/removal-of-sun-misc-unsafe-a-disaster-in-the-making/ ). – Kayaman May 09 '18 at 05:55
  • @Kayaman My guess is that it goes away in Java 12. Java 11 comes out with LTS support for enterprises that need to stay with existing stacks that use it, and then Oracle pulls the plug on the following non-LTS. – chrylis -cautiouslyoptimistic- May 09 '18 at 05:56
2

The easiest way to do this would be to register all instances of Student when you create them:

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);
  }
}

Then you could get the instance in your method using Student.fromString(address).

But there are a lot of reasons not to do this:

  • It leaks memory, because Student instances can never be GC'd as they are reachable through the registry.
  • It unsafely publishes the instance
  • It means you can't change the value of toString() after the constructor, should you want to provide a custom implementation later
  • It is mutable global state, which is never a good idea
  • As a consequence of the previous point, it is hard to test
  • Hash codes are not unique, so multiple instances of Student may have the same toString; in such a case, the implementation here would return the last-created instance with the given string.

as a few to get you started.

In short, it would be inadvisable to do this.

There are alternative ways to implement a registry which avoid some or all of these problems, but it would be reinventing the wheel.

You don't need to refer to instances by string: refer to them using references.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
  • toString() should be rewrite to ensure that two objects have deifferent toString() value.Because Object.toString() use ObjectIdentityHashCode as default which may be same between two different objects. – Hello World May 09 '18 at 05:57
  • 1
    @user9761865 that is also true; OP does not specify whether s/he expects the method to do in the face of toString collision. Another reason for the list. – Andy Turner May 09 '18 at 06:04