< prev index next >

src/java.base/share/classes/java/lang/Class.java

Print this page

        

*** 24,35 **** */ package java.lang; import java.lang.annotation.Annotation; - import java.lang.module.ModuleDescriptor.Version; - import java.lang.module.ModuleFinder; import java.lang.module.ModuleReader; import java.lang.ref.SoftReference; import java.io.IOException; import java.io.InputStream; import java.io.ObjectStreamField; --- 24,33 ----
*** 40,50 **** import java.lang.reflect.Executable; import java.lang.reflect.Field; import java.lang.reflect.GenericArrayType; import java.lang.reflect.GenericDeclaration; import java.lang.reflect.InvocationTargetException; - import java.lang.reflect.Layer; import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Module; import java.lang.reflect.Proxy; --- 38,47 ----
*** 52,82 **** import java.lang.reflect.TypeVariable; import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; - import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; - import java.util.Optional; import java.util.Set; import java.util.StringJoiner; - import java.util.stream.Collectors; import jdk.internal.HotSpotIntrinsicCandidate; import jdk.internal.loader.BootLoader; import jdk.internal.loader.BuiltinClassLoader; import jdk.internal.loader.ResourceHelper; - import jdk.internal.misc.SharedSecrets; import jdk.internal.misc.Unsafe; import jdk.internal.misc.VM; - import jdk.internal.module.ModuleHashes; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.ConstantPool; import jdk.internal.reflect.Reflection; import jdk.internal.reflect.ReflectionFactory; import jdk.internal.vm.annotation.ForceInline; --- 49,74 ----
*** 530,540 **** "Can not call newInstance() on the Class for java.lang.Class" ); } try { Class<?>[] empty = {}; ! final Constructor<T> c = getConstructor0(empty, Member.DECLARED); // Disable accessibility checks on the constructor // since we have to do the security check here anyway // (the stack depth is wrong for the Constructor's // security check to work) java.security.AccessController.doPrivileged( --- 522,533 ---- "Can not call newInstance() on the Class for java.lang.Class" ); } try { Class<?>[] empty = {}; ! final Constructor<T> c = getReflectionFactory().copyConstructor( ! getConstructor0(empty, Member.DECLARED)); // Disable accessibility checks on the constructor // since we have to do the security check here anyway // (the stack depth is wrong for the Constructor's // security check to work) java.security.AccessController.doPrivileged(
*** 1022,1043 **** * returned in that order. * * @return an array of interfaces directly implemented by this class */ public Class<?>[] getInterfaces() { ReflectionData<T> rd = reflectionData(); if (rd == null) { // no cloning required return getInterfaces0(); } else { Class<?>[] interfaces = rd.interfaces; if (interfaces == null) { interfaces = getInterfaces0(); rd.interfaces = interfaces; } ! // defensively copy before handing over to user code ! return interfaces.clone(); } } private native Class<?>[] getInterfaces0(); --- 1015,1041 ---- * returned in that order. * * @return an array of interfaces directly implemented by this class */ public Class<?>[] getInterfaces() { + // defensively copy before handing over to user code + return getInterfaces(true); + } + + private Class<?>[] getInterfaces(boolean cloneArray) { ReflectionData<T> rd = reflectionData(); if (rd == null) { // no cloning required return getInterfaces0(); } else { Class<?>[] interfaces = rd.interfaces; if (interfaces == null) { interfaces = getInterfaces0(); rd.interfaces = interfaces; } ! // defensively copy if requested ! return cloneArray ? interfaces.clone() : interfaces; } } private native Class<?>[] getInterfaces0();
*** 1765,1783 **** * Returns an array containing {@code Method} objects reflecting all the * public methods of the class or interface represented by this {@code * Class} object, including those declared by the class or interface and * those inherited from superclasses and superinterfaces. * - * <p> If this {@code Class} object represents a type that has multiple - * public methods with the same name and parameter types, but different - * return types, then the returned array has a {@code Method} object for - * each such method. - * - * <p> If this {@code Class} object represents a type with a class - * initialization method {@code <clinit>}, then the returned array does - * <em>not</em> have a corresponding {@code Method} object. - * * <p> If this {@code Class} object represents an array type, then the * returned array has a {@code Method} object for each of the public * methods inherited by the array type from {@code Object}. It does not * contain a {@code Method} object for {@code clone()}. * --- 1763,1772 ----
*** 1786,1801 **** * {@code Object}. Therefore, if no methods are explicitly declared in * this interface or any of its superinterfaces then the returned array * has length 0. (Note that a {@code Class} object which represents a class * always has public methods, inherited from {@code Object}.) * ! * <p> If this {@code Class} object represents a primitive type or void, ! * then the returned array has length 0. * ! * <p> Static methods declared in superinterfaces of the class or interface ! * represented by this {@code Class} object are not considered members of ! * the class or interface. * * <p> The elements in the returned array are not sorted and are not in any * particular order. * * @return the array of {@code Method} objects representing the --- 1775,1828 ---- * {@code Object}. Therefore, if no methods are explicitly declared in * this interface or any of its superinterfaces then the returned array * has length 0. (Note that a {@code Class} object which represents a class * always has public methods, inherited from {@code Object}.) * ! * <p> The returned array never contains methods with names "{@code <init>}" ! * or "{@code <clinit>}". * ! * <p> Generally, the result is computed as with the following 4 step algorithm. ! * Let C be the class or interface represented by this {@code Class} object: ! * <ol> ! * <li> A union of methods is composed of: ! * <ol type="a"> ! * <li> C's declared public instance and static methods as returned by ! * {@link #getDeclaredMethods()} and filtered to include only public ! * methods.</li> ! * <li> If C is a class other than {@code Object}, then include the result ! * of invoking this algorithm recursively on the superclass of C.</li> ! * <li> Include the results of invoking this algorithm recursively on all ! * direct superinterfaces of C, but include only instance methods.</li> ! * </ol></li> ! * <li> Union from step 1 is partitioned into subsets of methods with same ! * signature (name, parameter types) and return type.</li> ! * <li> Within each such subset only the most specific methods are selected. ! * Let method M be a method from a set of methods with same signature ! * and return type. M is most specific if there is no such method ! * N != M from the same set, such that N is more specific than M. ! * N is more specific than M if: ! * <ol type="a"> ! * <li> N is declared by a class and M is declared by an interface; or</li> ! * <li> N and M are both declared by classes or both by interfaces and ! * N's declaring type is the same as or a subtype of M's declaring type ! * (clearly, if M's and N's declaring types are the same type, then ! * M and N are the same method).</li> ! * </ol></li> ! * <li> The result of this algorithm is the union of all selected methods from ! * step 3.</li> ! * </ol> ! * ! * <p> Note that there may be more than one method with a particular name ! * and parameter types in a class because while the Java language forbids a ! * class to declare multiple methods with the same signature but different ! * return types, the Java virtual machine does not. This ! * increased flexibility in the virtual machine can be used to ! * implement various language features. For example, covariant ! * returns can be implemented with {@linkplain ! * java.lang.reflect.Method#isBridge bridge methods}; the bridge ! * method and the overriding method would have the same ! * signature but different return types. * * <p> The elements in the returned array are not sorted and are not in any * particular order. * * @return the array of {@code Method} objects representing the
*** 1903,1913 **** checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); Field field = getField0(name); if (field == null) { throw new NoSuchFieldException(name); } ! return field; } /** * Returns a {@code Method} object that reflects the specified public --- 1930,1940 ---- checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); Field field = getField0(name); if (field == null) { throw new NoSuchFieldException(name); } ! return getReflectionFactory().copyField(field); } /** * Returns a {@code Method} object that reflects the specified public
*** 1917,1968 **** * {@code parameterTypes} parameter is an array of {@code Class} * objects that identify the method's formal parameter types, in declared * order. If {@code parameterTypes} is {@code null}, it is * treated as if it were an empty array. * ! * <p> If the {@code name} is "{@code <init>}" or "{@code <clinit>}" a ! * {@code NoSuchMethodException} is raised. Otherwise, the method to ! * be reflected is determined by the algorithm that follows. Let C be the ! * class or interface represented by this object: ! * <OL> ! * <LI> C is searched for a <I>matching method</I>, as defined below. If a ! * matching method is found, it is reflected.</LI> ! * <LI> If no matching method is found by step 1 then: ! * <OL TYPE="a"> ! * <LI> If C is a class other than {@code Object}, then this algorithm is ! * invoked recursively on the superclass of C.</LI> ! * <LI> If C is the class {@code Object}, or if C is an interface, then ! * the superinterfaces of C (if any) are searched for a matching ! * method. If any such method is found, it is reflected.</LI> ! * </OL></LI> ! * </OL> * ! * <p> To find a matching method in a class or interface C:&nbsp; If C ! * declares exactly one public method with the specified name and exactly ! * the same formal parameter types, that is the method reflected. If more ! * than one such method is found in C, and one of these methods has a ! * return type that is more specific than any of the others, that method is ! * reflected; otherwise one of the methods is chosen arbitrarily. * ! * <p>Note that there may be more than one matching method in a ! * class because while the Java language forbids a class to ! * declare multiple methods with the same signature but different * return types, the Java virtual machine does not. This * increased flexibility in the virtual machine can be used to * implement various language features. For example, covariant * returns can be implemented with {@linkplain * java.lang.reflect.Method#isBridge bridge methods}; the bridge ! * method and the method being overridden would have the same * signature but different return types. * - * <p> If this {@code Class} object represents an array type, then this - * method does not find the {@code clone()} method. - * - * <p> Static methods declared in superinterfaces of the class or interface - * represented by this {@code Class} object are not considered members of - * the class or interface. - * * @param name the name of the method * @param parameterTypes the list of parameters * @return the {@code Method} object that matches the specified * {@code name} and {@code parameterTypes} * @throws NoSuchMethodException if a matching method is not found --- 1944,2016 ---- * {@code parameterTypes} parameter is an array of {@code Class} * objects that identify the method's formal parameter types, in declared * order. If {@code parameterTypes} is {@code null}, it is * treated as if it were an empty array. * ! * <p> If this {@code Class} object represents an array type, then this ! * method finds any public method inherited by the array type from ! * {@code Object} except method {@code clone()}. * ! * <p> If this {@code Class} object represents an interface then this ! * method does not find any implicitly declared method from ! * {@code Object}. Therefore, if no methods are explicitly declared in ! * this interface or any of its superinterfaces, then this method does not ! * find any method. * ! * <p> This method does not find any method with name "{@code <init>}" or ! * "{@code <clinit>}". ! * ! * <p> Generally, the method to be reflected is determined by the 4 step ! * algorithm that follows. ! * Let C be the class or interface represented by this {@code Class} object: ! * <ol> ! * <li> A union of methods is composed of: ! * <ol type="a"> ! * <li> C's declared public instance and static methods as returned by ! * {@link #getDeclaredMethods()} and filtered to include only public ! * methods that match given {@code name} and {@code parameterTypes}</li> ! * <li> If C is a class other than {@code Object}, then include the result ! * of invoking this algorithm recursively on the superclass of C.</li> ! * <li> Include the results of invoking this algorithm recursively on all ! * direct superinterfaces of C, but include only instance methods.</li> ! * </ol></li> ! * <li> This union is partitioned into subsets of methods with same ! * return type (the selection of methods from step 1 also guarantees that ! * they have the same method name and parameter types).</li> ! * <li> Within each such subset only the most specific methods are selected. ! * Let method M be a method from a set of methods with same VM ! * signature (return type, name, parameter types). ! * M is most specific if there is no such method N != M from the same ! * set, such that N is more specific than M. N is more specific than M ! * if: ! * <ol type="a"> ! * <li> N is declared by a class and M is declared by an interface; or</li> ! * <li> N and M are both declared by classes or both by interfaces and ! * N's declaring type is the same as or a subtype of M's declaring type ! * (clearly, if M's and N's declaring types are the same type, then ! * M and N are the same method).</li> ! * </ol></li> ! * <li> The result of this algorithm is chosen arbitrarily from the methods ! * with most specific return type among all selected methods from step 3. ! * Let R be a return type of a method M from the set of all selected methods ! * from step 3. M is a method with most specific return type if there is ! * no such method N != M from the same set, having return type S != R, ! * such that S is a subtype of R as determined by ! * R.class.{@link #isAssignableFrom}(S.class). ! * </ol> ! * ! * <p>Note that there may be more than one method with matching name and ! * parameter types in a class because while the Java language forbids a ! * class to declare multiple methods with the same signature but different * return types, the Java virtual machine does not. This * increased flexibility in the virtual machine can be used to * implement various language features. For example, covariant * returns can be implemented with {@linkplain * java.lang.reflect.Method#isBridge bridge methods}; the bridge ! * method and the overriding method would have the same * signature but different return types. * * @param name the name of the method * @param parameterTypes the list of parameters * @return the {@code Method} object that matches the specified * {@code name} and {@code parameterTypes} * @throws NoSuchMethodException if a matching method is not found
*** 1982,1996 **** */ @CallerSensitive public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); ! Method method = getMethod0(name, parameterTypes, true); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); } ! return method; } /** * Returns a {@code Method} object that reflects the specified public * member method of the class or interface represented by this --- 2030,2044 ---- */ @CallerSensitive public Method getMethod(String name, Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); ! Method method = getMethod0(name, parameterTypes); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); } ! return getReflectionFactory().copyMethod(method); } /** * Returns a {@code Method} object that reflects the specified public * member method of the class or interface represented by this
*** 2002,2012 **** * {@code name} and {@code parameterTypes}; {@code null} * if the method is not found or the name is * "&lt;init&gt;"or "&lt;clinit&gt;". */ Method getMethodOrNull(String name, Class<?>... parameterTypes) { ! return getMethod0(name, parameterTypes, true); } /** * Returns a {@code Constructor} object that reflects the specified --- 2050,2061 ---- * {@code name} and {@code parameterTypes}; {@code null} * if the method is not found or the name is * "&lt;init&gt;"or "&lt;clinit&gt;". */ Method getMethodOrNull(String name, Class<?>... parameterTypes) { ! Method method = getMethod0(name, parameterTypes); ! return method == null ? null : getReflectionFactory().copyMethod(method); } /** * Returns a {@code Constructor} object that reflects the specified
*** 2039,2049 **** */ @CallerSensitive public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); ! return getConstructor0(parameterTypes, Member.PUBLIC); } /** * Returns an array of {@code Class} objects reflecting all the --- 2088,2099 ---- */ @CallerSensitive public Constructor<T> getConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), true); ! return getReflectionFactory().copyConstructor( ! getConstructor0(parameterTypes, Member.PUBLIC)); } /** * Returns an array of {@code Class} objects reflecting all the
*** 2286,2296 **** checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); Field field = searchFields(privateGetDeclaredFields(false), name); if (field == null) { throw new NoSuchFieldException(name); } ! return field; } /** * Returns a {@code Method} object that reflects the specified --- 2336,2346 ---- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); Field field = searchFields(privateGetDeclaredFields(false), name); if (field == null) { throw new NoSuchFieldException(name); } ! return getReflectionFactory().copyField(field); } /** * Returns a {@code Method} object that reflects the specified
*** 2346,2356 **** checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); } ! return method; } /** * Returns a {@code Constructor} object that reflects the specified --- 2396,2406 ---- checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); Method method = searchMethods(privateGetDeclaredMethods(false), name, parameterTypes); if (method == null) { throw new NoSuchMethodException(getName() + "." + name + argumentTypesToString(parameterTypes)); } ! return getReflectionFactory().copyMethod(method); } /** * Returns a {@code Constructor} object that reflects the specified
*** 2392,2402 **** */ @CallerSensitive public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); ! return getConstructor0(parameterTypes, Member.DECLARED); } /** * Finds a resource with a given name. * --- 2442,2453 ---- */ @CallerSensitive public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes) throws NoSuchMethodException, SecurityException { checkMemberAccess(Member.DECLARED, Reflection.getCallerClass(), true); ! return getReflectionFactory().copyConstructor( ! getConstructor0(parameterTypes, Member.DECLARED)); } /** * Finds a resource with a given name. *
*** 3002,3185 **** } } return res; } - static class MethodArray { - // Don't add or remove methods except by add() or remove() calls. - private Method[] methods; - private int length; - private int defaults; - - MethodArray() { - this(20); - } - - MethodArray(int initialSize) { - if (initialSize < 2) - throw new IllegalArgumentException("Size should be 2 or more"); - - methods = new Method[initialSize]; - length = 0; - defaults = 0; - } - - boolean hasDefaults() { - return defaults != 0; - } - - void add(Method m) { - if (length == methods.length) { - methods = Arrays.copyOf(methods, 2 * methods.length); - } - methods[length++] = m; - - if (m != null && m.isDefault()) - defaults++; - } - - void addAll(Method[] ma) { - for (Method m : ma) { - add(m); - } - } - - void addAll(MethodArray ma) { - for (int i = 0; i < ma.length(); i++) { - add(ma.get(i)); - } - } - - void addIfNotPresent(Method newMethod) { - for (int i = 0; i < length; i++) { - Method m = methods[i]; - if (m == newMethod || (m != null && m.equals(newMethod))) { - return; - } - } - add(newMethod); - } - - void addAllIfNotPresent(MethodArray newMethods) { - for (int i = 0; i < newMethods.length(); i++) { - Method m = newMethods.get(i); - if (m != null) { - addIfNotPresent(m); - } - } - } - - /* Add Methods declared in an interface to this MethodArray. - * Static methods declared in interfaces are not inherited. - */ - void addInterfaceMethods(Method[] methods) { - for (Method candidate : methods) { - if (!Modifier.isStatic(candidate.getModifiers())) { - add(candidate); - } - } - } - - int length() { - return length; - } - - Method get(int i) { - return methods[i]; - } - - Method getFirst() { - for (Method m : methods) - if (m != null) - return m; - return null; - } - - void removeByNameAndDescriptor(Method toRemove) { - for (int i = 0; i < length; i++) { - Method m = methods[i]; - if (m != null && matchesNameAndDescriptor(m, toRemove)) { - remove(i); - } - } - } - - private void remove(int i) { - if (methods[i] != null && methods[i].isDefault()) - defaults--; - methods[i] = null; - } - - private boolean matchesNameAndDescriptor(Method m1, Method m2) { - return m1.getReturnType() == m2.getReturnType() && - m1.getName() == m2.getName() && // name is guaranteed to be interned - arrayContentsEq(m1.getParameterTypes(), - m2.getParameterTypes()); - } - - void compactAndTrim() { - int newPos = 0; - // Get rid of null slots - for (int pos = 0; pos < length; pos++) { - Method m = methods[pos]; - if (m != null) { - if (pos != newPos) { - methods[newPos] = m; - } - newPos++; - } - } - if (newPos != methods.length) { - methods = Arrays.copyOf(methods, newPos); - } - } - - /* Removes all Methods from this MethodArray that have a more specific - * default Method in this MethodArray. - * - * Users of MethodArray are responsible for pruning Methods that have - * a more specific <em>concrete</em> Method. - */ - void removeLessSpecifics() { - if (!hasDefaults()) - return; - - for (int i = 0; i < length; i++) { - Method m = get(i); - if (m == null || !m.isDefault()) - continue; - - for (int j = 0; j < length; j++) { - if (i == j) - continue; - - Method candidate = get(j); - if (candidate == null) - continue; - - if (!matchesNameAndDescriptor(m, candidate)) - continue; - - if (hasMoreSpecificClass(m, candidate)) - remove(j); - } - } - } - - Method[] getArray() { - return methods; - } - - // Returns true if m1 is more specific than m2 - static boolean hasMoreSpecificClass(Method m1, Method m2) { - Class<?> m1Class = m1.getDeclaringClass(); - Class<?> m2Class = m2.getDeclaringClass(); - return m1Class != m2Class && m2Class.isAssignableFrom(m1Class); - } - } - - // Returns an array of "root" methods. These Method objects must NOT // be propagated to the outside world, but must instead be copied // via ReflectionFactory.copyMethod. private Method[] privateGetPublicMethods() { Method[] res; --- 3053,3062 ----
*** 3188,3242 **** res = rd.publicMethods; if (res != null) return res; } // No cached value available; compute value recursively. ! // Start by fetching public declared methods ! MethodArray methods = new MethodArray(); ! { ! Method[] tmp = privateGetDeclaredMethods(true); ! methods.addAll(tmp); } ! // Now recur over superclass and direct superinterfaces. ! // Go over superinterfaces first so we can more easily filter ! // out concrete implementations inherited from superclasses at ! // the end. ! MethodArray inheritedMethods = new MethodArray(); ! for (Class<?> i : getInterfaces()) { ! inheritedMethods.addInterfaceMethods(i.privateGetPublicMethods()); } ! if (!isInterface()) { ! Class<?> c = getSuperclass(); ! if (c != null) { ! MethodArray supers = new MethodArray(); ! supers.addAll(c.privateGetPublicMethods()); ! // Filter out concrete implementations of any ! // interface methods ! for (int i = 0; i < supers.length(); i++) { ! Method m = supers.get(i); ! if (m != null && ! !Modifier.isAbstract(m.getModifiers()) && ! !m.isDefault()) { ! inheritedMethods.removeByNameAndDescriptor(m); ! } ! } ! // Insert superclass's inherited methods before ! // superinterfaces' to satisfy getMethod's search ! // order ! supers.addAll(inheritedMethods); ! inheritedMethods = supers; ! } ! } ! // Filter out all local methods from inherited ones ! for (int i = 0; i < methods.length(); i++) { ! Method m = methods.get(i); ! inheritedMethods.removeByNameAndDescriptor(m); ! } ! methods.addAllIfNotPresent(inheritedMethods); ! methods.removeLessSpecifics(); ! methods.compactAndTrim(); ! res = methods.getArray(); if (rd != null) { rd.publicMethods = res; } return res; } --- 3065,3097 ---- res = rd.publicMethods; if (res != null) return res; } // No cached value available; compute value recursively. ! // Start by fetching public declared methods... ! PublicMethods pms = new PublicMethods(); ! for (Method m : privateGetDeclaredMethods(/* publicOnly */ true)) { ! pms.merge(m); } ! // ...then recur over superclass methods... ! Class<?> sc = getSuperclass(); ! if (sc != null) { ! for (Method m : sc.privateGetPublicMethods()) { ! pms.merge(m); } ! } ! // ...and finally over direct superinterfaces. ! for (Class<?> intf : getInterfaces(/* cloneArray */ false)) { ! for (Method m : intf.privateGetPublicMethods()) { ! // static interface methods are not inherited ! if (!Modifier.isStatic(m.getModifiers())) { ! pms.merge(m); ! } ! } ! } ! ! res = pms.toArray(); if (rd != null) { rd.publicMethods = res; } return res; }
*** 3244,3264 **** // // Helpers for fetchers of one field, method, or constructor // private static Field searchFields(Field[] fields, String name) { - String internedName = name.intern(); for (Field field : fields) { ! if (field.getName() == internedName) { ! return getReflectionFactory().copyField(field); } } return null; } ! private Field getField0(String name) throws NoSuchFieldException { // Note: the intent is that the search algorithm this routine // uses be equivalent to the ordering imposed by // privateGetPublicFields(). It fetches only the declared // public fields for each class, however, to reduce the number // of Field objects which have to be created for the common --- 3099,3122 ---- // // Helpers for fetchers of one field, method, or constructor // + // This method does not copy the returned Field object! private static Field searchFields(Field[] fields, String name) { for (Field field : fields) { ! if (field.getName().equals(name)) { ! return field; } } return null; } ! // Returns a "root" Field object. This Field object must NOT ! // be propagated to the outside world, but must instead be copied ! // via ReflectionFactory.copyField. ! private Field getField0(String name) { // Note: the intent is that the search algorithm this routine // uses be equivalent to the ordering imposed by // privateGetPublicFields(). It fetches only the declared // public fields for each class, however, to reduce the number // of Field objects which have to be created for the common
*** 3268,3278 **** // Search declared public fields if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) { return res; } // Direct superinterfaces, recursively ! Class<?>[] interfaces = getInterfaces(); for (Class<?> c : interfaces) { if ((res = c.getField0(name)) != null) { return res; } } --- 3126,3136 ---- // Search declared public fields if ((res = searchFields(privateGetDeclaredFields(true), name)) != null) { return res; } // Direct superinterfaces, recursively ! Class<?>[] interfaces = getInterfaces(/* cloneArray */ false); for (Class<?> c : interfaces) { if ((res = c.getField0(name)) != null) { return res; } }
*** 3286,3376 **** } } return null; } private static Method searchMethods(Method[] methods, String name, Class<?>[] parameterTypes) { Method res = null; - String internedName = name.intern(); for (Method m : methods) { ! if (m.getName() == internedName ! && arrayContentsEq(parameterTypes, m.getParameterTypes()) && (res == null ! || res.getReturnType().isAssignableFrom(m.getReturnType()))) res = m; } ! ! return (res == null ? res : getReflectionFactory().copyMethod(res)); } ! private Method getMethod0(String name, Class<?>[] parameterTypes, boolean includeStaticMethods) { ! MethodArray interfaceCandidates = new MethodArray(2); ! Method res = privateGetMethodRecursive(name, parameterTypes, includeStaticMethods, interfaceCandidates); ! if (res != null) ! return res; ! // Not found on class or superclass directly ! interfaceCandidates.removeLessSpecifics(); ! return interfaceCandidates.getFirst(); // may be null } ! private Method privateGetMethodRecursive(String name, Class<?>[] parameterTypes, ! boolean includeStaticMethods, ! MethodArray allInterfaceCandidates) { ! // Note: the intent is that the search algorithm this routine ! // uses be equivalent to the ordering imposed by ! // privateGetPublicMethods(). It fetches only the declared ! // public methods for each class, however, to reduce the ! // number of Method objects which have to be created for the ! // common case where the method being requested is declared in ! // the class which is being queried. ! // ! // Due to default methods, unless a method is found on a superclass, ! // methods declared in any superinterface needs to be considered. ! // Collect all candidates declared in superinterfaces in {@code ! // allInterfaceCandidates} and select the most specific if no match on ! // a superclass is found. ! ! // Must _not_ return root methods ! Method res; ! // Search declared public methods ! if ((res = searchMethods(privateGetDeclaredMethods(true), ! name, ! parameterTypes)) != null) { ! if (includeStaticMethods || !Modifier.isStatic(res.getModifiers())) ! return res; ! } ! // Search superclass's methods ! if (!isInterface()) { ! Class<? super T> c = getSuperclass(); ! if (c != null) { ! if ((res = c.getMethod0(name, parameterTypes, true)) != null) { return res; } } } ! // Search superinterfaces' methods ! Class<?>[] interfaces = getInterfaces(); ! for (Class<?> c : interfaces) ! if ((res = c.getMethod0(name, parameterTypes, false)) != null) ! allInterfaceCandidates.add(res); ! // Not found ! return null; } private Constructor<T> getConstructor0(Class<?>[] parameterTypes, int which) throws NoSuchMethodException { Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC)); for (Constructor<T> constructor : constructors) { if (arrayContentsEq(parameterTypes, ! constructor.getParameterTypes())) { ! return getReflectionFactory().copyConstructor(constructor); } } throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes)); } --- 3144,3232 ---- } } return null; } + // This method does not copy the returned Method object! private static Method searchMethods(Method[] methods, String name, Class<?>[] parameterTypes) { + ReflectionFactory fact = getReflectionFactory(); Method res = null; for (Method m : methods) { ! if (m.getName().equals(name) ! && arrayContentsEq(parameterTypes, ! fact.getExecutableSharedParameterTypes(m)) && (res == null ! || (res.getReturnType() != m.getReturnType() ! && res.getReturnType().isAssignableFrom(m.getReturnType())))) res = m; } ! return res; } ! private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0]; ! // Returns a "root" Method object. This Method object must NOT ! // be propagated to the outside world, but must instead be copied ! // via ReflectionFactory.copyMethod. ! private Method getMethod0(String name, Class<?>[] parameterTypes) { ! PublicMethods.MethodList res = getMethodsRecursive( ! name, ! parameterTypes == null ? EMPTY_CLASS_ARRAY : parameterTypes, ! /* includeStatic */ true); ! return res == null ? null : res.getMostSpecific(); } ! // Returns a list of "root" Method objects. These Method objects must NOT ! // be propagated to the outside world, but must instead be copied ! // via ReflectionFactory.copyMethod. ! private PublicMethods.MethodList getMethodsRecursive(String name, Class<?>[] parameterTypes, ! boolean includeStatic) { ! // 1st check declared public methods ! Method[] methods = privateGetDeclaredMethods(/* publicOnly */ true); ! PublicMethods.MethodList res = PublicMethods.MethodList ! .filter(methods, name, parameterTypes, includeStatic); ! // if there is at least one match among declared methods, we need not ! // search any further as such match surely overrides matching methods ! // declared in superclass(es) or interface(s). ! if (res != null) { return res; } + + // if there was no match among declared methods, + // we must consult the superclass (if any) recursively... + Class<?> sc = getSuperclass(); + if (sc != null) { + res = sc.getMethodsRecursive(name, parameterTypes, includeStatic); } + + // ...and coalesce the superclass methods with methods obtained + // from directly implemented interfaces excluding static methods... + for (Class<?> intf : getInterfaces(/* cloneArray */ false)) { + res = PublicMethods.MethodList.merge( + res, intf.getMethodsRecursive(name, parameterTypes, + /* includeStatic */ false)); } ! ! return res; } + // Returns a "root" Constructor object. This Constructor object must NOT + // be propagated to the outside world, but must instead be copied + // via ReflectionFactory.copyConstructor. private Constructor<T> getConstructor0(Class<?>[] parameterTypes, int which) throws NoSuchMethodException { + ReflectionFactory fact = getReflectionFactory(); Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC)); for (Constructor<T> constructor : constructors) { if (arrayContentsEq(parameterTypes, ! fact.getExecutableSharedParameterTypes(constructor))) { ! return constructor; } } throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes)); }
< prev index next >