diff --git a/src/java.base/share/classes/java/lang/constant/ConstantUtils.java b/src/java.base/share/classes/java/lang/constant/ConstantUtils.java index ff53a94d619..10ed2758e3a 100644 --- a/src/java.base/share/classes/java/lang/constant/ConstantUtils.java +++ b/src/java.base/share/classes/java/lang/constant/ConstantUtils.java @@ -36,6 +36,7 @@ import static java.util.Objects.requireNonNull; class ConstantUtils { /** an empty constant descriptor */ public static final ConstantDesc[] EMPTY_CONSTANTDESC = new ConstantDesc[0]; + static final ClassDesc[] EMPTY_CLASSDESC = new ClassDesc[0]; static final Constable[] EMPTY_CONSTABLE = new Constable[0]; static final int MAX_ARRAY_TYPE_DESC_DIMENSIONS = 255; diff --git a/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java b/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java index 175d91bf3f6..738c4d68a43 100644 --- a/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java +++ b/src/java.base/share/classes/java/lang/constant/MethodTypeDesc.java @@ -55,6 +55,34 @@ public sealed interface MethodTypeDesc return MethodTypeDescImpl.ofDescriptor(descriptor); } + /** + * {@return a {@linkplain MethodTypeDesc} with the given return type and no + * parameter types} + * + * @param returnDesc a {@linkplain ClassDesc} describing the return type + * @throws NullPointerException if {@code returnDesc} is {@code null} + * @since 21 + */ + static MethodTypeDesc of(ClassDesc returnDesc) { + return new MethodTypeDescImpl(returnDesc, ConstantUtils.EMPTY_CLASSDESC); + } + + /** + * {@return a {@linkplain MethodTypeDesc} given the return type and a list of + * parameter types} + * + * @param returnDesc a {@linkplain ClassDesc} describing the return type + * @param paramDescs a {@linkplain List} of {@linkplain ClassDesc}s + * describing the parameter types + * @throws NullPointerException if any argument or its contents are {@code null} + * @throws IllegalArgumentException if any element of {@code paramDescs} is a + * {@link ClassDesc} for {@code void} + * @since 21 + */ + static MethodTypeDesc of(ClassDesc returnDesc, List paramDescs) { + return of(returnDesc, paramDescs.toArray(ConstantUtils.EMPTY_CLASSDESC)); + } + /** * Returns a {@linkplain MethodTypeDesc} given the return type and parameter * types. diff --git a/test/jdk/java/lang/constant/MethodTypeDescTest.java b/test/jdk/java/lang/constant/MethodTypeDescTest.java index 9619b831d3c..482267ff33f 100644 --- a/test/jdk/java/lang/constant/MethodTypeDescTest.java +++ b/test/jdk/java/lang/constant/MethodTypeDescTest.java @@ -25,6 +25,7 @@ import java.lang.invoke.MethodType; import java.lang.constant.ClassDesc; import java.lang.constant.MethodTypeDesc; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -36,6 +37,7 @@ import static java.lang.constant.ConstantDescs.CD_void; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertThrows; import static org.testng.Assert.fail; /** @@ -52,6 +54,9 @@ public class MethodTypeDescTest extends SymbolicDescTest { // Tests accessors (rType, pType, pCount, pList, pArray, descriptorString), // factories (ofDescriptor, of), equals + if (r.parameterCount() == 0) { + assertEquals(r, MethodTypeDesc.of(r.returnType())); + } assertEquals(r, MethodTypeDesc.ofDescriptor(r.descriptorString())); assertEquals(r, MethodTypeDesc.of(r.returnType(), r.parameterArray())); assertEquals(r, MethodTypeDesc.of(r.returnType(), r.parameterList().toArray(new ClassDesc[0]))); @@ -59,6 +64,12 @@ public class MethodTypeDescTest extends SymbolicDescTest { assertEquals(r, MethodTypeDesc.of(r.returnType(), IntStream.range(0, r.parameterCount()) .mapToObj(r::parameterType) .toArray(ClassDesc[]::new))); + assertEquals(r, MethodTypeDesc.of(r.returnType(), r.parameterList())); + assertEquals(r, MethodTypeDesc.of(r.returnType(), List.copyOf(r.parameterList()))); + assertEquals(r, MethodTypeDesc.of(r.returnType(), r.parameterList().stream().toList())); + assertEquals(r, MethodTypeDesc.of(r.returnType(), IntStream.range(0, r.parameterCount()) + .mapToObj(r::parameterType) + .toList())); } private void testMethodTypeDesc(MethodTypeDesc r, MethodType mt) throws ReflectiveOperationException { @@ -255,54 +266,29 @@ public class MethodTypeDescTest extends SymbolicDescTest { } public void testBadMethodTypeRefs() { + // ofDescriptor List badDescriptors = List.of("()II", "()I;", "(I;)", "(I)", "()L", "(V)V", "(java.lang.String)V", "()[]", "(Ljava/lang/String)V", "(Ljava.lang.String;)V", "(java/lang/String)V"); for (String d : badDescriptors) { - try { - MethodTypeDesc r = MethodTypeDesc.ofDescriptor(d); - fail(d); - } - catch (IllegalArgumentException e) { - // good - } + assertThrows(IllegalArgumentException.class, () -> MethodTypeDesc.ofDescriptor(d)); } + assertThrows(NullPointerException.class, () -> MethodTypeDesc.ofDescriptor(null)); - // try with null argument - try { - MethodTypeDesc r = MethodTypeDesc.ofDescriptor(null); - fail("should fail with NPE"); - } catch (NullPointerException ex) { - // good - } + // of(ClassDesc) + assertThrows(NullPointerException.class, () -> MethodTypeDesc.of(null)); + // of(ClassDesc, ClassDesc...) + assertThrows(NullPointerException.class, () -> MethodTypeDesc.of(CD_int, (ClassDesc[]) null)); + assertThrows(NullPointerException.class, () -> MethodTypeDesc.of(CD_int, new ClassDesc[] {null})); // try with void arguments, this will stress another code path in particular // ConstantMethodTypeDesc::init - try { - MethodTypeDesc r = MethodTypeDesc.of(CD_int, CD_void); - fail("can't reach here"); - } - catch (IllegalArgumentException e) { - // good - } + assertThrows(IllegalArgumentException.class, () -> MethodTypeDesc.of(CD_int, CD_void)); - try { - MethodTypeDesc r = MethodTypeDesc.of(CD_int, null); - fail("ClassDesc array should not be null"); - } - catch (NullPointerException e) { - // good - } - - try { - ClassDesc[] paramDescs = new ClassDesc[1]; - paramDescs[0] = null; - MethodTypeDesc r = MethodTypeDesc.of(CD_int, paramDescs); - fail("ClassDesc should not be null"); - } - catch (NullPointerException e) { - // good - } + // of(ClassDesc, List) + assertThrows(NullPointerException.class, () -> MethodTypeDesc.of(CD_int, (List) null)); + assertThrows(NullPointerException.class, () -> MethodTypeDesc.of(CD_int, Collections.singletonList(null))); + assertThrows(IllegalArgumentException.class, () -> MethodTypeDesc.of(CD_int, List.of(CD_void))); } }