1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package java.lang.constant; 26 27 import java.lang.invoke.MethodType; 28 import java.lang.invoke.TypeDescriptor; 29 import java.util.List; 30 import java.util.stream.Collectors; 31 import java.util.stream.Stream; 32 33 /** 34 * A <a href="package-summary.html#nominal">nominal descriptor</a> for a 35 * {@linkplain MethodType} constant. 36 * 37 * @apiNote In the future, if the Java language permits, {@linkplain MethodTypeDesc} 38 * may become a {@code sealed} interface, which would prohibit subclassing except 39 * by explicitly permitted types. Non-platform classes should not implement 40 * {@linkplain MethodTypeDesc} directly. 41 * 42 * @since 12 43 */ 44 public interface MethodTypeDesc 45 extends ConstantDesc, 46 TypeDescriptor.OfMethod<ClassDesc, MethodTypeDesc> { 47 /** 48 * Creates a {@linkplain MethodTypeDesc} given a method descriptor string. 49 * 50 * @param descriptor a method descriptor string 51 * @return a {@linkplain MethodTypeDesc} describing the desired method type 52 * @throws NullPointerException if any argument is {@code null} 53 * @throws IllegalArgumentException if the descriptor string is not a valid 54 * method descriptor 55 * @jvms 4.3.3 Method Descriptors 56 */ 57 static MethodTypeDesc ofDescriptor(String descriptor) { 58 return MethodTypeDescImpl.ofDescriptor(descriptor); 59 } 60 61 /** 62 * Returns a {@linkplain MethodTypeDesc} given the return type and parameter 63 * types. 64 * 65 * @param returnDesc a {@linkplain ClassDesc} describing the return type 66 * @param paramDescs {@linkplain ClassDesc}s describing the argument types 67 * @return a {@linkplain MethodTypeDesc} describing the desired method type 68 * @throws NullPointerException if any argument is {@code null} 69 */ 70 static MethodTypeDesc of(ClassDesc returnDesc, ClassDesc... paramDescs) { 71 return new MethodTypeDescImpl(returnDesc, paramDescs); 72 } 73 74 /** 75 * Gets the return type of the method type described by this {@linkplain MethodTypeDesc}. 76 * 77 * @return a {@link ClassDesc} describing the return type of the method type 78 */ 79 ClassDesc returnType(); 80 81 /** 82 * Returns the number of parameters of the method type described by 83 * this {@linkplain MethodTypeDesc}. 84 * @return the number of parameters 85 */ 86 int parameterCount(); 87 88 /** 89 * Returns the parameter type of the {@code index}'th parameter of the method type 90 * described by this {@linkplain MethodTypeDesc}. 91 * 92 * @param index the index of the parameter to retrieve 93 * @return a {@link ClassDesc} describing the desired parameter type 94 * @throws IndexOutOfBoundsException if the index is outside the half-open 95 * range {[0, parameterCount())} 96 */ 97 ClassDesc parameterType(int index); 98 99 /** 100 * Returns the parameter types as an immutable {@link List}. 101 * 102 * @return a {@link List} of {@link ClassDesc} describing the parameter types 103 */ 104 List<ClassDesc> parameterList(); 105 106 /** 107 * Returns the parameter types as an array. 108 * 109 * @return an array of {@link ClassDesc} describing the parameter types 110 */ 111 ClassDesc[] parameterArray(); 112 113 /** 114 * Returns a {@linkplain MethodTypeDesc} that is identical to 115 * this one, except with the specified return type. 116 * 117 * @param returnType a {@link ClassDesc} describing the new return type 118 * @return a {@linkplain MethodTypeDesc} describing the desired method type 119 * @throws NullPointerException if any argument is {@code null} 120 */ 121 MethodTypeDesc changeReturnType(ClassDesc returnType); 122 123 /** 124 * Returns a {@linkplain MethodTypeDesc} that is identical to this one, 125 * except that a single parameter type has been changed to the specified type. 126 * 127 * @param index the index of the parameter to change 128 * @param paramType a {@link ClassDesc} describing the new parameter type 129 * @return a {@linkplain MethodTypeDesc} describing the desired method type 130 * @throws NullPointerException if any argument is {@code null} 131 * @throws IndexOutOfBoundsException if the index is outside the half-open 132 * range {[0, parameterCount)} 133 */ 134 MethodTypeDesc changeParameterType(int index, ClassDesc paramType); 135 136 /** 137 * Returns a {@linkplain MethodTypeDesc} that is identical to this one, 138 * except that a range of parameter types have been removed. 139 * 140 * @param start the index of the first parameter to remove 141 * @param end the index after the last parameter to remove 142 * @return a {@linkplain MethodTypeDesc} describing the desired method type 143 * @throws IndexOutOfBoundsException if {@code start} is outside the half-open 144 * range {[0, parameterCount)}, or {@code end} is outside the closed range 145 * {@code [0, parameterCount]} 146 */ 147 MethodTypeDesc dropParameterTypes(int start, int end); 148 149 /** 150 * Returns a {@linkplain MethodTypeDesc} that is identical to this one, 151 * except that a range of additional parameter types have been inserted. 152 * 153 * @param pos the index at which to insert the first inserted parameter 154 * @param paramTypes {@link ClassDesc}s describing the new parameter types 155 * to insert 156 * @return a {@linkplain MethodTypeDesc} describing the desired method type 157 * @throws NullPointerException if any argument is {@code null} 158 * @throws IndexOutOfBoundsException if {@code pos} is outside the closed 159 * range {[0, parameterCount]} 160 */ 161 MethodTypeDesc insertParameterTypes(int pos, ClassDesc... paramTypes); 162 163 /** 164 * Returns the method type descriptor string. 165 * 166 * @return the method type descriptor string 167 * @jvms 4.3.3 Method Descriptors 168 */ 169 default String descriptorString() { 170 return String.format("(%s)%s", 171 Stream.of(parameterArray()) 172 .map(ClassDesc::descriptorString) 173 .collect(Collectors.joining()), 174 returnType().descriptorString()); 175 } 176 177 /** 178 * Returns a human-readable descriptor for this method type, using the 179 * canonical names for parameter and return types. 180 * 181 * @return the human-readable descriptor for this method type 182 */ 183 default String displayDescriptor() { 184 return displayDescriptor(false); 185 } 186 187 /** 188 * Returns a human-readable descriptor for this method type, using the 189 * canonical names for parameter and return types. 190 * 191 * @param detail if true displays class names in full 192 * 193 * @return the human-readable descriptor for this method type 194 */ 195 default String displayDescriptor(boolean detail) { 196 return String.format("(%s)%s", 197 Stream.of(parameterArray()) 198 .map(cd -> cd.displayName(detail)) 199 .collect(Collectors.joining(",")), 200 returnType().displayName(detail)); 201 } 202 203 /** 204 * Compares the specified object with this descriptor for equality. Returns 205 * {@code true} if and only if the specified object is also a 206 * {@linkplain MethodTypeDesc} both have the same arity, their return types 207 * are equal, and each pair of corresponding parameter types are equal. 208 * 209 * @param o the other object 210 * @return whether this descriptor is equal to the other object 211 */ 212 boolean equals(Object o); 213 }