/** Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.*********************/package java.lang;import jdk.internal.reflect.ReflectionFactory;import java.lang.reflect.Method;import java.lang.reflect.Modifier;import java.security.AccessController;import java.util.Arrays;import java.util.LinkedHashMap;import java.util.Map;/*** A collection of most specific public methods. Methods are added to it using* {@link #merge(Method)} method. Only the most specific methods for a* particular signature are kept.*/final class PublicMethods {/*** a map of (method name, parameter types) -> linked list of Method(s)*/private final Map<Key, MethodList> map = new LinkedHashMap<>();/*** keeps track of the number of collected methods*/private int methodCount;/*** Merges new method with existing methods. New method is either* ignored (if a more specific method with same signature exists) or added* to the collection. When it is added to the collection, it may replace one* or more existing methods with same signature if they are less specific* than added method.* See comments in code...*/void merge(Method method) {Key key = new Key(method);MethodList existing = map.get(key);int xLen = existing == null ? 0 : existing.length();MethodList merged = MethodList.merge(existing, method);methodCount += merged.length() - xLen;// replace if head of list changedif (merged != existing) {map.put(key, merged);}}/*** Dumps methods to array.*/Method[] toArray() {Method[] array = new Method[methodCount];int i = 0;for (MethodList ml : map.values()) {for (; ml != null; ml = ml.next) {array[i++] = ml.method;}}return array;}/*** Method (name, parameter types) tuple.*/private static final class Key {private static final ReflectionFactory reflectionFactory =AccessController.doPrivileged(new ReflectionFactory.GetReflectionFactoryAction());private final String name; // must be interned (as from Method.getName())private final Class<?>[] ptypes;Key(Method method) {name = method.getName();ptypes = reflectionFactory.getExecutableSharedParameterTypes(method);}static boolean matches(Method method,String name, // may not be internedClass<?>[] ptypes) {return method.getName().equals(name) &&Arrays.equals(reflectionFactory.getExecutableSharedParameterTypes(method),ptypes);}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (!(o instanceof Key)) return false;Key that = (Key) o;//noinspection StringEquality (guaranteed interned String(s))return name == that.name &&Arrays.equals(ptypes, that.ptypes);}@Overridepublic int hashCode() {return System.identityHashCode(name) + // guaranteed interned String31 * Arrays.hashCode(ptypes);}}/*** Node of a inked list containing Method(s) sharing the same* (name, parameter types) tuple.*/static final class MethodList {Method method;MethodList next;private MethodList(Method method) {this.method = method;}/*** @return the head of a linked list containing given {@code methods}* filtered by given method {@code name}, parameter types* {@code ptypes} and including or excluding static methods as* requested by {@code includeStatic} flag.*/static MethodList filter(Method[] methods, String name,Class<?>[] ptypes, boolean includeStatic) {MethodList head = null, tail = null;for (Method method : methods) {if ((includeStatic || !Modifier.isStatic(method.getModifiers())) &&Key.matches(method, name, ptypes)) {if (tail == null) {head = tail = new MethodList(method);} else {tail = tail.next = new MethodList(method);}}}return head;}/*** This method should only be called with the {@code head} (possibly null)* of a list of Method(s) that share the same (method name, parameter types)* and another {@code methodList} that also contains Method(s) with the* same and equal (method name, parameter types) as the 1st list.* It modifies the 1st list and returns the head of merged list* containing only the most specific methods for each signature* (i.e. return type). The returned head of the merged list may or* may not be the same as the {@code head} of the given list.* The given {@code methodList} is not modified.*/static MethodList merge(MethodList head, MethodList methodList) {for (MethodList ml = methodList; ml != null; ml = ml.next) {head = merge(head, ml.method);}return head;}private static MethodList merge(MethodList head, Method method) {Class<?> dclass = method.getDeclaringClass();Class<?> rtype = method.getReturnType();MethodList prev = null;for (MethodList l = head; l != null; l = l.next) {// eXisting methodMethod xmethod = l.method;// only merge methods with same signature:// (return type, name, parameter types) tuple// as we only keep methods with same (name, parameter types)// tuple together in one list, we only need to check return typeif (rtype == xmethod.getReturnType()) {Class<?> xdclass = xmethod.getDeclaringClass();if (dclass.isInterface() == xdclass.isInterface()) {// both methods are declared by interfaces// or both by classesif (dclass.isAssignableFrom(xdclass)) {// existing method is the same or overrides// new method - ignore new methodreturn head;}if (xdclass.isAssignableFrom(dclass)) {// new method overrides existing// method - knock out existing methodif (prev != null) {prev.next = l.next;} else {head = l.next;}// keep iterating} else {// unrelated (should only happen for interfaces)prev = l;// keep iterating}} else if (dclass.isInterface()) {// new method is declared by interface while// existing method is declared by class -// ignore new methodreturn head;} else /* xdclass.isInterface() */ {// new method is declared by class while// existing method is declared by interface -// knock out existing methodif (prev != null) {prev.next = l.next;} else {head = l.next;}// keep iterating}} else {// distinct signaturesprev = l;// keep iterating}}// append new method to the listif (prev == null) {head = new MethodList(method);} else {prev.next = new MethodList(method);}return head;}private int length() {int len = 1;for (MethodList ml = next; ml != null; ml = ml.next) {len++;}return len;}/*** @return 1st method in list with most specific return type*/Method getMostSpecific() {Method m = method;Class<?> rt = m.getReturnType();for (MethodList ml = next; ml != null; ml = ml.next) {Method m2 = ml.method;Class<?> rt2 = m2.getReturnType();if (rt2 != rt && rt.isAssignableFrom(rt2)) {// found more specific return typem = m2;rt = rt2;}}return m;}}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。