jdk/src/share/classes/java/lang/Class.java
changeset 24867 c3514175b6cd
parent 24865 09b1d992ca72
child 25392 0eabdbb887aa
equal deleted inserted replaced
24866:fcd7bd73d928 24867:c3514175b6cd
  2694         }
  2694         }
  2695         return res;
  2695         return res;
  2696     }
  2696     }
  2697 
  2697 
  2698     static class MethodArray {
  2698     static class MethodArray {
       
  2699         // Don't add or remove methods except by add() or remove() calls.
  2699         private Method[] methods;
  2700         private Method[] methods;
  2700         private int length;
  2701         private int length;
       
  2702         private int defaults;
  2701 
  2703 
  2702         MethodArray() {
  2704         MethodArray() {
  2703             methods = new Method[20];
  2705             this(20);
       
  2706         }
       
  2707 
       
  2708         MethodArray(int initialSize) {
       
  2709             if (initialSize < 2)
       
  2710                 throw new IllegalArgumentException("Size should be 2 or more");
       
  2711 
       
  2712             methods = new Method[initialSize];
  2704             length = 0;
  2713             length = 0;
       
  2714             defaults = 0;
       
  2715         }
       
  2716 
       
  2717         boolean hasDefaults() {
       
  2718             return defaults != 0;
  2705         }
  2719         }
  2706 
  2720 
  2707         void add(Method m) {
  2721         void add(Method m) {
  2708             if (length == methods.length) {
  2722             if (length == methods.length) {
  2709                 methods = Arrays.copyOf(methods, 2 * methods.length);
  2723                 methods = Arrays.copyOf(methods, 2 * methods.length);
  2710             }
  2724             }
  2711             methods[length++] = m;
  2725             methods[length++] = m;
       
  2726 
       
  2727             if (m != null && m.isDefault())
       
  2728                 defaults++;
  2712         }
  2729         }
  2713 
  2730 
  2714         void addAll(Method[] ma) {
  2731         void addAll(Method[] ma) {
  2715             for (Method m : ma) {
  2732             for (Method m : ma) {
  2716                 add(m);
  2733                 add(m);
  2740                     addIfNotPresent(m);
  2757                     addIfNotPresent(m);
  2741                 }
  2758                 }
  2742             }
  2759             }
  2743         }
  2760         }
  2744 
  2761 
  2745         void addAllNonStatic(Method[] methods) {
  2762         /* Add Methods declared in an interface to this MethodArray.
       
  2763          * Static methods declared in interfaces are not inherited.
       
  2764          */
       
  2765         void addInterfaceMethods(Method[] methods) {
  2746             for (Method candidate : methods) {
  2766             for (Method candidate : methods) {
  2747                 if (!Modifier.isStatic(candidate.getModifiers())) {
  2767                 if (!Modifier.isStatic(candidate.getModifiers())) {
  2748                     add(candidate);
  2768                     add(candidate);
  2749                 }
  2769                 }
  2750             }
  2770             }
  2756 
  2776 
  2757         Method get(int i) {
  2777         Method get(int i) {
  2758             return methods[i];
  2778             return methods[i];
  2759         }
  2779         }
  2760 
  2780 
  2761         void removeByNameAndSignature(Method toRemove) {
  2781         Method getFirst() {
       
  2782             for (Method m : methods)
       
  2783                 if (m != null)
       
  2784                     return m;
       
  2785             return null;
       
  2786         }
       
  2787 
       
  2788         void removeByNameAndDescriptor(Method toRemove) {
  2762             for (int i = 0; i < length; i++) {
  2789             for (int i = 0; i < length; i++) {
  2763                 Method m = methods[i];
  2790                 Method m = methods[i];
  2764                 if (m != null &&
  2791                 if (m != null && matchesNameAndDescriptor(m, toRemove)) {
  2765                     m.getReturnType() == toRemove.getReturnType() &&
  2792                     remove(i);
  2766                     m.getName() == toRemove.getName() &&
       
  2767                     arrayContentsEq(m.getParameterTypes(),
       
  2768                                     toRemove.getParameterTypes())) {
       
  2769                     methods[i] = null;
       
  2770                 }
  2793                 }
  2771             }
  2794             }
       
  2795         }
       
  2796 
       
  2797         private void remove(int i) {
       
  2798             if (methods[i] != null && methods[i].isDefault())
       
  2799                 defaults--;
       
  2800             methods[i] = null;
       
  2801         }
       
  2802 
       
  2803         private boolean matchesNameAndDescriptor(Method m1, Method m2) {
       
  2804             return m1.getReturnType() == m2.getReturnType() &&
       
  2805                    m1.getName() == m2.getName() && // name is guaranteed to be interned
       
  2806                    arrayContentsEq(m1.getParameterTypes(),
       
  2807                            m2.getParameterTypes());
  2772         }
  2808         }
  2773 
  2809 
  2774         void compactAndTrim() {
  2810         void compactAndTrim() {
  2775             int newPos = 0;
  2811             int newPos = 0;
  2776             // Get rid of null slots
  2812             // Get rid of null slots
  2786             if (newPos != methods.length) {
  2822             if (newPos != methods.length) {
  2787                 methods = Arrays.copyOf(methods, newPos);
  2823                 methods = Arrays.copyOf(methods, newPos);
  2788             }
  2824             }
  2789         }
  2825         }
  2790 
  2826 
       
  2827         /* Removes all Methods from this MethodArray that have a more specific
       
  2828          * default Method in this MethodArray.
       
  2829          *
       
  2830          * Users of MethodArray are responsible for pruning Methods that have
       
  2831          * a more specific <em>concrete</em> Method.
       
  2832          */
       
  2833         void removeLessSpecifics() {
       
  2834             if (!hasDefaults())
       
  2835                 return;
       
  2836 
       
  2837             for (int i = 0; i < length; i++) {
       
  2838                 Method m = get(i);
       
  2839                 if  (m == null || !m.isDefault())
       
  2840                     continue;
       
  2841 
       
  2842                 for (int j  = 0; j < length; j++) {
       
  2843                     if (i == j)
       
  2844                         continue;
       
  2845 
       
  2846                     Method candidate = get(j);
       
  2847                     if (candidate == null)
       
  2848                         continue;
       
  2849 
       
  2850                     if (!matchesNameAndDescriptor(m, candidate))
       
  2851                         continue;
       
  2852 
       
  2853                     if (hasMoreSpecificClass(m, candidate))
       
  2854                         remove(j);
       
  2855                 }
       
  2856             }
       
  2857         }
       
  2858 
  2791         Method[] getArray() {
  2859         Method[] getArray() {
  2792             return methods;
  2860             return methods;
       
  2861         }
       
  2862 
       
  2863         // Returns true if m1 is more specific than m2
       
  2864         static boolean hasMoreSpecificClass(Method m1, Method m2) {
       
  2865             Class<?> m1Class = m1.getDeclaringClass();
       
  2866             Class<?> m2Class = m2.getDeclaringClass();
       
  2867             return m1Class != m2Class && m2Class.isAssignableFrom(m1Class);
  2793         }
  2868         }
  2794     }
  2869     }
  2795 
  2870 
  2796 
  2871 
  2797     // Returns an array of "root" methods. These Method objects must NOT
  2872     // Returns an array of "root" methods. These Method objects must NOT
  2817         // Go over superinterfaces first so we can more easily filter
  2892         // Go over superinterfaces first so we can more easily filter
  2818         // out concrete implementations inherited from superclasses at
  2893         // out concrete implementations inherited from superclasses at
  2819         // the end.
  2894         // the end.
  2820         MethodArray inheritedMethods = new MethodArray();
  2895         MethodArray inheritedMethods = new MethodArray();
  2821         for (Class<?> i : getInterfaces()) {
  2896         for (Class<?> i : getInterfaces()) {
  2822             inheritedMethods.addAllNonStatic(i.privateGetPublicMethods());
  2897             inheritedMethods.addInterfaceMethods(i.privateGetPublicMethods());
  2823         }
  2898         }
  2824         if (!isInterface()) {
  2899         if (!isInterface()) {
  2825             Class<?> c = getSuperclass();
  2900             Class<?> c = getSuperclass();
  2826             if (c != null) {
  2901             if (c != null) {
  2827                 MethodArray supers = new MethodArray();
  2902                 MethodArray supers = new MethodArray();
  2828                 supers.addAll(c.privateGetPublicMethods());
  2903                 supers.addAll(c.privateGetPublicMethods());
  2829                 // Filter out concrete implementations of any
  2904                 // Filter out concrete implementations of any
  2830                 // interface methods
  2905                 // interface methods
  2831                 for (int i = 0; i < supers.length(); i++) {
  2906                 for (int i = 0; i < supers.length(); i++) {
  2832                     Method m = supers.get(i);
  2907                     Method m = supers.get(i);
  2833                     if (m != null && !Modifier.isAbstract(m.getModifiers())) {
  2908                     if (m != null &&
  2834                         inheritedMethods.removeByNameAndSignature(m);
  2909                             !Modifier.isAbstract(m.getModifiers()) &&
       
  2910                             !m.isDefault()) {
       
  2911                         inheritedMethods.removeByNameAndDescriptor(m);
  2835                     }
  2912                     }
  2836                 }
  2913                 }
  2837                 // Insert superclass's inherited methods before
  2914                 // Insert superclass's inherited methods before
  2838                 // superinterfaces' to satisfy getMethod's search
  2915                 // superinterfaces' to satisfy getMethod's search
  2839                 // order
  2916                 // order
  2842             }
  2919             }
  2843         }
  2920         }
  2844         // Filter out all local methods from inherited ones
  2921         // Filter out all local methods from inherited ones
  2845         for (int i = 0; i < methods.length(); i++) {
  2922         for (int i = 0; i < methods.length(); i++) {
  2846             Method m = methods.get(i);
  2923             Method m = methods.get(i);
  2847             inheritedMethods.removeByNameAndSignature(m);
  2924             inheritedMethods.removeByNameAndDescriptor(m);
  2848         }
  2925         }
  2849         methods.addAllIfNotPresent(inheritedMethods);
  2926         methods.addAllIfNotPresent(inheritedMethods);
       
  2927         methods.removeLessSpecifics();
  2850         methods.compactAndTrim();
  2928         methods.compactAndTrim();
  2851         res = methods.getArray();
  2929         res = methods.getArray();
  2852         if (rd != null) {
  2930         if (rd != null) {
  2853             rd.publicMethods = res;
  2931             rd.publicMethods = res;
  2854         }
  2932         }
  2917         }
  2995         }
  2918 
  2996 
  2919         return (res == null ? res : getReflectionFactory().copyMethod(res));
  2997         return (res == null ? res : getReflectionFactory().copyMethod(res));
  2920     }
  2998     }
  2921 
  2999 
  2922 
       
  2923     private Method getMethod0(String name, Class<?>[] parameterTypes, boolean includeStaticMethods) {
  3000     private Method getMethod0(String name, Class<?>[] parameterTypes, boolean includeStaticMethods) {
       
  3001         MethodArray interfaceCandidates = new MethodArray(2);
       
  3002         Method res =  privateGetMethodRecursive(name, parameterTypes, includeStaticMethods, interfaceCandidates);
       
  3003         if (res != null)
       
  3004             return res;
       
  3005 
       
  3006         // Not found on class or superclass directly
       
  3007         interfaceCandidates.removeLessSpecifics();
       
  3008         return interfaceCandidates.getFirst(); // may be null
       
  3009     }
       
  3010 
       
  3011     private Method privateGetMethodRecursive(String name,
       
  3012             Class<?>[] parameterTypes,
       
  3013             boolean includeStaticMethods,
       
  3014             MethodArray allInterfaceCandidates) {
  2924         // Note: the intent is that the search algorithm this routine
  3015         // Note: the intent is that the search algorithm this routine
  2925         // uses be equivalent to the ordering imposed by
  3016         // uses be equivalent to the ordering imposed by
  2926         // privateGetPublicMethods(). It fetches only the declared
  3017         // privateGetPublicMethods(). It fetches only the declared
  2927         // public methods for each class, however, to reduce the
  3018         // public methods for each class, however, to reduce the
  2928         // number of Method objects which have to be created for the
  3019         // number of Method objects which have to be created for the
  2929         // common case where the method being requested is declared in
  3020         // common case where the method being requested is declared in
  2930         // the class which is being queried.
  3021         // the class which is being queried.
       
  3022         //
       
  3023         // Due to default methods, unless a method is found on a superclass,
       
  3024         // methods declared in any superinterface needs to be considered.
       
  3025         // Collect all candidates declared in superinterfaces in {@code
       
  3026         // allInterfaceCandidates} and select the most specific if no match on
       
  3027         // a superclass is found.
       
  3028 
       
  3029         // Must _not_ return root methods
  2931         Method res;
  3030         Method res;
  2932         // Search declared public methods
  3031         // Search declared public methods
  2933         if ((res = searchMethods(privateGetDeclaredMethods(true),
  3032         if ((res = searchMethods(privateGetDeclaredMethods(true),
  2934                                  name,
  3033                                  name,
  2935                                  parameterTypes)) != null) {
  3034                                  parameterTypes)) != null) {
  2947         }
  3046         }
  2948         // Search superinterfaces' methods
  3047         // Search superinterfaces' methods
  2949         Class<?>[] interfaces = getInterfaces();
  3048         Class<?>[] interfaces = getInterfaces();
  2950         for (Class<?> c : interfaces)
  3049         for (Class<?> c : interfaces)
  2951             if ((res = c.getMethod0(name, parameterTypes, false)) != null)
  3050             if ((res = c.getMethod0(name, parameterTypes, false)) != null)
  2952                 return res;
  3051                 allInterfaceCandidates.add(res);
  2953         // Not found
  3052         // Not found
  2954         return null;
  3053         return null;
  2955     }
  3054     }
  2956 
  3055 
  2957     private Constructor<T> getConstructor0(Class<?>[] parameterTypes,
  3056     private Constructor<T> getConstructor0(Class<?>[] parameterTypes,