/*
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package java.lang.reflect;

import jdk.internal.access.SharedSecrets;
import sun.reflect.annotation.AnnotationParser;
import sun.reflect.annotation.TypeAnnotation;
import sun.reflect.annotation.TypeAnnotationParser;
import sun.reflect.generics.factory.CoreReflectionFactory;
import sun.reflect.generics.factory.GenericsFactory;
import sun.reflect.generics.repository.FieldRepository;
import sun.reflect.generics.scope.ClassScope;
import java.lang.annotation.Annotation;
import java.util.Map;
import java.util.Objects;

{@preview Associated with records, a preview feature of the Java language. This class is associated with records, a preview feature of the Java language. Preview features may be removed in a future release, or upgraded to permanent features of the Java language.} A RecordComponent provides information about, and dynamic access to, a component of a record class.
See Also:
@jls8.10 Record Types
Since:14
/** * {@preview Associated with records, a preview feature of the Java language. * * This class is associated with <i>records</i>, a preview * feature of the Java language. Preview features * may be removed in a future release, or upgraded to permanent * features of the Java language.} * * A {@code RecordComponent} provides information about, and dynamic access to, a * component of a record class. * * @see Class#getRecordComponents() * @see java.lang.Record * @jls 8.10 Record Types * @since 14 */
@jdk.internal.PreviewFeature(feature=jdk.internal.PreviewFeature.Feature.RECORDS, essentialAPI=false) public final class RecordComponent implements AnnotatedElement { // declaring class private Class<?> clazz; private String name; private Class<?> type; private Method accessor; private String signature; // generic info repository; lazily initialized private transient FieldRepository genericInfo; private byte[] annotations; private byte[] typeAnnotations; @SuppressWarnings("preview") private RecordComponent root; // only the JVM can create record components private RecordComponent() {}
Returns the name of this record component.
Returns:the name of this record component
/** * Returns the name of this record component. * * @return the name of this record component */
public String getName() { return name; }
Returns a Class that identifies the declared type for this record component.
Returns:a Class identifying the declared type of the component represented by this record component
/** * Returns a {@code Class} that identifies the declared type for this * record component. * * @return a {@code Class} identifying the declared type of the component * represented by this record component */
public Class<?> getType() { return type; }
Returns a String that describes the generic type signature for this record component.
Returns:a String that describes the generic type signature for this record component
@jvms4.7.9.1 Signatures
/** * Returns a {@code String} that describes the generic type signature for * this record component. * * @return a {@code String} that describes the generic type signature for * this record component * * @jvms 4.7.9.1 Signatures */
public String getGenericSignature() { return signature; }
Returns a Type object that represents the declared type for this record component.

If the declared type of the record component is a parameterized type, the Type object returned reflects the actual type arguments used in the source code.

If the type of the underlying record component is a type variable or a parameterized type, it is created. Otherwise, it is resolved.

Throws:
  • GenericSignatureFormatError – if the generic record component signature does not conform to the format specified in The Java™ Virtual Machine Specification
  • TypeNotPresentException – if the generic type signature of the underlying record component refers to a non-existent type declaration
  • MalformedParameterizedTypeException – if the generic signature of the underlying record component refers to a parameterized type that cannot be instantiated for any reason
Returns:a Type object that represents the declared type for this record component
/** * Returns a {@code Type} object that represents the declared type for * this record component. * * <p>If the declared type of the record component is a parameterized type, * the {@code Type} object returned reflects the actual type arguments used * in the source code. * * <p>If the type of the underlying record component is a type variable or a * parameterized type, it is created. Otherwise, it is resolved. * * @return a {@code Type} object that represents the declared type for * this record component * @throws GenericSignatureFormatError if the generic record component * signature does not conform to the format specified in * <cite>The Java&trade; Virtual Machine Specification</cite> * @throws TypeNotPresentException if the generic type * signature of the underlying record component refers to a non-existent * type declaration * @throws MalformedParameterizedTypeException if the generic * signature of the underlying record component refers to a parameterized * type that cannot be instantiated for any reason */
public Type getGenericType() { if (getGenericSignature() != null) return getGenericInfo().getGenericType(); else return getType(); } // Accessor for generic info repository private FieldRepository getGenericInfo() { // lazily initialize repository if necessary if (genericInfo == null) { // create and cache generic info repository genericInfo = FieldRepository.make(getGenericSignature(), getFactory()); } return genericInfo; //return cached repository } // Accessor for factory private GenericsFactory getFactory() { Class<?> c = getDeclaringRecord(); // create scope and factory return CoreReflectionFactory.make(c, ClassScope.make(c)); }
Returns an AnnotatedType object that represents the use of a type to specify the declared type of this record component.
Returns:an object representing the declared type of this record component
/** * Returns an {@code AnnotatedType} object that represents the use of a type to specify * the declared type of this record component. * * @return an object representing the declared type of this record component */
public AnnotatedType getAnnotatedType() { return TypeAnnotationParser.buildAnnotatedType(typeAnnotations, SharedSecrets.getJavaLangAccess(). getConstantPool(getDeclaringRecord()), this, getDeclaringRecord(), getGenericType(), TypeAnnotation.TypeAnnotationTarget.FIELD); }
Returns a Method that represents the accessor for this record component.
Returns:a Method that represents the accessor for this record component
/** * Returns a {@code Method} that represents the accessor for this record * component. * * @return a {@code Method} that represents the accessor for this record * component */
public Method getAccessor() { return accessor; }
Throws:
  • NullPointerException – {@inheritDoc}
/** * @throws NullPointerException {@inheritDoc} */
@Override public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { Objects.requireNonNull(annotationClass); return annotationClass.cast(declaredAnnotations().get(annotationClass)); } private transient volatile Map<Class<? extends Annotation>, Annotation> declaredAnnotations; private Map<Class<? extends Annotation>, Annotation> declaredAnnotations() { Map<Class<? extends Annotation>, Annotation> declAnnos; if ((declAnnos = declaredAnnotations) == null) { synchronized (this) { if ((declAnnos = declaredAnnotations) == null) { @SuppressWarnings("preview") RecordComponent root = this.root; if (root != null) { declAnnos = root.declaredAnnotations(); } else { declAnnos = AnnotationParser.parseAnnotations( annotations, SharedSecrets.getJavaLangAccess() .getConstantPool(getDeclaringRecord()), getDeclaringRecord()); } declaredAnnotations = declAnnos; } } } return declAnnos; }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public Annotation[] getAnnotations() { return getDeclaredAnnotations(); }
{@inheritDoc}
/** * {@inheritDoc} */
@Override public Annotation[] getDeclaredAnnotations() { return AnnotationParser.toArray(declaredAnnotations()); }
Returns a string describing this record component. The format is the record component type, followed by a space, followed by the name of the record component. For example:
   String name
   int age
Returns:a string describing this record component
/** * Returns a string describing this record component. The format is * the record component type, followed by a space, followed by the name * of the record component. * For example: * <pre> * String name * int age * </pre> * * @return a string describing this record component */
public String toString() { return (getType().getTypeName() + " " + getName()); }
Returns the record class which declares this record component.
Returns:The record class declaring this record component.
/** * Returns the record class which declares this record component. * * @return The record class declaring this record component. */
public Class<?> getDeclaringRecord() { return clazz; } }