< prev index next > src/java.base/share/classes/java/lang/runtime/ObjectMethods.java
Print this page
* questions.
*/
package java.lang.runtime;
+ import jdk.internal.value.PrimitiveClass;
+
import java.lang.invoke.ConstantCallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.invoke.StringConcatFactory;
private static final MethodHandle OBJECT_HASHCODE;
private static final MethodHandle OBJECT_TO_STRING;
private static final MethodHandle STRING_FORMAT;
private static final MethodHandle HASH_COMBINER;
- private static final HashMap<Class<?>, MethodHandle> primitiveEquals = new HashMap<>();
+ /* package-private */
+ static final HashMap<Class<?>, MethodHandle> primitiveEquals = new HashMap<>();
+
private static final HashMap<Class<?>, MethodHandle> primitiveHashers = new HashMap<>();
private static final HashMap<Class<?>, MethodHandle> primitiveToString = new HashMap<>();
static {
try {
}
/**
* Generates a method handle for the {@code toString} method for a given data class
* @param receiverClass the data class
+ * @param simpleName the simple name of the record class
* @param getters the list of getters
* @param names the names
* @return the method handle
*/
private static MethodHandle makeToString(MethodHandles.Lookup lookup,
Class<?> receiverClass,
+ String simpleName,
MethodHandle[] getters,
List<String> names) {
assert getters.length == names.size();
if (getters.length == 0) {
// special case
- MethodHandle emptyRecordCase = MethodHandles.constant(String.class, receiverClass.getSimpleName() + "[]");
+ MethodHandle emptyRecordCase = MethodHandles.constant(String.class, simpleName + "[]");
emptyRecordCase = MethodHandles.dropArguments(emptyRecordCase, 0, receiverClass); // (R)S
return emptyRecordCase;
}
boolean firstTime = true;
splits = split(toSplit);
mhs = new MethodHandle[splits.size()];
for (int splitIndex = 0; splitIndex < splits.size(); splitIndex++) {
String recipe = "";
if (firstTime && splitIndex == 0) {
- recipe = receiverClass.getSimpleName() + "[";
+ recipe = simpleName + "[";
}
for (int i = 0; i < splits.get(splitIndex).size(); i++) {
recipe += firstTime ? names.get(namesIndex) + "=" + "\1" : "\1";
if (firstTime && namesIndex != names.size() - 1) {
recipe += ", ";
requireNonNull(recordClass);
requireNonNull(names);
requireNonNull(getters);
Arrays.stream(getters).forEach(Objects::requireNonNull);
MethodType methodType;
- if (type instanceof MethodType mt)
+ Class<?> receiverType = PrimitiveClass.isPrimitiveClass(recordClass)
+ ? PrimitiveClass.asValueType(recordClass) : recordClass;
+ if (type instanceof MethodType mt) {
methodType = mt;
- else {
+ if (mt.parameterType(0) != receiverType) {
+ throw new IllegalArgumentException("Bad method type: " + mt);
+ }
+ } else {
methodType = null;
if (!MethodHandle.class.equals(type))
throw new IllegalArgumentException(type.toString());
}
List<MethodHandle> getterList = List.of(getters);
+ for (MethodHandle getter : getterList) {
+ if (getter.type().parameterType(0) != receiverType) {
+ throw new IllegalArgumentException("Bad receiver type: " + getter);
+ }
+ }
MethodHandle handle = switch (methodName) {
case "equals" -> {
- if (methodType != null && !methodType.equals(MethodType.methodType(boolean.class, recordClass, Object.class)))
+ if (methodType != null && !methodType.equals(MethodType.methodType(boolean.class, receiverType, Object.class)))
throw new IllegalArgumentException("Bad method type: " + methodType);
- yield makeEquals(recordClass, getterList);
+ yield makeEquals(receiverType, getterList);
}
case "hashCode" -> {
- if (methodType != null && !methodType.equals(MethodType.methodType(int.class, recordClass)))
+ if (methodType != null && !methodType.equals(MethodType.methodType(int.class, receiverType)))
throw new IllegalArgumentException("Bad method type: " + methodType);
- yield makeHashCode(recordClass, getterList);
+ yield makeHashCode(receiverType, getterList);
}
case "toString" -> {
- if (methodType != null && !methodType.equals(MethodType.methodType(String.class, recordClass)))
+ if (methodType != null && !methodType.equals(MethodType.methodType(String.class, receiverType)))
throw new IllegalArgumentException("Bad method type: " + methodType);
List<String> nameList = "".equals(names) ? List.of() : List.of(names.split(";"));
if (nameList.size() != getterList.size())
throw new IllegalArgumentException("Name list and accessor list do not match");
- yield makeToString(lookup, recordClass, getters, nameList);
+ yield makeToString(lookup, receiverType, recordClass.getSimpleName(), getters, nameList);
}
default -> throw new IllegalArgumentException(methodName);
};
return methodType != null ? new ConstantCallSite(handle) : handle;
}
< prev index next >