JDK-8269097 : Add java.util.Objects.newIdentity method
  • Type: CSR
  • Component: core-libs
  • Sub-Component: java.util
  • Priority: P3
  • Status: Closed
  • Resolution: Withdrawn
  • Fix Versions: tbd
  • Submitted: 2021-06-21
  • Updated: 2021-07-19
  • Resolved: 2021-07-19
Related Reports
CSR :  
Description
Summary
-------

Add `java.util.Objects.newIdentity` to supply a unique object with identity.  
This is a replacement code can be used today for the traditional `new Object()` idiom, which will be deprecated under Project Valhalla.

Problem
-------

Forward looking to JEP 401: Primitive Objects (Preview), the current practice using `new Object()` to create an object suitable for use as a unique key or synchronization is problematic.  

Refer to [JEP 401: Primitive Classes (Preview)][https://openjdk.java.net/jeps/401]

The naming and context are discussed on the valhalla-spec-experts emails [Making Object Abstract](https://mail.openjdk.java.net/pipermail/valhalla-spec-experts/2021-June/001534.html).



Solution
--------

Creating an API for the specific purpose of creating a unique object with identity enables a smooth transition away from the problematic use case and enables specific recommendations and transitional tools.


Specification
-------------

The method `newIdentity()` is added to `java.util.Objects`.

    /**
     * {@return a new instance of an unspecified class}
     * The object has a unique identity; no other references to it exist.
     * It can be used for synchronization, or where a placeholder Object is needed.
     * The class does not override any of the methods of {@code java.lang.Object}.
     * Use this method to avoid relying on the {@linkplain Object#Object() Object constructor}.
     *
     * @since 17
     */
    public static Object newIdentity() {...}

In java.lang.Object the javadoc in the constructor includes a link to `java.util.Objects.newIdentity()`

     /**
      * Constructs a new object.
      * @see Objects#newIdentity()
      */
     public Object() {}


Comments
Marking the API as a Preview-feature would render it useless as a transition aid. It would not be adopted and there would be no advantage or opportunity to get developers aware of the important distinctions and put them into practice.
01-07-2021

The terminology for identity can be defined in terms of existing JLS and VM concepts. The value-based class terminology has been defined and refined over several releases as a subset of the allowable behavior of Object is the counterpart to identity. Similarly, defining identity in terms of == (same ness) as defined for Object in Objects.equals, presence of a Monitor with which the concepts of synchronization, waiting and notification are based, can correctly describe the returned object now and remain so with Valhalla. The description of identity could be in the same file with the value-based description to be able to compare and contrast them. For further reading the reference to the in-process JEPs can motivate the usefulness of the particular subset of Object API and behavior.
01-07-2021

I'd be more comfortable with a naming like "newIdentity" that implicitly refers to various Valhalla concepts if the method were @Preview-ed. The name "newObject" can be understand solely within the concepts presently found in the JDK and Java SE. The name "newObject" might not be the best name post-Valhalla, but I don't think "newIdentity" is a good name absent Valhalla framing.
01-07-2021

I too have concerns about the name of this method, in three broad areas. 1. The name is likely to be incredibly confusing to most Java developers, at least for the next several years. Most developers will _not_ have heard of the Valhalla concepts of _identity classes_ and _primitive classes_ and so they will have no idea that this name refers to those concepts. Instead, they'll think it means something else. The `java.security.Identity` class is only one possible source of confusion. A more likely source of confusion is that current (pre-Valhalla) Java does have the notion of identity vs. equality. For example, many Java programmers are aware that two strings can be `equals()` even if they are `!=`. Thus, one might think this method somehow gives an existing object a new identity, so that two objects that were `==` are now `!=`. Of course, this doesn't make any sense at all, hence my claim this will be incredibly confusing. 2. One can justify the name `newIdentity` by introducing the concepts of _identity classes_ and _primitive classes_ from Valhalla. This can be done, but it might quite difficult, as it's forward-looking and speculative. Consider the careful wordsmithing of the "value-based class" concept in the present JDK. Probably it's worth a mention in this doc that the returned instance is _not_ value-based. A similar "identity-based class" page might be necessary to explain this concept, or perhaps such material could be included inline here. It would have to be carefully written to explain the concept adequately without unnecessarily constraining Project Valhalla. 3. The name "newIdentity" embodies the concepts of _identity classes_ and _primitive classes_, concepts whose names have changed twice during the course of Project Valhalla -- so far. If the names change again, it will render this API obsolete. Or, the presence of this API in Java SE serves as a constraint against future renaming. Either one seems undesirable. Here are a couple suggestions for alternative names. `newObject` -- the advantage is that everybody knows what this means already. One could claim that this will become obsolete or ambiguous when Valhalla is delivered, but I think that claim is overstated and pedantic. People are unlikely to forget what this means or why this API is here. `newIdentityObject` -- more descriptive, but also more verbose. Still requires the notion of "identity" to be described, as discussed above.
30-06-2021

[~dlsmith], there are multiple newFoo methods in the JDK which are declared to return either an interface type or an abstract class (JMXConnectorServerFactory.newJMXConnectorServer, Lock.newCondition, etc.); I don't think either concern is likely to cause confusion and the docs can be easily written to address those point. (The returned object of this method is not, in particular, a now-deprecated, java.security.Identity.)
30-06-2021

Another critique of `newObject` is that it has two potential interpretations, both of which are misguided: 1. A developer might read `Object` as the class (per `getClass`) of the returned object. This is wrong���the reason for introducing a factory method is so that it can return instances of a *subclass* of `Object`. 2. A developer might read `Object` as the type of the returned object, and conclude that an arbitrary object of any kind is fair game. But this is much more permissive than the intent, which is to return an instance of an uninteresting class; you can't cast it to `String` or something. The object is only useful because of its identity.
29-06-2021

The rationale for the newIdentity name is to emphasize that the object has a more specific purpose that includes identity based operations including synchronization, uniqueness, etc. that are not available to [value-based](https://docs.oracle.com/en/java/javase/16/docs/api/java.base/java/lang/doc-files/ValueBased.html) objects. This lays the groundwork for [JEP 401: Primitive Classes (Preview)](https://openjdk.java.net/jeps/401) that creates a distinction between identity and value based classes that is reflected in the type system by additional interfaces and in which the class `java.lang.Object` does not have identity.
29-06-2021

The customary name for a method in the JDK's APs which returns a new Foo is "newFoo". So if the method in question is returning an object, by default I'd expect it to be named "newObject". I take it the identity-ness versus the object-ness (or lockable-ness, etc) of a new Object is the focus of this method; however, replacing new Object() with newObject() is an easy to understand transformation.
29-06-2021

The thread about the discussion of this API: https://mail.openjdk.java.net/pipermail/valhalla-spec-experts/2021-June/001533.html
28-06-2021

The bikeshedding on the name is done. [~briangoetz]Brian and [~dlsmith] Dan are satisfied with `newIdentity()` and the EG discussion has come to a conclusion. No guarantee is made about other methods on the class of the instance. None are specified. The newIdentity instance is a general purpose replacement for `new Object()` in use cases where a unique untyped identity is used. With parts of the design of primitive classes still a work in progress, it is too early to make specific recommendations for use of `Objects.newIdentity()`. Brian and Dan prefer leaving flexibility in the spec.
26-06-2021

Moving to Provisional. Naming bikeshed: does this method return a new *identity* a new *object* and a new object-with-identity, etc. Is the returned object guaranteed to only have methods defined in Object? If the Object constructor is soft-deprecated for usage other than by subclass constructors, I think it should have an API note to start discouraging direct usage.
25-06-2021

Added a constraint on the class of the instance returned from newIdentity(). ` * The class does not override any of the methods of {@code java.lang.Object}.`
23-06-2021

I agree it would be worthwhile to assert that none of the methods of java.lang.Object are overridden. That's something callers would want to be able to rely on. I'm pretty happy with "The object has a unique identity; no other references to it exist." as a guide to the == behavior, etc. I thought about asserting something about interfaces, but we do want flexibility there in the future, and making a blacklist is a task that's never done. (Sure, Serializable and Cloneable are the top candidates, but will there be more in the future?) I'd hesitate to draw *any* attention to interfaces, because that's not really the point. If somebody's doing something that reveals whether a particular interface is implemented, they're probably doing it wrong.
23-06-2021

For the time being a rather loose spec is advantageous, falling back on the assumptions of `new Object()` as it is being proposed as a replacement for `new Object()`.
22-06-2021

It seems to me that some stronger semantics should be required for certain things. In particular: * the idea of "unique identity" assumes rather a lot; perhaps better to say that the reference to the new instance will always return false when compared to any other reference using `==`; * some statements about the behavior of `equals()` being `==` and `hashCode()` being `System.identityHashCode()` seem necessary; * we might want to specify that the class is _not_ Serializable and maybe _not_ Cloneable; * there are probably a bunch of things that we want to leave unspecified, such as the set of interfaces that are implemented; however, it might be worth specifying that the interfaces implemented are unspecified and may change over time.
22-06-2021

[~rriggs], please include links to any specific discussion about the design and naming of this method.
22-06-2021