src/share/classes/java/lang/reflect/Method.java

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 1996, 2006, 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 --- 1,7 ---- /* ! * Copyright (c) 1996, 2011, 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
*** 34,44 **** import sun.reflect.annotation.AnnotationType; import sun.reflect.annotation.AnnotationParser; import java.lang.annotation.Annotation; import java.lang.annotation.AnnotationFormatError; import java.nio.ByteBuffer; - import java.util.Map; /** * A {@code Method} provides information about, and access to, a single method * on a class or interface. The reflected method may be a class method * or an instance method (including an abstract method). --- 34,43 ----
*** 56,68 **** * @see java.lang.Class#getDeclaredMethod(String, Class[]) * * @author Kenneth Russell * @author Nakul Saraiya */ ! public final ! class Method extends AccessibleObject implements GenericDeclaration, ! Member { private Class<?> clazz; private int slot; // This is guaranteed to be interned by the VM in the 1.4 // reflection implementation private String name; --- 55,65 ---- * @see java.lang.Class#getDeclaredMethod(String, Class[]) * * @author Kenneth Russell * @author Nakul Saraiya */ ! public final class Method extends Executable { private Class<?> clazz; private int slot; // This is guaranteed to be interned by the VM in the 1.4 // reflection implementation private String name;
*** 81,102 **** // For sharing of MethodAccessors. This branching structure is // currently only two levels deep (i.e., one root Method and // potentially many Method objects pointing to it.) private Method root; - // Generics infrastructure private String getGenericSignature() {return signature;} // Accessor for factory private GenericsFactory getFactory() { // create scope and factory return CoreReflectionFactory.make(this, MethodScope.make(this)); } // Accessor for generic info repository ! private MethodRepository getGenericInfo() { // lazily initialize repository if necessary if (genericInfo == null) { // create and cache generic info repository genericInfo = MethodRepository.make(getGenericSignature(), getFactory()); --- 78,100 ---- // For sharing of MethodAccessors. This branching structure is // currently only two levels deep (i.e., one root Method and // potentially many Method objects pointing to it.) private Method root; + // Generics infrastructure private String getGenericSignature() {return signature;} // Accessor for factory private GenericsFactory getFactory() { // create scope and factory return CoreReflectionFactory.make(this, MethodScope.make(this)); } // Accessor for generic info repository ! @Override ! MethodRepository getGenericInfo() { // lazily initialize repository if necessary if (genericInfo == null) { // create and cache generic info repository genericInfo = MethodRepository.make(getGenericSignature(), getFactory());
*** 117,128 **** int modifiers, int slot, String signature, byte[] annotations, byte[] parameterAnnotations, ! byte[] annotationDefault) ! { this.clazz = declaringClass; this.name = name; this.parameterTypes = parameterTypes; this.returnType = returnType; this.exceptionTypes = checkedExceptions; --- 115,125 ---- int modifiers, int slot, String signature, byte[] annotations, byte[] parameterAnnotations, ! byte[] annotationDefault) { this.clazz = declaringClass; this.name = name; this.parameterTypes = parameterTypes; this.returnType = returnType; this.exceptionTypes = checkedExceptions;
*** 154,205 **** // Might as well eagerly propagate this if already present res.methodAccessor = methodAccessor; return res; } /** ! * Returns the {@code Class} object representing the class or interface ! * that declares the method represented by this {@code Method} object. */ public Class<?> getDeclaringClass() { return clazz; } /** * Returns the name of the method represented by this {@code Method} * object, as a {@code String}. */ public String getName() { return name; } /** ! * Returns the Java language modifiers for the method represented ! * by this {@code Method} object, as an integer. The {@code Modifier} class should ! * be used to decode the modifiers. ! * ! * @see Modifier */ public int getModifiers() { return modifiers; } /** ! * Returns an array of {@code TypeVariable} objects that represent the ! * type variables declared by the generic declaration represented by this ! * {@code GenericDeclaration} object, in declaration order. Returns an ! * array of length 0 if the underlying generic declaration declares no type ! * variables. ! * ! * @return an array of {@code TypeVariable} objects that represent ! * the type variables declared by this generic declaration ! * @throws GenericSignatureFormatError if the generic ! * signature of this generic declaration does not conform to ! * the format specified in ! * <cite>The Java&trade; Virtual Machine Specification</cite> * @since 1.5 */ public TypeVariable<Method>[] getTypeParameters() { if (getGenericSignature() != null) return (TypeVariable<Method>[])getGenericInfo().getTypeParameters(); else return (TypeVariable<Method>[])new TypeVariable[0]; --- 151,201 ---- // Might as well eagerly propagate this if already present res.methodAccessor = methodAccessor; return res; } + @Override + boolean hasGenericInformation() { + return (getGenericSignature() != null); + } + + @Override + byte[] getAnnotationBytes() { + return annotations; + } + /** ! * {@inheritDoc} */ + @Override public Class<?> getDeclaringClass() { return clazz; } /** * Returns the name of the method represented by this {@code Method} * object, as a {@code String}. */ + @Override public String getName() { return name; } /** ! * {@inheritDoc} */ + @Override public int getModifiers() { return modifiers; } /** ! * {@inheritDoc} ! * @throws GenericSignatureFormatError {@inheritDoc} * @since 1.5 */ + @Override public TypeVariable<Method>[] getTypeParameters() { if (getGenericSignature() != null) return (TypeVariable<Method>[])getGenericInfo().getTypeParameters(); else return (TypeVariable<Method>[])new TypeVariable[0];
*** 243,344 **** if (getGenericSignature() != null) { return getGenericInfo().getReturnType(); } else { return getReturnType();} } - /** ! * Returns an array of {@code Class} objects that represent the formal ! * parameter types, in declaration order, of the method ! * represented by this {@code Method} object. Returns an array of length ! * 0 if the underlying method takes no parameters. ! * ! * @return the parameter types for the method this object ! * represents */ public Class<?>[] getParameterTypes() { return (Class<?>[]) parameterTypes.clone(); } /** ! * Returns an array of {@code Type} objects that represent the formal ! * parameter types, in declaration order, of the method represented by ! * this {@code Method} object. Returns an array of length 0 if the ! * underlying method takes no parameters. ! * ! * <p>If a formal parameter type is a parameterized type, ! * the {@code Type} object returned for it must accurately reflect ! * the actual type parameters used in the source code. ! * ! * <p>If a formal parameter type is a type variable or a parameterized ! * type, it is created. Otherwise, it is resolved. ! * ! * @return an array of Types that represent the formal ! * parameter types of the underlying method, in declaration order ! * @throws GenericSignatureFormatError ! * if the generic method signature does not conform to the format ! * specified in ! * <cite>The Java&trade; Virtual Machine Specification</cite> ! * @throws TypeNotPresentException if any of the parameter ! * types of the underlying method refers to a non-existent type ! * declaration ! * @throws MalformedParameterizedTypeException if any of ! * the underlying method's parameter types refer to a parameterized ! * type that cannot be instantiated for any reason * @since 1.5 */ public Type[] getGenericParameterTypes() { ! if (getGenericSignature() != null) ! return getGenericInfo().getParameterTypes(); ! else ! return getParameterTypes(); } - /** ! * Returns an array of {@code Class} objects that represent ! * the types of the exceptions declared to be thrown ! * by the underlying method ! * represented by this {@code Method} object. Returns an array of length ! * 0 if the method declares no exceptions in its {@code throws} clause. ! * ! * @return the exception types declared as being thrown by the ! * method this object represents */ public Class<?>[] getExceptionTypes() { return (Class<?>[]) exceptionTypes.clone(); } /** ! * Returns an array of {@code Type} objects that represent the ! * exceptions declared to be thrown by this {@code Method} object. ! * Returns an array of length 0 if the underlying method declares ! * no exceptions in its {@code throws} clause. ! * ! * <p>If an exception type is a type variable or a parameterized ! * type, it is created. Otherwise, it is resolved. ! * ! * @return an array of Types that represent the exception types ! * thrown by the underlying method ! * @throws GenericSignatureFormatError ! * if the generic method signature does not conform to the format ! * specified in ! * <cite>The Java&trade; Virtual Machine Specification</cite> ! * @throws TypeNotPresentException if the underlying method's ! * {@code throws} clause refers to a non-existent type declaration ! * @throws MalformedParameterizedTypeException if ! * the underlying method's {@code throws} clause refers to a ! * parameterized type that cannot be instantiated for any reason * @since 1.5 */ public Type[] getGenericExceptionTypes() { ! Type[] result; ! if (getGenericSignature() != null && ! ((result = getGenericInfo().getExceptionTypes()).length > 0)) ! return result; ! else ! return getExceptionTypes(); } /** * Compares this {@code Method} against the specified object. Returns * true if the objects are the same. Two {@code Methods} are the same if --- 239,286 ---- if (getGenericSignature() != null) { return getGenericInfo().getReturnType(); } else { return getReturnType();} } /** ! * {@inheritDoc} */ + @Override public Class<?>[] getParameterTypes() { return (Class<?>[]) parameterTypes.clone(); } /** ! * {@inheritDoc} ! * @throws GenericSignatureFormatError {@inheritDoc} ! * @throws TypeNotPresentException {@inheritDoc} ! * @throws MalformedParameterizedTypeException {@inheritDoc} * @since 1.5 */ + @Override public Type[] getGenericParameterTypes() { ! return super.getGenericParameterTypes(); } /** ! * {@inheritDoc} */ + @Override public Class<?>[] getExceptionTypes() { return (Class<?>[]) exceptionTypes.clone(); } /** ! * {@inheritDoc} ! * @throws GenericSignatureFormatError {@inheritDoc} ! * @throws TypeNotPresentException {@inheritDoc} ! * @throws MalformedParameterizedTypeException {@inheritDoc} * @since 1.5 */ + @Override public Type[] getGenericExceptionTypes() { ! return super.getGenericExceptionTypes(); } /** * Compares this {@code Method} against the specified object. Returns * true if the objects are the same. Two {@code Methods} are the same if
*** 350,369 **** Method other = (Method)obj; if ((getDeclaringClass() == other.getDeclaringClass()) && (getName() == other.getName())) { if (!returnType.equals(other.getReturnType())) return false; ! /* Avoid unnecessary cloning */ ! Class<?>[] params1 = parameterTypes; ! Class<?>[] params2 = other.parameterTypes; ! if (params1.length == params2.length) { ! for (int i = 0; i < params1.length; i++) { ! if (params1[i] != params2[i]) ! return false; ! } ! return true; ! } } } return false; } --- 292,302 ---- Method other = (Method)obj; if ((getDeclaringClass() == other.getDeclaringClass()) && (getName() == other.getName())) { if (!returnType.equals(other.getReturnType())) return false; ! return equalParamTypes(parameterTypes, other.parameterTypes); } } return false; }
*** 397,435 **** * and then other modifiers in the following order: * {@code abstract}, {@code static}, {@code final}, * {@code synchronized}, {@code native}, {@code strictfp}. */ public String toString() { ! try { ! StringBuilder sb = new StringBuilder(); ! int mod = getModifiers() & Modifier.methodModifiers(); ! if (mod != 0) { ! sb.append(Modifier.toString(mod)).append(' '); } sb.append(Field.getTypeName(getReturnType())).append(' '); sb.append(Field.getTypeName(getDeclaringClass())).append('.'); ! sb.append(getName()).append('('); ! Class<?>[] params = parameterTypes; // avoid clone ! for (int j = 0; j < params.length; j++) { ! sb.append(Field.getTypeName(params[j])); ! if (j < (params.length - 1)) ! sb.append(','); ! } ! sb.append(')'); ! Class<?>[] exceptions = exceptionTypes; // avoid clone ! if (exceptions.length > 0) { ! sb.append(" throws "); ! for (int k = 0; k < exceptions.length; k++) { ! sb.append(exceptions[k].getName()); ! if (k < (exceptions.length - 1)) ! sb.append(','); ! } ! } ! return sb.toString(); ! } catch (Exception e) { ! return "<" + e + ">"; ! } } /** * Returns a string describing this {@code Method}, including * type parameters. The string is formatted as the method access --- 330,349 ---- * and then other modifiers in the following order: * {@code abstract}, {@code static}, {@code final}, * {@code synchronized}, {@code native}, {@code strictfp}. */ public String toString() { ! return sharedToString(Modifier.methodModifiers(), ! parameterTypes, ! exceptionTypes); } + + @Override + void specificToStringHeader(StringBuilder sb) { sb.append(Field.getTypeName(getReturnType())).append(' '); sb.append(Field.getTypeName(getDeclaringClass())).append('.'); ! sb.append(getName()); } /** * Returns a string describing this {@code Method}, including * type parameters. The string is formatted as the method access
*** 466,531 **** * @return a string describing this {@code Method}, * include type parameters * * @since 1.5 */ public String toGenericString() { ! try { ! StringBuilder sb = new StringBuilder(); ! int mod = getModifiers() & Modifier.methodModifiers(); ! if (mod != 0) { ! sb.append(Modifier.toString(mod)).append(' '); ! } ! TypeVariable<?>[] typeparms = getTypeParameters(); ! if (typeparms.length > 0) { ! boolean first = true; ! sb.append('<'); ! for(TypeVariable<?> typeparm: typeparms) { ! if (!first) ! sb.append(','); ! // Class objects can't occur here; no need to test ! // and call Class.getName(). ! sb.append(typeparm.toString()); ! first = false; ! } ! sb.append("> "); } Type genRetType = getGenericReturnType(); sb.append( ((genRetType instanceof Class<?>)? Field.getTypeName((Class<?>)genRetType):genRetType.toString())) .append(' '); sb.append(Field.getTypeName(getDeclaringClass())).append('.'); ! sb.append(getName()).append('('); ! Type[] params = getGenericParameterTypes(); ! for (int j = 0; j < params.length; j++) { ! String param = (params[j] instanceof Class)? ! Field.getTypeName((Class)params[j]): ! (params[j].toString()); ! if (isVarArgs() && (j == params.length - 1)) // replace T[] with T... ! param = param.replaceFirst("\\[\\]$", "..."); ! sb.append(param); ! if (j < (params.length - 1)) ! sb.append(','); ! } ! sb.append(')'); ! Type[] exceptions = getGenericExceptionTypes(); ! if (exceptions.length > 0) { ! sb.append(" throws "); ! for (int k = 0; k < exceptions.length; k++) { ! sb.append((exceptions[k] instanceof Class)? ! ((Class)exceptions[k]).getName(): ! exceptions[k].toString()); ! if (k < (exceptions.length - 1)) ! sb.append(','); ! } ! } ! return sb.toString(); ! } catch (Exception e) { ! return "<" + e + ">"; ! } } /** * Invokes the underlying method represented by this {@code Method} * object, on the specified object with the specified parameters. --- 380,403 ---- * @return a string describing this {@code Method}, * include type parameters * * @since 1.5 */ + @Override public String toGenericString() { ! return sharedToGenericString(Modifier.methodModifiers()); } + @Override + void specificToGenericStringHeader(StringBuilder sb) { Type genRetType = getGenericReturnType(); sb.append( ((genRetType instanceof Class<?>)? Field.getTypeName((Class<?>)genRetType):genRetType.toString())) .append(' '); sb.append(Field.getTypeName(getDeclaringClass())).append('.'); ! sb.append(getName()); } /** * Invokes the underlying method represented by this {@code Method} * object, on the specified object with the specified parameters.
*** 612,643 **** public boolean isBridge() { return (getModifiers() & Modifier.BRIDGE) != 0; } /** ! * Returns {@code true} if this method was declared to take ! * a variable number of arguments; returns {@code false} ! * otherwise. ! * ! * @return {@code true} if an only if this method was declared to ! * take a variable number of arguments. * @since 1.5 */ public boolean isVarArgs() { ! return (getModifiers() & Modifier.VARARGS) != 0; } /** ! * Returns {@code true} if this method is a synthetic ! * method; returns {@code false} otherwise. ! * ! * @return true if and only if this method is a synthetic ! * method as defined by the Java Language Specification. * @since 1.5 */ public boolean isSynthetic() { ! return Modifier.isSynthetic(getModifiers()); } // NOTE that there is no synchronization used here. It is correct // (though not efficient) to generate more than one MethodAccessor // for a given Method. However, avoiding synchronization will --- 484,508 ---- public boolean isBridge() { return (getModifiers() & Modifier.BRIDGE) != 0; } /** ! * {@inheritDoc} * @since 1.5 */ + @Override public boolean isVarArgs() { ! return super.isVarArgs(); } /** ! * {@inheritDoc} * @since 1.5 */ + @Override public boolean isSynthetic() { ! return super.isSynthetic(); } // NOTE that there is no synchronization used here. It is correct // (though not efficient) to generate more than one MethodAccessor // for a given Method. However, avoiding synchronization will
*** 673,712 **** root.setMethodAccessor(accessor); } } /** - * @throws NullPointerException {@inheritDoc} - * @since 1.5 - */ - public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { - if (annotationClass == null) - throw new NullPointerException(); - - return (T) declaredAnnotations().get(annotationClass); - } - - /** - * @since 1.5 - */ - public Annotation[] getDeclaredAnnotations() { - return AnnotationParser.toArray(declaredAnnotations()); - } - - private transient Map<Class<? extends Annotation>, Annotation> declaredAnnotations; - - private synchronized Map<Class<? extends Annotation>, Annotation> declaredAnnotations() { - if (declaredAnnotations == null) { - declaredAnnotations = AnnotationParser.parseAnnotations( - annotations, sun.misc.SharedSecrets.getJavaLangAccess(). - getConstantPool(getDeclaringClass()), - getDeclaringClass()); - } - return declaredAnnotations; - } - - /** * Returns the default value for the annotation member represented by * this {@code Method} instance. If the member is of a primitive type, * an instance of the corresponding wrapper type is returned. Returns * null if no default is associated with the member, or if the method * instance does not represent a declared member of an annotation type. --- 538,547 ----
*** 732,767 **** throw new AnnotationFormatError("Invalid default: " + this); return result; } /** ! * Returns an array of arrays that represent the annotations on the formal ! * parameters, in declaration order, of the method represented by ! * this {@code Method} object. (Returns an array of length zero if the ! * underlying method is parameterless. If the method has one or more ! * parameters, a nested array of length zero is returned for each parameter ! * with no annotations.) The annotation objects contained in the returned ! * arrays are serializable. The caller of this method is free to modify ! * the returned arrays; it will have no effect on the arrays returned to ! * other callers. ! * ! * @return an array of arrays that represent the annotations on the formal ! * parameters, in declaration order, of the method represented by this ! * Method object * @since 1.5 */ public Annotation[][] getParameterAnnotations() { ! int numParameters = parameterTypes.length; ! if (parameterAnnotations == null) ! return new Annotation[numParameters][0]; ! Annotation[][] result = AnnotationParser.parseParameterAnnotations( ! parameterAnnotations, ! sun.misc.SharedSecrets.getJavaLangAccess(). ! getConstantPool(getDeclaringClass()), ! getDeclaringClass()); ! if (result.length != numParameters) ! throw new java.lang.annotation.AnnotationFormatError( ! "Parameter annotations don't match number of parameters"); ! return result; } } --- 567,601 ---- throw new AnnotationFormatError("Invalid default: " + this); return result; } /** ! * {@inheritDoc} ! * @throws NullPointerException {@inheritDoc} ! * @since 1.5 ! */ ! public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { ! return super.getAnnotation(annotationClass); ! } ! ! /** ! * {@inheritDoc} ! * @since 1.5 ! */ ! public Annotation[] getDeclaredAnnotations() { ! return super.getDeclaredAnnotations(); ! } ! ! /** ! * {@inheritDoc} * @since 1.5 */ + @Override public Annotation[][] getParameterAnnotations() { ! return sharedGetParameterAnnotations(parameterTypes, parameterAnnotations); ! } ! @Override ! void handleParameterNumberMismatch(int resultLength, int numParameters) { ! throw new AnnotationFormatError("Parameter annotations don't match number of parameters"); } }