如何访问父类中定义的方法?这里我有以下继承:
BaseDTO
|
SortableDTO<T>
|
BaseSearchArticleDTO
|
SearchNeedsYearPlus2ArticleDTO
方法public void setSortCriteria1(SortDataBean<T> sortCriteria1)
在SortableDTO<T>
中定义。当我尝试通过类SearchNeedsYearPlus2ArticleDTO
的引用来访问此方法时,如:
SearchNeedsYearPlus2ArticleDTO dto = new SearchNeedsYearPlus2ArticleDTO();
Method setSortCriteria1 = dto.getClass().getDeclaredMethod("setSortCriteria1",SortDataBean.class);
我得到了:
java.lang.NoSuchMethodException: com.mhis.posm.web.dto.article.search.SearchNeedsYearPlus2ArticleDTO.setSortCriteria1(com.mhis.posm.transversal.bean.sort.SortDataBean)
但如果我这样做:
Method setSortCriteria1 = dto.getClass().getSuperclass().getSuperclass().getDeclaredMethod("setSortCriteria1",SortDataBean.class);
它正在发挥作用。然后我发现了我正在做的错误。
返回一个反映指定的声明方法的Method对象 此Class对象表示的类或接口。名字 parameter是一个String,它指定所需的简单名称 方法,而parameterTypes参数是Class对象的数组 以声明的顺序标识方法的形式参数类型。 如果在a中声明了多个具有相同参数类型的方法 class,其中一个方法的返回类型更多 特定于任何其他方法,返回该方法;除此以外 其中一种方法是任意选择的。如果名称是“&lt; init&gt;”或 “&LT; clinit&gt;” 中引发NoSuchMethodException。
返回反映指定公共成员的Method对象 此Class对象表示的类或接口的方法。该 name参数是一个String,指定所需的简单名称 方法。 parameterTypes参数是Class对象的数组 按声明的顺序标识方法的形式参数类型。如果 parameterTypes为null,将其视为空数组。
如果名称是“&lt; init&gt;”或“&lt; clinit&gt;”引发NoSuchMethodException。 否则,要反映的方法由算法确定 接下来。设C为该对象表示的类:
搜索C以查找任何匹配方法。如果没有找到匹配方法,则在C的超类上递归调用步骤1的算法。
如果在上面的步骤1中没有找到方法,则搜索C的超接口以寻找匹配方法。如果是这样的话 方法被发现,它被反映出来。
要在类C中查找匹配方法:如果C只声明一个具有指定名称和完全相同的形式参数类型的公共方法,那么这就是方法 反映。如果在C中找到多个这样的方法,那么其中一个 这些方法的返回类型比任何方法都更具体 其他人,这种方法得到反映;否则其中一种方法是 任意选择。
请注意,类中可能有多个匹配方法,因为Java时 语言禁止类声明具有相同签名的多个方法但是 不同的返回类型,Java虚拟机没有。这增加了灵活性 在虚拟机中可以用来实现各种语言功能。例如, 协变返回可以用桥接方法实现;桥梁法和 被覆盖的方法将具有相同的签名但返回类型不同。
所以我需要为我的案件打电话getMethod
,这解决了这个问题。
现在我有一个实用程序类:
public class ReflectionUtils{
private ReflectionUtils() {
}
public static <T> Method getMethod(Class<T> instanceClass, String name, Class<?>... parameterTypes) {
Method method = null;
try {
method = instanceClass.getDeclaredMethod(name,parameterTypes);
}catch (Exception e) {
}
return method;
}
public static Object invokeOnMethod(Method method, Object obj, Object... args) {
try {
method.setAccessible(true);
return method.invoke(obj,args);
}catch (Exception e) {
return null;
}
}
}
如果我想更改方法public static <T> Method getMethod(Class<T> instanceClass, String name, Class<?>... parameterTypes)
以便它捕获任何访问修饰符的方法并且属于任何地方,封闭类或其超类或接口,我该怎么办?
答案 0 :(得分:3)
根据继承主体,Dervied Classes不继承private
方法。因此,在您的示例中,SearchNeedsYearPlus2ArticleDTO
实例无法访问BaseSearchArticleDTO
中声明的私有方法。
因此,使用Class
SearchNeedsYearPlus2ArticleDTO
对象,您可以访问
SearchNeedsYearPlus2ArticleDTO
(private, protected, public
)protected, public
)IMO你可以有像这样的回退机制
try {
Method m = instanceClass.getMethod(name); // try to get inherited method
m.setAccessible(true); // if protected setAccessible
m.invoke(instanceClass.newInstance());
} catch(NoSuchMethodException ne) {
try {
Method m = instanceClass.getDeclaredMethod(name); // try to get declared method in the same class
m.setAccessible(true); // if private setAccessible
m.invoke(instanceClass.newInstance());
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
答案 1 :(得分:0)
好。这是我提出的ReflectionUtils#getMethod
:
public static Method getMethod(Class<?> instanceClass, String name, Class<?>... parameterTypes) {
if(ObjectUtils.notEqual(instanceClass,null) && StringUtils.isNotEmpty(name)) {
Class<?> searchType = instanceClass;
while (searchType != null) {
Method[] methods = (searchType.isInterface() ? searchType.getMethods() : searchType.getDeclaredMethods());
for (Method method : methods) {
if (name.equals(method.getName()) && (parameterTypes == null || Arrays.equals(parameterTypes, method.getParameterTypes()))) {
return method;
}
}
searchType = searchType.getSuperclass();
}
}
return null;
}
它有效。事件它返回超类的私有方法,并且在使该方法可访问之后,您可以使用子对象作为目标实例来调用该私有方法。
我在test(String message)
中创建了一个方法SortableDTO
,它只是打印在控制台中作为参数传递的消息。
然后我做了:
SearchNeedsYearPlus2ArticleDTO dto = new SearchNeedsYearPlus2ArticleDTO();
Method test = ReflectionUtils.getMethod(dto.getClass(),"test",String.class);
System.out.println("Modifier of the method is private? : " + Modifier.isPrivate(test.getModifiers()));
ReflectionUtils.makeAccessible(test);
ReflectionUtils.invokeMethod(test,dto,"JYM");
瞧。有用。注意,为了简洁起见,省略了方法ReflectionUtils#makeAccessible
和ReflectionUtils#invokeMethod
的定义。 : - )
这是输出: