Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JDK-8280168: Add Objects.toIdentityString #7139

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -292,7 +292,7 @@ private static boolean isObjectMethod(Method m) {
private static Object callObjectMethod(Object self, Method m, Object[] args) {
assert(isObjectMethod(m)) : m;
return switch (m.getName()) {
case "toString" -> self.getClass().getName() + "@" + Integer.toHexString(self.hashCode());
case "toString" -> java.util.Objects.toIdentityString(self);
case "hashCode" -> System.identityHashCode(self);
case "equals" -> (self == args[0]);
default -> null;
Expand Down
26 changes: 25 additions & 1 deletion src/java.base/share/classes/java/util/Objects.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -164,6 +164,30 @@ public static String toString(Object o, String nullDefault) {
return (o != null) ? o.toString() : nullDefault;
}

/**
* {@return a string equivalent to the string returned by {@code
* Object.toString} if that method and {@code hashCode} are not
* overridden}
*
* @implNote
* This method constructs a string for an object without calling
* any overridable methods of the object.
*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original Object.toString() invokes the hashCode() method.
Perhaps the spec should indicate that it calls IdentityhashCode() instead of hashCode().

Though not incorrect, in Valhalla, Not all objects have identity and will need to different implementation.

Are there any use cases in the JDK that will use this method?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the return statement to say if hashCode isn't overridden either. The implSpec tag does explicitly mention identityHashCode already.

There are a few instances of this sort of code in the JDK src directory already; I may include a refactoring of at least one of them in a future revision of the PR. Thanks.

* @implSpec
* The method returns a string equivalent to:<br>
* {@code o.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(o))}
*
* @param o an object
* @throws NullPointerException if the argument is null
* @see Object#toString
* @see System#identityHashCode(Object)
* @since 19
*/
public static String toIdentityString(Object o) {
requireNonNull(o);
return o.getClass().getName() + "@" + Integer.toHexString(System.identityHashCode(o));
}

/**
* Returns 0 if the arguments are identical and {@code
* c.compare(a, b)} otherwise.
Expand Down
37 changes: 34 additions & 3 deletions test/jdk/java/util/Objects/BasicObjectsTest.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand All @@ -23,9 +23,8 @@

/*
* @test
* @bug 6797535 6889858 6891113 8013712 8011800 8014365
* @bug 6797535 6889858 6891113 8013712 8011800 8014365 8280168
* @summary Basic tests for methods in java.util.Objects
* @author Joseph D. Darcy
*/

import java.util.*;
Expand All @@ -40,6 +39,7 @@ public static void main(String... args) {
errors += testHash();
errors += testToString();
errors += testToString2();
errors += testToIdentityString();
errors += testCompare();
errors += testRequireNonNull();
errors += testIsNull();
Expand Down Expand Up @@ -134,6 +134,37 @@ private static int testToString2() {
return errors;
}

private static int testToIdentityString() {
int errors = 0;
// Test null behavior
try {
Objects.toIdentityString(null);
errors++;
} catch (NullPointerException npe) {
; // Expected
}
// Behavior on typical objects
Object o = new Object(){};
errors += (Objects.toIdentityString(o).equals(o.toString()))? 0 : 1;
// Verify object's toString *not* called
Object badToString = new Object() {
@Override
public String toString() {
throw new RuntimeException();
}
};
Objects.toIdentityString(badToString);
// Verify object's hashCode *not* called
Object badHashCode = new Object() {
@Override
public int hashCode() {
throw new RuntimeException("0xDEADBEFF");
}
};
Objects.toIdentityString(badHashCode);
return errors;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another potential test is on an instance of a class that overrides toString(), that would ensure that toDefaultString() doesn't invoke toString.

}

private static int testCompare() {
int errors = 0;
String[] values = {"e. e. cummings", "zzz"};
Expand Down