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