3

A library I use contains a certain object type, LackingObject (some type), which lacks an attribute of type Ext (some type). If I was able to change the LackingObject class, I would simply add an attribute with type Ext, but LackingObject cannot be changed, nor extended. What I'd do now in languages like C or C++ is to create a Map that maps LackingObjects to Exts, which, in Java, would (somewhat equivalently) look like

Map<LackingObject, Ext> object_extension = new HashMap<>();

so whenever I encounter a LackingObject in my code for the first time, I can call

LackingObject o = ...;
Ext value = compute_value_for(o, ...);
object_extension.put(o, value);

and then, to recall that added attribute, I would call

Ext resolved = object_extension.get(o);

This however will not work, as the default HashMap behavior is to map the results of Object::hashCode, not Objects, to values, so if I had two (apart from the Ext value) equal LackingObjects, they could not both be a unique key in a java.util.HashMap.

The question: In Java, is there at least one of the following:

  • a way to let the standard libraries map object instances to values?

  • a way to receive an unique identifier for an object instance?

I found a 7 year old post somewhat related to this topic, but I hope things have changed during the years.

The final resort would be to create a wrapper class,

class Wrapper{
    LackingObject o;
    Ext v;
}

but that overall seems to me like an inferior solution, as we would be adding a potentially redundant new object type to the project structure, instead of just adding a few statements.

(Unrelated to the topic, as this part of the problem is specific to my current condition, but this 'inferior solution' would also require me to change a lot of already existing source code, which I would happily avoid, if possible.)

14
  • What is the library? Commented Jan 1, 2021 at 18:49
  • 1
    Why don't you just encapsulate the LackingObject in a class that includes the attribute? It's not an inferior approach. Quite standard and extensible, and much more readable than what you're describing. Read Effective Java, favor composition over inheritence... Commented Jan 1, 2021 at 18:50
  • 1
    Why don't just override equals() in the LackingObject class? This way you decide when two objects are the same, regarding their variable values, for example. Equals won't check for hashcodes if you override it Commented Jan 1, 2021 at 19:20
  • 1
    @BasilBourque But the question is not about ANTLR. It is clearly about LackingObjects and Exts. Commented Jan 1, 2021 at 19:31
  • 1
    @CaptainTrojan totally right, indeed. Reading it twice doesn't even make sense, as you wouldn't have to store the Ext in any Map if LackingObject could hold an Ext instance. This question was a good one, taking into account your needs and limits. +1 Commented Jan 1, 2021 at 19:38

2 Answers 2

8

You can use IdentityHashMap for this purpose. According to its documentation:

This class implements the Map interface with a hash table, using reference-equality in place of object-equality when comparing keys (and values). In other words, in an IdentityHashMap, two keys k1 and k2 are considered equal if and only if (k1==k2). (In normal Map implementations (like HashMap) two keys k1 and k2 are considered equal if and only if (k1==null ? k2==null : k1.equals(k2)).)
This class is not a general-purpose Map implementation! While this class implements the Map interface, it intentionally violates Map's general contract, which mandates the use of the equals method when comparing objects. This class is designed for use only in the rare cases wherein reference-equality semantics are required.
Sign up to request clarification or add additional context in comments.

Comments

2

System.identityHashCode

Digging in the guts of IdentityHashMap (obtained thanks to Answer by Unmitigated), I found an answer to the partial question:

What is the way to receive a unique identifier for an object instance?

…with the key being: System.identityHashCode

with the signature of

int identityHashCode(Object);

To quote the Javadoc:

Returns the same hash code for the given object as would be returned by the default method hashCode(), whether or not the given object's class overrides hashCode(). The hash code for the null reference is zero.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.