我正在尝试获取在 java 8 中声明方法的“最高”类/接口
示例:
package pkg;
public class Classes {
public static interface IInterface {
void iMethod();
}
public abstract static class AClass implements IInterface {
protected abstract void aMethod();
}
public static class SubClass extends AClass {
@Override
public void iMethod() {
System.out.println("Sub iMethod");
}
@Override
protected void aMethod() {
System.out.println("Sub aMethod");
}
}
}
// getFirstDeclarator(Classes.SubClass.class, iMethod) -> AClass
// getFirstDeclarator(Classes.SubClass.class, aMethod) -> IInterface
这就是我尝试做的,只要该方法是公共的,它就可以完美工作(因为
Class#getMethod
仅适用于可访问的方法),除了它也应该适用于私有/受保护的方法
import pkg.Classes;
import java.lang.reflect.Method;
public class Main {
public static void main(String[] args) throws Exception {
Method iMethod = Classes.SubClass.class.getDeclaredMethod("iMethod");
Method aMethod = Classes.SubClass.class.getDeclaredMethod("aMethod");
System.out.println(getFirstDeclarator(Classes.SubClass.class, iMethod));
System.out.println(getFirstDeclarator(Classes.SubClass.class, aMethod));
}
/**
* Get the declaring class or interface of a method.
* If the method is overridden, this method will return the highest superclass or interface that declares it.
*/
public static Class<?> getFirstDeclarator(Class<?> startClass, Method method) {
Class<?> superClass = startClass.getSuperclass();
if (superClass != null) {
try {
// The problem is here: Class#getMethod only works for accessible methods
superClass.getMethod(method.getName(), method.getParameterTypes());
return getFirstDeclarator(superClass, method);
} catch (NoSuchMethodException e) {
// The method is not declared in the superclass
}
}
for (Class<?> iface : startClass.getInterfaces()) {
try {
iface.getMethod(method.getName(), method.getParameterTypes()); // Same problem here
return getFirstDeclarator(iface, method);
} catch (NoSuchMethodException e) {
// The method is not declared in the interface
}
}
return startClass;
}
}
您知道是否有办法使其适用于不可访问的方法吗?或者还有别的办法吗?
是的,请使用
.getDeclaredMethods()
代替。
有 2 件事相关:
public
/protected
标记的方法。 getDeclaredMethods()
就是这样做的。 getMethods()
没有。j.l.Class
对象的类中直接声明的方法,而且还需要其父系。 getMethods()
就是这样做的。 getMethods()
没有。
getDeclaredMethods()
检查的
j.l.Class
实例,直到 c = c.getSuperclass()
为空(或者,如果您愿意,可以使用 c
以避免循环查找您可能不感兴趣的对象)。您不再见证您感兴趣的方法的那个类?无论您在上一个循环中上过什么课,都是正确的答案。更新包含“答案”的变量,直到该方法消失,然后返回该答案。
请注意,对于接口,您想要的整个概念
并不存在。不存在“第一声明者”这样的东西。简单地说:
c == Object.class
当我打电话给
interface Gun {
void shoot(Person p);
}
interface Camera {
void shoot(Person p);
}
class ReallyBadIdea implements Camera, Gun {
@Override public void shoot(Person p) {
System.out.println("Psychopathic news reporter?");
}
}
时,正确答案是什么?
除非你的答案是“抛出异常”,否则你就错了。Camera 和 Gun 都有理由声称自己是第一个声明者。选择“第一个声明的”是不正确的,因为 java 不遗余力地规定
getFirstDeclarator(ReallyBadIdea.class, ReallyBadIdea.class.getMethod("shoot", Person.class))
接口的顺序并不重要;如果你现在突然介绍说它确实如此,那就太糟糕了。从架构上来说,这是一个致命的错误。充其量你可以颁布“任意一个”,但除非你真正涉及
implements
,否则你仍然会引入顺序相关性。您可能希望重新审视是什么让您认为您需要这个。有点X/Y 问题的味道。您有一些未知的问题(从您的问题中尚不清楚)。你想到了一个解决方案:“我知道!我只要得到第一个声明符,那会有帮助的!” ....“哦,等等,这比我想象的要困难,让我向 Stack Overflow 询问一下。”。
但是,实际上,问题在于您的方法可能是错误的,因为“第一个声明符”应该无关紧要,而且实际上甚至对于接口来说也是无法回答的。 “第一个声明者”将自己仅限于类可能是可以接受的设计。但是当涉及接口时“第一个声明符”呢?我很难想象
that是(部分)适当解决方案的任何问题。