有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java访问封闭类或父类方法的一般方法

如何访问父类中定义的方法?在这里,我继承了以下遗产:

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);

它正在工作。然后我发现了我所做的错误

^{}

Returns a Method object that reflects the specified declared method of the class or interface represented by this Class object. The name parameter is a String that specifies the simple name of the desired method, and the parameterTypes parameter is an array of Class objects that identify the method's formal parameter types, in declared order. If more than one method with the same parameter types is declared in a class, and one of these methods has a return type that is more specific than any of the others, that method is returned; otherwise one of the methods is chosen arbitrarily. If the name is "<init>"or "<clinit>" a NoSuchMethodException is raised.

^{}

Returns a Method object that reflects the specified public member method of the class or interface represented by this Class object. The name parameter is a String specifying the simple name of the desired method. The parameterTypes parameter is an array of Class objects that identify the method's formal parameter types, in declared order. If parameterTypes is null, it is treated as if it were an empty array.

If the name is "<init>"or "<clinit>" a NoSuchMethodException is raised. Otherwise, the method to be reflected is determined by the algorithm that follows. Let C be the class represented by this object:

  • C is searched for any matching methods. If no matching method is found, the algorithm of step 1 is invoked recursively on the superclass of C.

  • If no method was found in step 1 above, the superinterfaces of C are searched for a matching method. If any such method is found, it is reflected.

To find a matching method in a class C: If C declares exactly one public method with the specified name and exactly the same formal parameter types, that is the method reflected. If more than one such method is found in C, and one of these methods has a return type that is more specific than any of the others, that method is reflected; otherwise one of the methods is chosen arbitrarily.

Note that there may be more than one matching method in a class because while the Java language forbids a class to declare multiple methods with the same signature but different return types, the Java virtual machine does not. This increased flexibility in the virtual machine can be used to implement various language features. For example, covariant returns can be implemented with bridge methods; the bridge method and the method being overridden would have the same signature but different return types.

因此,我需要为我的案例调用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),使其捕获任何访问修饰符的方法,并属于封闭类、其超类或接口中的任何位置,我该如何做


共 (2) 个答案

  1. # 1 楼答案

    根据继承原则,private方法不是由Dervied类继承的。因此,在您的示例中SearchNeedsYearPlus2ArticleDTO实例无法访问BaseSearchArticleDTO中声明的私有方法

    因此,使用Class对象SearchNeedsYearPlus2ArticleDTO,您可以访问

    • SearchNeedsYearPlus2ArticleDTOprivate, protected, public)的所有方法
    • 层次结构中超类的所有继承方法(protected, public

    在我看来,你可以有这样的后备机制

    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();
        }
    
  2. # 2 楼答案

    好的。这是我的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;
    }
    

    它是有效的。事件,它返回超类的私有方法,在使该方法可访问之后,您可以使用子对象作为目标实例调用该私有方法

    我在SortableDTO中创建了一个方法test(String message),它只打印作为控制台参数传递的消息

    然后我做了:

    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#makeAccessibleReflectionUtils#invokeMethod的定义。:-)

    以下是输出:

    enter image description here