CtMethod cm = ((CtClassType)cc).getMethodsCache();
while (cm != null) {
if (Modifier.isPublic(cm.getModifiers()))
- h.put(cm, cm);
+ h.put(cm.getStringRep(), cm);
cm = cm.next;
}
*/
public final class CtMethod extends CtBehavior {
protected CtMethod next;
- protected int cachedHashCode;
+ protected String cachedStringRep;
CtMethod(MethodInfo minfo, CtClass declaring) {
super(declaring, minfo);
next = null;
- cachedHashCode = 0;
+ cachedStringRep = null;
}
/**
* the hash codes for the two methods are equal.
*/
public int hashCode() {
- /* This method is overridden in ExistingMethod for optimization.
- */
- if (cachedHashCode == 0) {
- String signature
- = methodInfo.getName() + ':' + methodInfo.getDescriptor();
+ return getStringRep().hashCode();
+ }
- // System.identityHashCode() returns 0 only for null.
- cachedHashCode = System.identityHashCode(signature.intern());
- }
+ /* This method is also called by CtClassType.getMethods0().
+ */
+ final String getStringRep() {
+ if (cachedStringRep == null)
+ cachedStringRep = methodInfo.getName()
+ + Descriptor.getParamDescriptor(methodInfo.getDescriptor());
- return cachedHashCode;
+ return cachedStringRep;
}
/**
*/
public boolean equals(Object obj) {
return obj != null && obj instanceof CtMethod
- && obj.hashCode() == hashCode();
+ && ((CtMethod)obj).getStringRep().equals(getStringRep());
}
/**
while (it.hasNext()) {
MethodInfo minfo = (MethodInfo)it.next();
if (minfo.getName().equals(name)
- && Descriptor.eqSignature(minfo.getDescriptor(), descriptor))
+ && Descriptor.eqParamTypes(minfo.getDescriptor(), descriptor))
throw new CannotCompileException("duplicate method: " + name);
}
}
}
/**
- * Returns true if desc1 and desc2 has the same signature.
+ * Returns true if the list of the parameter types of desc1 is equal to
+ * that of desc2.
+ * For example, "(II)V" and "(II)I" are equal.
*/
- public static boolean eqSignature(String desc1, String desc2) {
+ public static boolean eqParamTypes(String desc1, String desc2) {
if (desc1.charAt(0) != '(')
return false;
}
}
+ /**
+ * Returns the signature of the given descriptor. The signature does
+ * not include the return type. For example, the signature of "(I)V"
+ * is "(I)".
+ */
+ public static String getParamDescriptor(String decl) {
+ return decl.substring(0, decl.indexOf(')') + 1);
+ }
+
/**
* Returns the <code>CtClass</code> object representing the return
* type specified by the given descriptor.
return methods;
Class baseclass = getJavaClass();
- Method[] allmethods = baseclass.getMethods();
+ Method[] allmethods = baseclass.getDeclaredMethods();
int n = allmethods.length;
methods = new Method[n];
for (int i = 0; i < n; ++i) {
Method m = allmethods[i];
- if (m.getDeclaringClass() == baseclass) {
- String mname = m.getName();
- if (mname.startsWith(methodPrefix)) {
- int k = 0;
- for (int j = methodPrefixLen;; ++j) {
- char c = mname.charAt(j);
- if ('0' <= c && c <= '9')
- k = k * 10 + c - '0';
- else
- break;
- }
-
- methods[k] = m;
+ String mname = m.getName();
+ if (mname.startsWith(methodPrefix)) {
+ int k = 0;
+ for (int j = methodPrefixLen;; ++j) {
+ char c = mname.charAt(j);
+ if ('0' <= c && c <= '9')
+ k = k * 10 + c - '0';
+ else
+ break;
}
+
+ methods[k] = m;
}
}
* <p>If a class is reflective,
* then all the method invocations on every
* instance of that class are intercepted by the runtime
- * metaobject controlling that instance.
- * To do this, the original class file representing a reflective class:
+ * metaobject controlling that instance. The methods inherited from the
+ * super classes are also intercepted except final methods. To intercept
+ * a final method in a super class, that super class must be also reflective.
+ *
+ * <p>To do this, the original class file representing a reflective class:
*
* <ul><pre>
* class Person {
return;
m2 = m;
+ if (Modifier.isFinal(mod)) {
+ mod &= ~Modifier.FINAL;
+ m2.setModifiers(mod);
+ }
}
else {
if (Modifier.isFinal(mod))