📄 classinspector.java
字号:
continue; } /* We have seen an ambiguous situation; one of the cases may * tie on each parameter. */ ambiguous = true; if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("MethodResolutionInfo")) { SanityManager.DEBUG("MethodResolutionInfo", "MRI - Ambiguous match"); } } } firstTimeAround = false; } while (ambiguous && somethingChanged); if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("MethodResolutionInfo")) { SanityManager.DEBUG("MethodResolutionInfo", "MRI - End method resolution trace for " + methodName + "()" + "\nMRI - "); } } /* Throw an exception here if the method invocation ambiguous */ if (ambiguous) { /* Put the parameter type names into a single string */ String parmTypesString = ""; for (int i = 0; i < paramClasses.length; i++) { if (i != 0) parmTypesString += ", "; parmTypesString += (paramClasses[i] == null ? "null" : paramClasses[i].getName()); if (primParamClasses != null && primParamClasses[i] != null) parmTypesString += "(" + primParamClasses[i].getName() + ")"; } throw StandardException.newException(SQLState.LANG_AMBIGUOUS_METHOD_INVOCATION, receiverClass.getName(), methodName, parmTypesString); } if (candidateIndex == -1) return null; if (SanityManager.DEBUG) { if (methods[candidateIndex] == null) SanityManager.THROWASSERT("methods is null at index " + candidateIndex); } return methods[candidateIndex]; } /** Get (load) the class for the given class name. This method converts any java language class name into a Class object. This includes cases like String[] and primitive types. This will attempt to load the class from the application set. @exception ClassNotFoundException Class cannot be found, or a SecurityException or LinkageException was thrown loading the class. */ public Class getClass(String className) throws ClassNotFoundException { if ((className == null) || (className.length() == 0)) { return null; } int arrayDepth = 0; int classNameLength = className.length(); int position = classNameLength - 2; while ((position >= 0) && className.substring(position, position + 2).equals("[]")) { arrayDepth++; position -= 2; classNameLength -= 2; } if (classNameLength <= 0) { // a bogus class name, let Class.forName deal with the error. return Class.forName(className); } if (arrayDepth != 0) className = className.substring(0, classNameLength); Class baseClass = null; if (classNameLength >=3 && classNameLength <=7) { if ("int".equals(className)) baseClass = Integer.TYPE; else if ("short".equals(className)) baseClass = Short.TYPE; else if ("boolean".equals(className)) baseClass = Boolean.TYPE; else if ("byte".equals(className)) baseClass = Byte.TYPE; else if ("float".equals(className)) baseClass = Float.TYPE; else if ("double".equals(className)) baseClass = Double.TYPE; else if ("long".equals(className)) baseClass = Long.TYPE; else if ("char".equals(className)) baseClass = Character.TYPE; else if ("void".equals(className)) baseClass = Void.TYPE; } if (baseClass == null) { baseClass = cf.loadApplicationClass(className); } if (arrayDepth == 0) return baseClass; // need to create an actual instance of the array type // and get its class from that. There is no other documented // way to do this. While a getName() on an array class // returns [[[Lclassname; format it's not consistent // with primitive types, e.g. // // Integer.TYPE.getName() returns "int" // Class.forName(new int[0] returns "[I" // if (arrayDepth == 1) return Array.newInstance(baseClass, 0).getClass(); return Array.newInstance(baseClass, new int[arrayDepth]).getClass(); } /** Is method/constructor T more or equally specific than method U. See the Java Language Specification section 15.11.2.2. */ private boolean isMethodMoreSpecificOrEqual(Member T, Member U, boolean[] isParam) { Class[] TC; Class[] UC; if (T instanceof Method) { if (!classConvertableFromTo(T.getDeclaringClass(), U.getDeclaringClass(), true)) return false; TC = ((Method) T).getParameterTypes(); UC = ((Method) U).getParameterTypes(); } else { TC = ((Constructor) T).getParameterTypes(); UC = ((Constructor) U).getParameterTypes(); } return signatureConvertableFromTo(TC, null, UC, isParam, true); } /** * Can we convert a signature from fromTypes(primFromTypes) to toTypes. * "mixTypes" is a flag to show if object/primitive type conversion is * possible; this is used for comparing two candidate methods in the * second pass of the two pass method resolution. * * @param fromTypes from types' classes * @param primFromTypes primitive from types or null * @param toTypes to types' classes * @param isParam is parameter (?) or not * @param mixTypes mixing object/primitive types for comparison **/ private boolean signatureConvertableFromTo(Class[] fromTypes, Class[] primFromTypes, Class[] toTypes, boolean[] isParam, boolean mixTypes) { // In the case repeatLastParameter was true, then the two methods may have // different numbers of parameters. We need to compare only the non-repeated // parameters, which is the number of input parameters. int checkCount = fromTypes.length; if (toTypes.length < checkCount) checkCount = toTypes.length; for (int i = 0; i < checkCount; i++) { Class fromClass = fromTypes[i]; Class toClass = toTypes[i]; // this means an untyped null was passed in. Can only ever be in the // from side as the null can only be in the signature passed in by // the caller of findPublicMethod. Any signatures of existing methods // are always typed. if (fromClass == null) { // primitive types are only considered on // the 2nd pass if (toClass.isPrimitive()) { if ((primFromTypes == null) // first pass || (isParam != null && ! isParam[i])) { return false; } } continue; } if ((!classConvertableFromTo(fromClass, toClass, mixTypes)) && // primitive type, if any, also doesn't work ((primFromTypes == null) || (primFromTypes[i] == null) || (!classConvertableFromTo(primFromTypes[i], toClass, mixTypes)) )) return false; } return true; } /** * Can we convert a fromClass to toClass. * "mixTypes" is a flag to show if object/primitive type conversion is * possible; this is used for comparing two candidate methods in the * second pass of the two pass method resolution. * * @param fromClass from class * @param toClass to class * @param mixTypes mixing object/primitive types for comparison **/ protected boolean classConvertableFromTo(Class fromClass, Class toClass, boolean mixTypes) { if (toClass.isAssignableFrom(fromClass)) { return true; } // When comparing two candidate methods to see which one is closer, // we want to mix object type and primitive type, because they could // both be chosen in the second pass. But when deciding if a method // is qualified (to be a candidate), we do not want to mix types at // any time, the reason is that we can NOT do more than one step // conversion: for example, input parameter is BigDecimal, we convert // it to double for method resolution, we can NOT convert it again to // Double to match a method. "(paramTypes, primParamTypes)" already // includes all the one-step conversions. But at any time we do want // to see if two primitives are convertable. if ((!(toClass.isPrimitive() && fromClass.isPrimitive())) && (!mixTypes)) return false; // There are nine predefined Class objects to represent the eight // primitive Java types and void. We also handle prim vs. non-prim // conversion of the same type. boolean and double are only convertable // to themseleves. void should never be seen here. In the second pass // we treat primitive type and the corrsponding non-primitive type // uniformly String fromName = fromClass.getName(), toName = toClass.getName(); if ((fromClass == Boolean.TYPE) || fromName.equals(nonPrimTypeNames[0])) { if ((toClass == Boolean.TYPE) || toName.equals(nonPrimTypeNames[0])) return true; } else if ((fromClass == Byte.TYPE) || fromName.equals(nonPrimTypeNames[1])) { if ((toClass == Byte.TYPE) || toName.equals(nonPrimTypeNames[1]) || // we never need to see if toClass is of wider "object" type, // because a wider "object" type and a narrower "primitive" // type can never both be candidate, eg, "int" and "Long" can // never both accomodate the same parameter; while "long" and // "Integer" can. (toClass == Short.TYPE) || (toClass == Integer.TYPE) || (toClass == Long.TYPE) || (toClass == Float.TYPE) || (toClass == Double.TYPE) ) return true; } else if ((fromClass == Character.TYPE) || fromName.equals(nonPrimTypeNames[2])) { if ((toClass == Character.TYPE) || toName.equals(nonPrimTypeNames[2]) || (toClass == Integer.TYPE) || (toClass == Long.TYPE) || (toClass == Float.TYPE) || (toClass == Double.TYPE) ) return true; } else if ((fromClass == Short.TYPE) || fromName.equals(nonPrimTypeNames[3])) { if ((toClass == Short.TYPE) || toName.equals(nonPrimTypeNames[3]) || (toClass == Integer.TYPE) || (toClass == Long.TYPE) || (toClass == Float.TYPE) || (toClass == Double.TYPE) ) return true; } else if ((fromClass == Integer.TYPE) || fromName.equals(nonPrimTypeNames[4])) { if ((toClass == Integer.TYPE) || toName.equals(nonPrimTypeNames[4]) || (toClass == Long.TYPE) || (toClass == Float.TYPE) || (toClass == Double.TYPE) ) return true; } else if ((fromClass == Long.TYPE) || fromName.equals(nonPrimTypeNames[5])) { if ((toClass == Long.TYPE) || toName.equals(nonPrimTypeNames[5]) || (toClass == Float.TYPE) || (toClass == Double.TYPE) ) return true; } else if ((fromClass == Float.TYPE) || fromName.equals(nonPrimTypeNames[6])) { if ((toClass == Float.TYPE) || toName.equals(nonPrimTypeNames[6]) || (toClass == Double.TYPE) ) return true; } else if ((fromClass == Double.TYPE) || fromName.equals(nonPrimTypeNames[7])) { if ((toClass == Double.TYPE) || toName.equals(nonPrimTypeNames[7])) return true; } return false; } /** * Translate a JVM-style type descriptor to a Java-language-style type * name. * * @param vmTypeName The String that contains the JVM type name * * @return The Java-language-style type name */ public static String readableClassName(Class clazz) { if (!clazz.isArray()) return clazz.getName(); int arrayDepth = 0; do { arrayDepth++; clazz = clazz.getComponentType(); } while (clazz.isArray()); StringBuffer sb = new StringBuffer(clazz.getName()); for (int i = 0; i < arrayDepth; i++) { sb.append("[]"); } return sb.toString(); } /** * Get the declaring class for a method. * * @param method A Member describing a method * * @return A String with the declaring class * * @see Member#getDeclaringClass */ public String getDeclaringClass(Member method) { return method.getDeclaringClass().getName(); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -