📄 classfile.java
字号:
item = new ClassItem(name, this, field); m_itemMap.put(field, item); } return item; } } /** * Get information for field. This can only be used with existing classes. * If the field is not found directly, superclasses are checked for * inherited fields matching the supplied name. * * @param name field name * @return field information * @throws JiBXException if field not found */ public ClassItem getField(String name) throws JiBXException { Field field = getAccessibleField(name); if (field == null) { throw new JiBXException("Field " + name + " not found in class " + m_name); } else { ClassItem item = (ClassItem)m_itemMap.get(field); if (item == null) { item = new ClassItem(name, this, field); m_itemMap.put(field, item); } return item; } } /** * Get array of methods defined by class or interface. In the case of an * interface, this merges all methods from superinterfaces in the array * returned. * * @return array of methods defined by class */ private Method[] getMethods() { if (m_methods == null) { // start with methods defined directly Method[] methods = m_curClass.getMethods(); if (m_curClass.isInterface() && m_superInterfaces.length > 0) { // for interface extending other interfaces, merge methods ArrayList merges = new ArrayList(); for (int i = 0; i < methods.length; i++) { merges.add(methods[i]); } for (int i = 0; i < m_superInterfaces.length; i++) { methods = m_superInterfaces[i].getMethods(); for (int j = 0; j < methods.length; j++) { merges.add(methods[j]); } } // set merged array methods = (Method[])merges.toArray(new Method[merges.size()]); } // cache the created method array m_methods = methods; } return m_methods; } /** * Get array of methods defined by class. * * @return array of methods defined by class */ public ClassItem[] getMethodItems() { if (m_curClass == null) { return EMPTY_CLASS_ITEMS; } else { Method[] methods = getMethods(); ClassItem[] items = new ClassItem[methods.length]; for (int i = 0; i < methods.length; i++) { Method method = methods[i]; items[i] = new ClassItem(method.getName(), this, method); } return items; } } /** * Get internal information for method without respect to potential trailing * arguments or return value. This can only be used with existing classes. * If the method is not found directly, superclasses are checked for * inherited methods matching the supplied name. This compares the supplied * partial signature against the actual method signature, and considers it * a match if the actual sigature starts with the supplied signature.. * * @param name method name * @param sig partial method signature to be matched * @return method information, or <code>null</code> if method not found */ protected Method getAccessibleMethod(String name, String sig) { // only check loadable classes if (m_curClass != null) { // check for match to method defined in class Method[] methods = getMethods(); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; if (method.getName().equals(name)) { if (method.getSignature().startsWith(sig)) { return method; } } } // try match to method inherited from superclass if (m_superClass != null) { Method method = m_superClass.getAccessibleMethod(name, sig); if (method != null && ((m_isSamePackage && !method.isPrivate()) || method.isPublic() || method.isProtected())) { return method; } } } return null; } /** * Get information for method without respect to potential trailing * arguments or return value. This can only be used with existing classes. * If the method is not found directly, superclasses are checked for * inherited methods matching the supplied name. This compares the supplied * partial signature against the actual method signature, and considers it * a match if the actual sigature starts with the supplied signature.. * * @param name method name * @param sig partial method signature to be matched * @return method information, or <code>null</code> if method not found */ public ClassItem getMethod(String name, String sig) { Method method = getAccessibleMethod(name, sig); if (method == null) { return null; } else { ClassItem item = (ClassItem)m_itemMap.get(method); if (item == null) { item = new ClassItem(name, this, method); m_itemMap.put(method, item); } return item; } } /** * Get information for method matching one of several possible signatures. * This can only be used with existing classes. If a match is not found * directly, superclasses are checked for inherited methods matching the * supplied name and signatures. The signature variations are checked in * the order supplied. * * @param name method name * @param sigs possible signatures for method (including return type) * @return method information, or <code>null</code> if method not found */ public ClassItem getMethod(String name, String[] sigs) { Method method = null; for (int i = 0; method == null && i < sigs.length; i++) { method = getAccessibleMethod(name, sigs[i]); } if (method == null) { return null; } else { ClassItem item = (ClassItem)m_itemMap.get(method); if (item == null) { item = new ClassItem(name, this, method); m_itemMap.put(method, item); } return item; } } /** * Check for match to specified access level. This treats a field or method * as matching if the access level is the same as or more open than the * required level. * * @param item information for field or method to be checked * @param access required access level for match * @return <code>true</code> if access level match, <code>false</code> if * not */ private static boolean matchAccess(FieldOrMethod item, int access) { if (item.isPublic()) { return true; } else if (item.isProtected()) { return access <= PROTECTED_ACCESS; } else if (item.isPrivate()) { return access == PRIVATE_ACCESS; } else { return access <= PACKAGE_ACCESS; } } /** * Check if one type is assignment compatible with another type. This is an * ugly replacement for apparently broken BCEL code. * * @param have type being checked * @param need type needed * @return <code>true</code> if compatible, <code>false</code> if not */ private static boolean isAssignmentCompatible(Type have, Type need) { if (have.equals(need)) { return true; } else { try { return ClassItem.isAssignable(have.toString(), need.toString()); } catch (JiBXException e) { throw new IllegalStateException ("Internal error: Unable to access data for " + have.toString() + " or " + need.toString() + ":\n" + e.getMessage()); } } } /** * Get information for best matching method. This tries to find a method * which matches the specified name, return type, and argument types. If an * exact match is not found it looks for a method with a return type that * is extended or implemented by the specified type and arguments that are * extended or implemented by the specified types. This can only be used * with existing classes. If the method is not found directly, superclasses * are checked for inherited methods. * * @param name method name * @param access access level required for matching methods * @param ret return value type (<code>null</code> if indeterminant) * @param args argument value types * @return method information, or <code>null</code> if method not found */ private Method getBestAccessibleMethod(String name, int access, Type ret, Type[] args) { // just fail for classes that aren't loadable if (m_curClass == null) { return null; } // check for match to method defined in class Method[] methods = getMethods(); Method best = null; int diff = Integer.MAX_VALUE; for (int i = 0; i < methods.length; i++) { Method method = methods[i]; if (method.getName().equals(name) && matchAccess(method, access)) { // make sure the return type is compatible boolean match = true; int ndiff = 0; if (ret != null) { Type type = method.getReturnType(); match = isAssignmentCompatible(ret, type); } if (match) { // check closeness of argument types Type[] types = method.getArgumentTypes(); if (args.length == types.length) { for (int j = 0; j < args.length; j++) { Type type = types[j]; Type arg = args[j]; if (!type.equals(arg)) { ndiff++; match = isAssignmentCompatible(arg, type); if (!match) { break; } } } } else { match = false; } } if (match && ndiff < diff) { best = method; } } } if (best != null) { return best; } // try methods inherited from superclass if no match found if (m_superClass != null) { if (access < PROTECTED_ACCESS) { if (m_isSamePackage) { access = PACKAGE_ACCESS; } else { access = PROTECTED_ACCESS; } } return m_superClass.getBestAccessibleMethod(name, access, ret, args); } else { return null; } } /** * Get information for best matching method. This tries to find a method * which matches the specified name, return type, and argument types. If an * exact match is not found it looks for a method with a return type that * is extended or implemented by the specified type and arguments that are * extended or implemented by the specified types. This can only be used * with existing classes. If the method is not found directly, superclasses * are checked for inherited methods. * * @param name method name * @param ret return value type (<code>null</code> if indeterminant) * @param args argument value types * @return method information, or <code>null</code> if method not found */ public ClassItem getBestMethod(String name, String ret, String[] args) { Type rtype = null; if (ret != null) { rtype = ClassItem.typeFromName(ret); } Type[] atypes = new Type[args.length]; for (int i = 0; i < args.length; i++) { atypes[i] = ClassItem.typeFromName(args[i]); } Method method = getBestAccessibleMethod(name, PRIVATE_ACCESS, rtype, atypes); if (method == null) { return null; } ClassItem item = (ClassItem)m_itemMap.get(method); if (item == null) { item = new ClassItem(name, this, method); m_itemMap.put(method, item); } return item; } /** * Get information for initializer. This can only be used with existing * classes. Only the class itself is checked for an initializer matching * the argument list signature. * * @param sig encoded argument list signature * @return method information, or <code>null</code> if method not found */ public ClassItem getInitializerMethod(String sig) { // only check if loadable class if (m_curClass != null) { // check for match to method defined in class Method[] methods = getMethods(); for (int i = 0; i < methods.length; i++) { Method method = methods[i]; if (method.getName().equals("<init>")) { if (method.getSignature().startsWith(sig)) { ClassItem item = (ClassItem)m_itemMap.get(method); if (item == null) { item = new ClassItem("<init>", this, method); m_itemMap.put(method, item); } return item; } } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -