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); |
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, |