1 /*
2 * Copyright (c) 2012, 2025, 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
26 package java.lang.reflect;
27
28 import java.lang.annotation.Annotation;
29 import java.util.Arrays;
30 import java.util.Map;
31 import java.util.Set;
32 import java.util.Objects;
33 import java.util.StringJoiner;
34 import java.util.stream.Collectors;
35
36 import jdk.internal.access.SharedSecrets;
37 import jdk.internal.vm.annotation.Stable;
38 import sun.reflect.annotation.AnnotationParser;
39 import sun.reflect.annotation.AnnotationSupport;
40 import sun.reflect.annotation.TypeAnnotationParser;
41 import sun.reflect.annotation.TypeAnnotation;
42 import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;
43 import sun.reflect.generics.repository.ConstructorRepository;
44
45 /**
46 * A shared superclass for the common functionality of {@link Method}
47 * and {@link Constructor}.
48 *
49 * @sealedGraph
50 * @since 1.8
51 */
52 public abstract sealed class Executable extends AccessibleObject
53 implements Member, GenericDeclaration permits Constructor, Method {
54 /*
55 * Only grant package-visibility to the constructor.
56 */
57 @SuppressWarnings("deprecation")
58 Executable() {}
59
60 /**
61 * Accessor method to allow code sharing
62 */
63 abstract byte[] getAnnotationBytes();
64
65 /**
66 * Does the Executable have generic information.
67 */
68 abstract boolean hasGenericInformation();
69
70 abstract ConstructorRepository getGenericInfo();
71
72 boolean equalParamTypes(Class<?>[] params1, Class<?>[] params2) {
73 // The parameter arrays are trusted and the same for a root and all leaf
74 // copies. Thus, == on arrays is more useful than == on Executable.
75 if (params1 == params2)
76 return true;
77 /* Avoid unnecessary cloning */
78 if (params1.length == params2.length) {
79 for (int i = 0; i < params1.length; i++) {
80 if (params1[i] != params2[i])
81 return false;
82 }
83 return true;
84 }
85 return false;
86 }
87
88 Annotation[][] parseParameterAnnotations(byte[] parameterAnnotations) {
89 return AnnotationParser.parseParameterAnnotations(
90 parameterAnnotations,
91 SharedSecrets.getJavaLangAccess().
92 getConstantPool(getDeclaringClass()),
93 getDeclaringClass());
94 }
95
96 void printModifiersIfNonzero(StringBuilder sb, int mask, boolean isDefault) {
97 int mod = getModifiers() & mask;
98
99 if (mod != 0 && !isDefault) {
100 sb.append(Modifier.toString(mod)).append(' ');
101 } else {
102 int access_mod = mod & Modifier.ACCESS_MODIFIERS;
103 if (access_mod != 0)
104 sb.append(Modifier.toString(access_mod)).append(' ');
105 if (isDefault)
106 sb.append("default ");
107 mod = (mod & ~Modifier.ACCESS_MODIFIERS);
108 if (mod != 0)
109 sb.append(Modifier.toString(mod)).append(' ');
110 }
111 }
112
113 String sharedToString(int modifierMask,
114 boolean isDefault,
115 Class<?>[] parameterTypes,
116 Class<?>[] exceptionTypes) {
117 try {
118 StringBuilder sb = new StringBuilder();
119
120 printModifiersIfNonzero(sb, modifierMask, isDefault);
121 specificToStringHeader(sb);
122 sb.append(Arrays.stream(parameterTypes)
123 .map(Type::getTypeName)
124 .collect(Collectors.joining(",", "(", ")")));
125 if (exceptionTypes.length > 0) {
126 sb.append(Arrays.stream(exceptionTypes)
127 .map(Type::getTypeName)
128 .collect(Collectors.joining(",", " throws ", "")));
129 }
130 return sb.toString();
131 } catch (Exception e) {
132 return "<" + e + ">";
133 }
134 }
135
136 /**
137 * Generate toString header information specific to a method or
138 * constructor.
139 */
140 abstract void specificToStringHeader(StringBuilder sb);
141
142 static String typeVarBounds(TypeVariable<?> typeVar) {
143 Type[] bounds = typeVar.getBounds();
144 if (bounds.length == 1 && bounds[0].equals(Object.class)) {
145 return typeVar.getName();
146 } else {
147 return typeVar.getName() + " extends " +
148 Arrays.stream(bounds)
149 .map(Type::getTypeName)
150 .collect(Collectors.joining(" & "));
151 }
152 }
153
154 String sharedToGenericString(int modifierMask, boolean isDefault) {
155 try {
156 StringBuilder sb = new StringBuilder();
157
158 printModifiersIfNonzero(sb, modifierMask, isDefault);
159
160 TypeVariable<?>[] typeparms = getTypeParameters();
161 if (typeparms.length > 0) {
162 sb.append(Arrays.stream(typeparms)
163 .map(Executable::typeVarBounds)
164 .collect(Collectors.joining(",", "<", "> ")));
165 }
166
167 specificToGenericStringHeader(sb);
168
169 sb.append('(');
170 StringJoiner sj = new StringJoiner(",");
171 Type[] params = getGenericParameterTypes();
172 for (int j = 0; j < params.length; j++) {
173 String param = params[j].getTypeName();
174 if (isVarArgs() && (j == params.length - 1)) // replace T[] with T...
175 param = param.replaceFirst("\\[\\]$", "...");
176 sj.add(param);
177 }
178 sb.append(sj.toString());
179 sb.append(')');
180
181 Type[] exceptionTypes = getGenericExceptionTypes();
182 if (exceptionTypes.length > 0) {
183 sb.append(Arrays.stream(exceptionTypes)
184 .map(Type::getTypeName)
185 .collect(Collectors.joining(",", " throws ", "")));
186 }
187 return sb.toString();
188 } catch (Exception e) {
189 return "<" + e + ">";
190 }
191 }
192
193 /**
194 * Generate toGenericString header information specific to a
195 * method or constructor.
196 */
197 abstract void specificToGenericStringHeader(StringBuilder sb);
198
199 /**
200 * Returns the {@code Class} object representing the class or interface
201 * that declares the executable represented by this object.
202 */
203 public abstract Class<?> getDeclaringClass();
204
205 /**
206 * Returns the name of the executable represented by this object.
207 */
208 public abstract String getName();
209
210 /**
211 * {@return the Java language {@linkplain Modifier modifiers} for
212 * the executable represented by this object}
213 * @see #accessFlags
214 */
215 public abstract int getModifiers();
216
217 /**
218 * {@return an unmodifiable set of the {@linkplain AccessFlag
219 * access flags} for the executable represented by this object,
220 * possibly empty}
221 *
222 * @see #getModifiers()
223 * @jvms 4.6 Methods
224 * @since 20
225 */
226 @Override
227 public Set<AccessFlag> accessFlags() {
228 return reflectionFactory.parseAccessFlags(getModifiers(),
229 AccessFlag.Location.METHOD,
230 getDeclaringClass());
231 }
232
233 /**
234 * Returns an array of {@code TypeVariable} objects that represent the
235 * type variables declared by the generic declaration represented by this
236 * {@code GenericDeclaration} object, in declaration order. Returns an
237 * array of length 0 if the underlying generic declaration declares no type
238 * variables.
239 *
240 * @return an array of {@code TypeVariable} objects that represent
241 * the type variables declared by this generic declaration
242 * @throws GenericSignatureFormatError if the generic
243 * signature of this generic declaration does not conform to
244 * the format specified in
245 * <cite>The Java Virtual Machine Specification</cite>
246 */
247 public abstract TypeVariable<?>[] getTypeParameters();
248
249 // returns shared array of parameter types - must never give it out
250 // to the untrusted code...
251 abstract Class<?>[] getSharedParameterTypes();
252
253 // returns shared array of exception types - must never give it out
254 // to the untrusted code...
255 abstract Class<?>[] getSharedExceptionTypes();
256
257 /**
258 * Returns an array of {@code Class} objects that represent the formal
259 * parameter types, in declaration order, of the executable
260 * represented by this object. Returns an array of length
261 * 0 if the underlying executable takes no parameters.
262 * Note that the constructors of some inner classes
263 * may have an {@linkplain java.compiler/javax.lang.model.util.Elements.Origin#MANDATED
264 * implicitly declared} parameter in addition to explicitly
265 * declared ones.
266 * Also note that compact constructors of a record class may have
267 * {@linkplain java.compiler/javax.lang.model.util.Elements.Origin#MANDATED
268 * implicitly declared} parameters.
269 *
270 * @return the parameter types for the executable this object
271 * represents
272 */
273 @SuppressWarnings("doclint:reference") // cross-module links
274 public abstract Class<?>[] getParameterTypes();
275
276 /**
277 * Returns the number of formal parameters (whether explicitly
278 * declared or implicitly declared or neither) for the executable
279 * represented by this object.
280 *
281 * @return The number of formal parameters for the executable this
282 * object represents
283 */
284 public abstract int getParameterCount();
285
286 /**
287 * Returns an array of {@code Type} objects that represent the
288 * formal parameter types, in declaration order, of the executable
289 * represented by this object. An array of length 0 is returned if the
290 * underlying executable takes no parameters. Note that the
291 * constructors of some inner classes may have an implicitly
292 * declared parameter in addition to explicitly declared ones.
293 * Compact constructors of a record class may also have
294 * {@linkplain java.compiler/javax.lang.model.util.Elements.Origin#MANDATED
295 * implicitly declared} parameters,
296 * but they are a special case and thus considered as if they had
297 * been explicitly declared in the source.
298 * Finally note that as a {@link java.lang.reflect##LanguageJvmModel
299 * modeling artifact}, the number of returned parameters can differ
300 * depending on whether or not generic information is present. If
301 * generic information is present, parameters explicitly
302 * present in the source or parameters of compact constructors
303 * of a record class will be returned.
304 * Note that parameters of compact constructors of a record class are a special case,
305 * as they are not explicitly present in the source, and its type will be returned
306 * regardless of the parameters being
307 * {@linkplain java.compiler/javax.lang.model.util.Elements.Origin#MANDATED
308 * implicitly declared} or not.
309 * If generic information is not present, implicit and synthetic parameters may be
310 * returned as well.
311 *
312 * <p>If a formal parameter type is a parameterized type,
313 * the {@code Type} object returned for it must accurately reflect
314 * the actual type arguments used in the source code. This assertion also
315 * applies to the parameters of compact constructors of a record class,
316 * independently of them being
317 * {@linkplain java.compiler/javax.lang.model.util.Elements.Origin#MANDATED
318 * implicitly declared} or not.
319 *
320 * <p>If a formal parameter type is a type variable or a parameterized
321 * type, it is created. Otherwise, it is resolved.
322 *
323 * @return an array of {@code Type}s that represent the formal
324 * parameter types of the underlying executable, in declaration order
325 * @throws GenericSignatureFormatError
326 * if the generic method signature does not conform to the format
327 * specified in
328 * <cite>The Java Virtual Machine Specification</cite>
329 * @throws TypeNotPresentException if any of the parameter
330 * types of the underlying executable refers to a non-existent type
331 * declaration
332 * @throws MalformedParameterizedTypeException if any of
333 * the underlying executable's parameter types refer to a parameterized
334 * type that cannot be instantiated for any reason
335 */
336 @SuppressWarnings("doclint:reference") // cross-module links
337 public Type[] getGenericParameterTypes() {
338 if (hasGenericInformation())
339 return getGenericInfo().getParameterTypes();
340 else
341 return getParameterTypes();
342 }
343
344 /**
345 * Behaves like {@code getGenericParameterTypes}, but returns type
346 * information for all parameters, including synthetic parameters.
347 */
348 Type[] getAllGenericParameterTypes() {
349 final boolean genericInfo = hasGenericInformation();
350
351 // Easy case: we don't have generic parameter information. In
352 // this case, we just return the result of
353 // getParameterTypes().
354 if (!genericInfo) {
355 return getParameterTypes();
356 } else {
357 final boolean realParamData = hasRealParameterData();
358 final Type[] genericParamTypes = getGenericParameterTypes();
359 final Type[] nonGenericParamTypes = getSharedParameterTypes();
360 // If we have real parameter data, then we use the
361 // synthetic and mandate flags to our advantage.
362 if (realParamData) {
363 if (getDeclaringClass().isRecord() && this instanceof Constructor) {
364 /* we could be seeing a compact constructor of a record class
365 * its parameters are mandated but we should be able to retrieve
366 * its generic information if present
367 */
368 if (genericParamTypes.length == nonGenericParamTypes.length) {
369 return genericParamTypes;
370 } else {
371 return nonGenericParamTypes.clone();
372 }
373 } else {
374 final Type[] out = new Type[nonGenericParamTypes.length];
375 final Parameter[] params = getParameters();
376 int fromidx = 0;
377 for (int i = 0; i < out.length; i++) {
378 final Parameter param = params[i];
379 if (param.isSynthetic() || param.isImplicit()) {
380 // If we hit a synthetic or mandated parameter,
381 // use the non generic parameter info.
382 out[i] = nonGenericParamTypes[i];
383 } else {
384 // Otherwise, use the generic parameter info.
385 out[i] = genericParamTypes[fromidx];
386 fromidx++;
387 }
388 }
389 return out;
390 }
391 } else {
392 // Otherwise, use the non-generic parameter data.
393 // Without method parameter reflection data, we have
394 // no way to figure out which parameters are
395 // synthetic/mandated, thus, no way to match up the
396 // indexes.
397 return genericParamTypes.length == nonGenericParamTypes.length ?
398 genericParamTypes : getParameterTypes();
399 }
400 }
401 }
402
403 /**
404 * {@return an array of {@code Parameter} objects representing
405 * all the parameters to the underlying executable represented by
406 * this object} An array of length 0 is returned if the executable
407 * has no parameters.
408 *
409 * <p>The parameters of the underlying executable do not necessarily
410 * have unique names, or names that are legal identifiers in the
411 * Java programming language (JLS {@jls 3.8}).
412 *
413 * @throws MalformedParametersException if the class file contains
414 * a MethodParameters attribute that is improperly formatted.
415 */
416 public Parameter[] getParameters() {
417 // TODO: This may eventually need to be guarded by security
418 // mechanisms similar to those in Field, Method, etc.
419 //
420 // Need to copy the cached array to prevent users from messing
421 // with it. Since parameters are immutable, we can
422 // shallow-copy.
423 return parameterData().parameters.clone();
424 }
425
426 private Parameter[] synthesizeAllParams() {
427 final int realparams = getParameterCount();
428 final Parameter[] out = new Parameter[realparams];
429 for (int i = 0; i < realparams; i++)
430 // TODO: is there a way to synthetically derive the
431 // modifiers? Probably not in the general case, since
432 // we'd have no way of knowing about them, but there
433 // may be specific cases.
434 out[i] = new Parameter(null, 0, this, i);
435 return out;
436 }
437
438 private void verifyParameters(final Parameter[] parameters) {
439 final int mask = Modifier.FINAL | Modifier.SYNTHETIC | Modifier.MANDATED;
440
441 if (getParameterCount() != parameters.length)
442 throw new MalformedParametersException("Wrong number of parameters in MethodParameters attribute");
443
444 for (Parameter parameter : parameters) {
445 final String name = parameter.getRealName();
446 final int mods = parameter.getModifiers();
447
448 if (name != null) {
449 if (name.isEmpty() || name.indexOf('.') != -1 ||
450 name.indexOf(';') != -1 || name.indexOf('[') != -1 ||
451 name.indexOf('/') != -1) {
452 throw new MalformedParametersException("Invalid parameter name \"" + name + "\"");
453 }
454 }
455
456 if (mods != (mods & mask)) {
457 throw new MalformedParametersException("Invalid parameter modifiers");
458 }
459 }
460 }
461
462
463 boolean hasRealParameterData() {
464 return parameterData().isReal;
465 }
466
467 private ParameterData parameterData() {
468 ParameterData parameterData = this.parameterData;
469 if (parameterData != null) {
470 return parameterData;
471 }
472
473 Parameter[] tmp;
474 // Go to the JVM to get them
475 try {
476 tmp = getParameters0();
477 } catch (IllegalArgumentException e) {
478 // Rethrow ClassFormatErrors
479 throw new MalformedParametersException("Invalid constant pool index");
480 }
481
482 // If we get back nothing, then synthesize parameters
483 if (tmp == null) {
484 tmp = synthesizeAllParams();
485 parameterData = new ParameterData(tmp, false);
486 } else {
487 verifyParameters(tmp);
488 parameterData = new ParameterData(tmp, true);
489 }
490 return this.parameterData = parameterData;
491 }
492
493 private transient @Stable ParameterData parameterData;
494
495 record ParameterData(@Stable Parameter[] parameters, boolean isReal) {}
496
497 private native Parameter[] getParameters0();
498 native byte[] getTypeAnnotationBytes0();
499
500 // Needed by reflectaccess
501 byte[] getTypeAnnotationBytes() {
502 return getTypeAnnotationBytes0();
503 }
504
505 /**
506 * Returns an array of {@code Class} objects that represent the
507 * types of exceptions declared to be thrown by the underlying
508 * executable represented by this object. Returns an array of
509 * length 0 if the executable declares no exceptions in its {@code
510 * throws} clause.
511 *
512 * @return the exception types declared as being thrown by the
513 * executable this object represents
514 */
515 public abstract Class<?>[] getExceptionTypes();
516
517 /**
518 * Returns an array of {@code Type} objects that represent the
519 * exceptions declared to be thrown by this executable object.
520 * Returns an array of length 0 if the underlying executable declares
521 * no exceptions in its {@code throws} clause.
522 *
523 * <p>If an exception type is a type variable or a parameterized
524 * type, it is created. Otherwise, it is resolved.
525 *
526 * @return an array of Types that represent the exception types
527 * thrown by the underlying executable
528 * @throws GenericSignatureFormatError
529 * if the generic method signature does not conform to the format
530 * specified in
531 * <cite>The Java Virtual Machine Specification</cite>
532 * @throws TypeNotPresentException if the underlying executable's
533 * {@code throws} clause refers to a non-existent type declaration
534 * @throws MalformedParameterizedTypeException if
535 * the underlying executable's {@code throws} clause refers to a
536 * parameterized type that cannot be instantiated for any reason
537 */
538 public Type[] getGenericExceptionTypes() {
539 Type[] result;
540 if (hasGenericInformation() &&
541 ((result = getGenericInfo().getExceptionTypes()).length > 0))
542 return result;
543 else
544 return getExceptionTypes();
545 }
546
547 /**
548 * {@return a string describing this {@code Executable}, including
549 * any type parameters}
550 */
551 public abstract String toGenericString();
552
553 /**
554 * {@return {@code true} if this executable was declared to take a
555 * variable number of arguments; returns {@code false} otherwise}
556 */
557 public boolean isVarArgs() {
558 return (getModifiers() & Modifier.VARARGS) != 0;
559 }
560
561 /**
562 * Returns {@code true} if this executable is a synthetic
563 * construct; returns {@code false} otherwise.
564 *
565 * @return true if and only if this executable is a synthetic
566 * construct as defined by
567 * <cite>The Java Language Specification</cite>.
568 * @jls 13.1 The Form of a Binary
569 * @jvms 4.6 Methods
570 */
571 public boolean isSynthetic() {
572 return Modifier.isSynthetic(getModifiers());
573 }
574
575 /**
576 * Returns an array of arrays of {@code Annotation}s that
577 * represent the annotations on the formal parameters, in
578 * declaration order, of the {@code Executable} represented by
579 * this object. Synthetic and mandated parameters (see
580 * explanation below), such as the outer "this" parameter to an
581 * inner class constructor will be represented in the returned
582 * array. If the executable has no parameters (meaning no formal,
583 * no synthetic, and no mandated parameters), a zero-length array
584 * will be returned. If the {@code Executable} has one or more
585 * parameters, a nested array of length zero is returned for each
586 * parameter with no annotations. The annotation objects contained
587 * in the returned arrays are serializable. The caller of this
588 * method is free to modify the returned arrays; it will have no
589 * effect on the arrays returned to other callers.
590 *
591 * A compiler may add extra parameters that are implicitly
592 * declared in source ("mandated"), as well as parameters that
593 * are neither implicitly nor explicitly declared in source
594 * ("synthetic") to the parameter list for a method. See {@link
595 * java.lang.reflect.Parameter} for more information.
596 *
597 * <p>Note that any annotations returned by this method are
598 * declaration annotations.
599 *
600 * @see java.lang.reflect.Parameter
601 * @see java.lang.reflect.Parameter#getAnnotations
602 * @return an array of arrays that represent the annotations on
603 * the formal and implicit parameters, in declaration order, of
604 * the executable represented by this object
605 */
606 public abstract Annotation[][] getParameterAnnotations();
607
608 Annotation[][] sharedGetParameterAnnotations(Class<?>[] parameterTypes,
609 byte[] parameterAnnotations) {
610 int numParameters = parameterTypes.length;
611 if (parameterAnnotations == null)
612 return new Annotation[numParameters][0];
613
614 Annotation[][] result = parseParameterAnnotations(parameterAnnotations);
615
616 if (result.length != numParameters &&
617 handleParameterNumberMismatch(result.length, parameterTypes)) {
618 Annotation[][] tmp = new Annotation[numParameters][];
619 // Shift annotations down to account for any implicit leading parameters
620 System.arraycopy(result, 0, tmp, numParameters - result.length, result.length);
621 for (int i = 0; i < numParameters - result.length; i++) {
622 tmp[i] = new Annotation[0];
623 }
624 result = tmp;
625 }
626 return result;
627 }
628
629 abstract boolean handleParameterNumberMismatch(int resultLength, Class<?>[] parameterTypes);
630
631 /**
632 * {@inheritDoc}
633 * @throws NullPointerException {@inheritDoc}
634 */
635 @Override
636 public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
637 Objects.requireNonNull(annotationClass);
638 return annotationClass.cast(declaredAnnotations().get(annotationClass));
639 }
640
641 /**
642 * {@inheritDoc}
643 *
644 * @throws NullPointerException {@inheritDoc}
645 */
646 @Override
647 public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) {
648 Objects.requireNonNull(annotationClass);
649
650 return AnnotationSupport.getDirectlyAndIndirectlyPresent(declaredAnnotations(), annotationClass);
651 }
652
653 /**
654 * {@inheritDoc}
655 */
656 @Override
657 public Annotation[] getDeclaredAnnotations() {
658 return AnnotationParser.toArray(declaredAnnotations());
659 }
660
661 private transient volatile Map<Class<? extends Annotation>, Annotation> declaredAnnotations;
662
663 private Map<Class<? extends Annotation>, Annotation> declaredAnnotations() {
664 Map<Class<? extends Annotation>, Annotation> declAnnos;
665 if ((declAnnos = declaredAnnotations) == null) {
666 synchronized (this) {
667 if ((declAnnos = declaredAnnotations) == null) {
668 Executable root = (Executable)getRoot();
669 if (root != null) {
670 declAnnos = root.declaredAnnotations();
671 } else {
672 declAnnos = AnnotationParser.parseAnnotations(
673 getAnnotationBytes(),
674 SharedSecrets.getJavaLangAccess().
675 getConstantPool(getDeclaringClass()),
676 getDeclaringClass()
677 );
678 }
679 declaredAnnotations = declAnnos;
680 }
681 }
682 }
683 return declAnnos;
684 }
685
686 /**
687 * Returns an {@code AnnotatedType} object that represents the use of a type to
688 * specify the return type of the method/constructor represented by this
689 * Executable.
690 *
691 * If this {@code Executable} object represents a constructor, the {@code
692 * AnnotatedType} object represents the type of the constructed object.
693 *
694 * If this {@code Executable} object represents a method, the {@code
695 * AnnotatedType} object represents the use of a type to specify the return
696 * type of the method.
697 *
698 * @return an object representing the return type of the method
699 * or constructor represented by this {@code Executable}
700 */
701 public abstract AnnotatedType getAnnotatedReturnType();
702
703 /* Helper for subclasses of Executable.
704 *
705 * Returns an AnnotatedType object that represents the use of a type to
706 * specify the return type of the method/constructor represented by this
707 * Executable.
708 */
709 AnnotatedType getAnnotatedReturnType0(Type returnType) {
710 return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(),
711 SharedSecrets.getJavaLangAccess().
712 getConstantPool(getDeclaringClass()),
713 this,
714 getDeclaringClass(),
715 returnType,
716 TypeAnnotation.TypeAnnotationTarget.METHOD_RETURN);
717 }
718
719 /**
720 * Returns an {@code AnnotatedType} object that represents the use of a
721 * type to specify the receiver type of the method/constructor represented
722 * by this {@code Executable} object.
723 *
724 * The receiver type of a method/constructor is available only if the
725 * method/constructor has a receiver parameter (JLS {@jls 8.4.1}). If this {@code
726 * Executable} object <em>represents an instance method or represents a
727 * constructor of an inner member class</em>, and the
728 * method/constructor <em>either</em> has no receiver parameter or has a
729 * receiver parameter with no annotations on its type, then the return
730 * value is an {@code AnnotatedType} object representing an element with no
731 * annotations.
732 *
733 * If this {@code Executable} object represents a static method or
734 * represents a constructor of a top level, static member, local, or
735 * anonymous class, then the return value is null.
736 *
737 * @return an object representing the receiver type of the method or
738 * constructor represented by this {@code Executable} or {@code null} if
739 * this {@code Executable} can not have a receiver parameter
740 *
741 * @jls 8.4 Method Declarations
742 * @jls 8.4.1 Formal Parameters
743 * @jls 8.8 Constructor Declarations
744 */
745 public AnnotatedType getAnnotatedReceiverType() {
746 if (Modifier.isStatic(this.getModifiers()))
747 return null;
748 return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(),
749 SharedSecrets.getJavaLangAccess().
750 getConstantPool(getDeclaringClass()),
751 this,
752 getDeclaringClass(),
753 parameterize(getDeclaringClass()),
754 TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER);
755 }
756
757 Type parameterize(Class<?> c) {
758 Class<?> ownerClass = c.getDeclaringClass();
759 TypeVariable<?>[] typeVars = c.getTypeParameters();
760
761 // base case, static nested classes, according to JLS 8.1.3, has no
762 // enclosing instance, therefore its owner is not generified.
763 if (ownerClass == null || Modifier.isStatic(c.getModifiers())) {
764 if (typeVars.length == 0)
765 return c;
766 else
767 return ParameterizedTypeImpl.make(c, typeVars, null);
768 }
769
770 // Resolve owner
771 Type ownerType = parameterize(ownerClass);
772 if (ownerType instanceof Class<?> && typeVars.length == 0) // We have yet to encounter type parameters
773 return c;
774 else
775 return ParameterizedTypeImpl.make(c, typeVars, ownerType);
776 }
777
778 /**
779 * Returns an array of {@code AnnotatedType} objects that represent the use
780 * of types to specify formal parameter types of the method/constructor
781 * represented by this Executable. The order of the objects in the array
782 * corresponds to the order of the formal parameter types in the
783 * declaration of the method/constructor.
784 *
785 * Returns an array of length 0 if the method/constructor declares no
786 * parameters.
787 * Note that the constructors of some inner classes
788 * may have an
789 * {@linkplain java.compiler/javax.lang.model.util.Elements.Origin#MANDATED
790 * implicitly declared} parameter in addition to explicitly declared ones.
791 * Also note that compact constructors of a record class may have
792 * {@linkplain java.compiler/javax.lang.model.util.Elements.Origin#MANDATED
793 * implicitly declared} parameters.
794 *
795 * @return an array of objects representing the types of the
796 * formal parameters of the method or constructor represented by this
797 * {@code Executable}
798 */
799 @SuppressWarnings("doclint:reference") // cross-module links
800 public AnnotatedType[] getAnnotatedParameterTypes() {
801 return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes0(),
802 SharedSecrets.getJavaLangAccess().
803 getConstantPool(getDeclaringClass()),
804 this,
805 getDeclaringClass(),
806 getAllGenericParameterTypes(),
807 TypeAnnotation.TypeAnnotationTarget.METHOD_FORMAL_PARAMETER);
808 }
809
810 /**
811 * Returns an array of {@code AnnotatedType} objects that represent the use
812 * of types to specify the declared exceptions of the method/constructor
813 * represented by this Executable. The order of the objects in the array
814 * corresponds to the order of the exception types in the declaration of
815 * the method/constructor.
816 *
817 * Returns an array of length 0 if the method/constructor declares no
818 * exceptions.
819 *
820 * @return an array of objects representing the declared
821 * exceptions of the method or constructor represented by this {@code
822 * Executable}
823 */
824 public AnnotatedType[] getAnnotatedExceptionTypes() {
825 return TypeAnnotationParser.buildAnnotatedTypes(getTypeAnnotationBytes0(),
826 SharedSecrets.getJavaLangAccess().
827 getConstantPool(getDeclaringClass()),
828 this,
829 getDeclaringClass(),
830 getGenericExceptionTypes(),
831 TypeAnnotation.TypeAnnotationTarget.THROWS);
832 }
833 }