📄 classinspector.java
字号:
/* Now check to see if there is a declared field that hides the public field. */ try { Field declaredField = receiverClass.getDeclaredField(fieldName); if (SanityManager.DEBUG) { if ((declaredField.getModifiers() & Modifier.PUBLIC) == Modifier.PUBLIC) SanityManager.THROWASSERT("declared field not expected to be public here " + declaredField); } } catch (NoSuchFieldException nsfe) { // no field hides the public field in the super class return publicField; } } } catch (ClassNotFoundException cnfe) { e = cnfe; } catch (NoSuchFieldException nsfep) { e = nsfep; } catch (SecurityException se) { e = se; } throw StandardException.newException( staticField ? SQLState.LANG_NO_STATIC_FIELD_FOUND : SQLState.LANG_NO_FIELD_FOUND, e, fieldName, receiverType); } /** * Find a public constructor that implements a given signature. * The signature is given using the full Java class names of the types. <BR> * A untyped null paramter is indicated by passing in an empty string ("") * as its class name. * * @param receiverTypes The class name of the receiver * @param parmTypes An array of class names representing the * parameter types. Pass a zero-element array if * there are no parameters. * @param primParmTypes This is used in the second pass of the two-pass * method resolution algorithm. Use primitive type * if it has one, otherwise use same object type * @param isParam Array of booleans telling whether parameter is a ?. * * @return A Member representing the matching constructor. Returns null * if no such constructor. * * @exception ClassNotFoundException One or more of the classes does * not exist. * @exception StandardException Thrown on ambiguous constructor invocation. * * @see Member * @see Modifier */ public Member findPublicConstructor(String receiverType, String[] parmTypes, String[] primParmTypes, boolean[] isParam) throws ClassNotFoundException, StandardException { Class receiverClass = getClass(receiverType); if (receiverClass == null) return null; // arrays, primitives, and interfaces do not have constructors if (receiverClass.isArray() || receiverClass.isPrimitive() || receiverClass.isInterface()) { return null; } // convert the parameter types to classes Class[] paramClasses = new Class[parmTypes.length]; Class[] primParamClasses = null; if (primParmTypes != null) primParamClasses = new Class[primParmTypes.length]; boolean unknownParameters = false; for (int i = 0; i < paramClasses.length; i++) { paramClasses[i] = getClass(parmTypes[i]); if (paramClasses[i] == null) unknownParameters = true; if (primParmTypes == null) continue; if (primParmTypes[i].equals(parmTypes[i])) // no separate primitive primParamClasses[i] = null; else primParamClasses[i] = getClass(primParmTypes[i]); } try { if (!unknownParameters && (primParmTypes == null)) { // look for an exact match for first pass Member method = receiverClass.getConstructor(paramClasses); return method; } } catch (NoSuchMethodException nsme) { // no overloading possible if there are no arguments if (paramClasses.length == 0) return null; // now the tricky method resolution } // name is only used for debugging return resolveMethod(receiverClass, "<init>", paramClasses, primParamClasses, isParam, false, false, receiverClass.getConstructors()); } /** * Get the parameter types for a method described by a Member as a String[]. * * @param method A Member describing a method * * @return A String[] describing the parameters of the method */ public String[] getParameterTypes(Member method) { Class[] parameterClasses; if (method instanceof Method) { parameterClasses = ((Method) method).getParameterTypes(); } else { parameterClasses = ((Constructor) method).getParameterTypes(); } String[] parameterTypes = new String[parameterClasses.length]; for (int i = 0; i < parameterTypes.length; i++) { parameterTypes[i] = ClassInspector.readableClassName(parameterClasses[i]); } return parameterTypes; } /** * Determine whether a type is a Java primitive, like int or boolean * * @param typeName The name of the Java type * * @return true if it's a primitive type */ public static boolean primitiveType(String typeName) { for (int i = 0; i < primTypeNames.length; i++) { if (typeName.equals(primTypeNames[i])) return true; } return false; } /** * Tricky function to resolve a method. If primParamClasses is null * we know it's first pass. First pass try to match as all "object" * types, second pass try to match any combination of "object" and * "primitive" types. Find the closest match among all the qualified * candidates. If there's a tie, it's ambiguous. * * @param receiverClass the class who holds the methods * @param methodName the name of method * @param paramClasses object type classes of input parameters * @param primParamClasses primitive type classes or null * @param isParam isParam (for ?) array * @param staticMethod static method or not * @param Member[] methods method stack * @return the matched method * **/ private Member resolveMethod( Class receiverClass, String methodName, Class[] paramClasses, Class[] primParamClasses, boolean[] isParam, boolean staticMethod, boolean repeatLastParameter, Member[] methods) throws StandardException { if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("MethodResolutionInfo")) { SanityManager.DEBUG("MethodResolutionInfo", "MRI - Begin method resolution trace for " + methodName + "() with " + paramClasses.length + (repeatLastParameter ? "+" : "") + " parameters"); for (int parmCtr = 0; parmCtr < paramClasses.length; parmCtr++) { SanityManager.DEBUG("MethodResolutionInfo", "MRI - Parameter #" + parmCtr + " is of type " + (paramClasses[parmCtr] == null ? "null" : paramClasses[parmCtr].getName())); } } } /* Step through all the methods available in this class */ int candidateIndex = -1; boolean firstTimeAround = true; boolean ambiguous; boolean somethingChanged; do { ambiguous = false; somethingChanged = false;nextMethod: for (int i = 0; i < methods.length; i++) { Member currentMethod = methods[i]; // on second and later times around there will be null entries // also, don't compare ourself to ourself if ((currentMethod == null) || (i == candidateIndex)) { continue; } // must have the same number of parameters Class[] currentMethodParameters = currentMethod instanceof Method ? ((Method) currentMethod).getParameterTypes(): ((Constructor) currentMethod).getParameterTypes(); // only check the basic stuff once if (firstTimeAround) { if (repeatLastParameter) { // match any number of parameters greater or equal to // the passed in number, but repeating the last type. if (currentMethodParameters.length < paramClasses.length) { methods[i] = null; // remove non-applicable methods continue; } } else { // regular match on parameter count if (currentMethodParameters.length != paramClasses.length) { methods[i] = null; // remove non-applicable methods continue; } } /* Look only at methods that match the modifiers */ if (staticMethod && !Modifier.isStatic(currentMethod.getModifiers())) { methods[i] = null; // remove non-applicable methods continue; } /* Look only at methods with the right name */ if (!methodName.startsWith("<")) { if ( ! methodName.equals(currentMethod.getName())) { methods[i] = null; // remove non-applicable methods continue; } } if (repeatLastParameter) { // With N parameters requested check all parameters from N-1 to end are equal // to the requested parameter. for (int pr = paramClasses.length - 1; pr < currentMethodParameters.length; pr++) { if (!currentMethodParameters[pr].equals(paramClasses[paramClasses.length - 1])) { methods[i] = null; // remove non-applicable methods continue nextMethod; } } } } if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("MethodResolutionInfo")) { SanityManager.DEBUG("MethodResolutionInfo", "MRI - Considering :" + currentMethod.toString()); } } // can the required signature be converted to those of this method if (!signatureConvertableFromTo(paramClasses, primParamClasses, currentMethodParameters, isParam, false)) { if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("MethodResolutionInfo")) { SanityManager.DEBUG("MethodResolutionInfo", "MRI - Skipping :" + currentMethod.toString()); } } methods[i] = null; // remove non-applicable methods continue; } if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("MethodResolutionInfo")) { SanityManager.DEBUG("MethodResolutionInfo", "MRI - Match found "); } } /* Is this the first match? */ if (candidateIndex == -1) { candidateIndex = i; if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("MethodResolutionInfo")) { SanityManager.DEBUG("MethodResolutionInfo", "MRI - Current method is now candidate"); } } continue; } /* Not the first match, so find out which one, if either one, * has the best match on the parameters. (No narrowing * conversions.) 15.11 of Java Language Specification. */ Member candidateMethod = methods[candidateIndex]; // If the candidate method is more specific than the current // method then the candidate method is still the maximally specific method // Note at this point we could still have a ambiguous situation. boolean candidateMoreOrEqual = isMethodMoreSpecificOrEqual( candidateMethod, currentMethod, isParam); boolean currentMoreOrEqual = isMethodMoreSpecificOrEqual( currentMethod, candidateMethod, isParam); if (candidateMoreOrEqual && ! currentMoreOrEqual) { if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("MethodResolutionInfo")) { SanityManager.DEBUG("MethodResolutionInfo", "MRI - Candidate is still maximally specific"); } } methods[i] = null; // remove non-applicable methods continue; } // if the current method is more specific than the candidiate // method then it becomes the new maximally specific method // Note at this point we could still have a ambiguous situation. if (currentMoreOrEqual && ! candidateMoreOrEqual) { if (SanityManager.DEBUG) { if (SanityManager.DEBUG_ON("MethodResolutionInfo")) { SanityManager.DEBUG("MethodResolutionInfo", "MRI - Current method is now candidate, replaced previous candidate"); } } methods[candidateIndex] = null; // remove non-applicable methods candidateIndex = i; somethingChanged = true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -