我在Java中使用动态类型实现了简单的解释语言。不幸的是我遇到了以下问题。测试以下代码时:
def main() {
def ks = Map[[1, 2]].keySet();
return ks.size();
}
我偶然发现了以下异常:
java.lang.IllegalAccessException: class is not public: java.util.HashMap$KeySet.size()int/invokeSpecial
当然,这是因为HashMap $ KeySet类具有“包”可见性这一事实。这意味着当我调用它的“size()”方法时,我从类中调用我的代码不可见的方法。 Java很容易避免这个问题 - 方法keySet()返回类型为Set的值,因此使用的方法size()在公共和抽象类“Set”中声明。
我的问题是:有没有人有想法,应该如何以通用方式处理?在“一般”的情况下,我的意思不仅仅是这个简单的案例,我可以通过整个继承链找到这个方法的“第一个声明”,还有以下病理案例:
interface I1 {
public void foo();
}
interface I2 {
public void foo();
}
interface I3 {
public void foo();
}
class C implements I1, I2, I3 {
public void foo() { .... }
}
我目前的印象是我可以忽略那些病态案例并选择任何匹配方法,理由是如果这样的对象存在,那么它的创建是成功的,所以它的编译是成功的,所以所有这些方法都有相同的签名,因为在Java根据查看对象的方式(如I1,I2或I3)无法指定这些方法的不同实现,那么结果将始终相同。
任何帮助将不胜感激。
答案 0 :(得分:0)
好的,这是我的解决方案。它不是很好,但是嘿,无论有用吗:
public static Method findMethod(Class<?> cls, String name, Class<?>[] fa) {
System.out.println("Checking class " + cls + " for method " + name);
// since it is called recursively, we want to stop some day, and when we are
// passed null (so most getSuperclass was called on Object.class or something similar)
if (cls == null) {
return null;
}
Method m = null;
if ((m = findMethod(cls.getSuperclass(), name, fa)) != null) {
return m;
}
// ok, if we're here, then m is null. so check if cls is public. it must be public, because
// otherwise we won't be able to call it - we are definitely in different package. if class
// isn't public, then check interfaces.
if (!Modifier.isPublic(cls.getModifiers())) {
System.out.println("Class is not public, and superclasses do not contain method " + name);
System.out.println("Checking all interfaces");
for (Class<?> iface: cls.getInterfaces()) {
if ((m = findMethod(iface, name, fa)) != null) {
return m;
}
}
}
return findMethodInClass(cls, name, fa);
}
private static Method findMethodInClass(Class<?> cls, String name, Class<?>[] fa) {
Method m = null;
// scan all methods and move plausible candidates to the start of an array
Method[] mm = cls.getMethods();
int n = 0;
for (int i = 0 ; i < mm.length ; ++i) {
if (checkMethod(mm[i], name, fa)) {
mm[n++] = mm[i];
}
}
if (n > 1) {
System.out.println("Caveat: we have to perform more specific test. n == " + n);
System.out.println("class: " + cls + "\nname: " + name);
for (int i = 0 ; i < n ; ++i) {
System.out.println(mm[i]);
}
}
if (n > 0) {
m = mm[0];
}
return m;
}
在findMethodInClass中调用的方法checkMethod()只检查名称是否正确,以及调用哪个方法的参数或多或少与正式参数列表匹配。它的实现留给读者一个简单的练习。有什么意见吗?