有 Java 编程相关的问题?

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

java不能调用方法,即使它是公共的

这是我的密码。 然后它抛出

can not access a member of class sun.management.ClassLoadingImpl with modifiers "public"

我首先反映这个方法,然后调用它。如您所见,getObjectName是一个公共方法,但为什么我不能调用它呢

我认为原始代码很混乱,我在这里粘贴了一个明确的代码:

public class App {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        Object bean = ManagementFactory.getClassLoadingMXBean();
        Method[] methods = bean.getClass().getMethods();
        for (Method method : methods) {
            if (method.getName().equals("getObjectName")) {
                System.out.println(method.getName() + ":" + method.invoke(bean).toString());
            }
        }
    }
}

下面是旧的

import java.lang.management.ManagementFactory;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Hello world!
 */
public class App {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        Method[] methods = ManagementFactory.class.getMethods();
        System.out.println(ManagementFactory.getClassLoadingMXBean().getObjectName());
        for (Method method : methods) {
            if (method.getName().startsWith("get") && method.getName().endsWith("Bean")) {
                System.out.println(method.getName());
                Object bean = method.invoke(null);
                printBean(bean);
            }
        }
    }

    private static void printBean(Object bean) throws InvocationTargetException, IllegalAccessException {
        Method[] methods = bean.getClass().getMethods();
        for (Method method : methods) {
            if (method.getName().startsWith("get")) {
                System.out.println(method.getName());
                System.out.println(method.getName() + ":" + method.invoke(bean).toString());
            }
        }
    }
}

共 (2) 个答案

  1. # 1 楼答案

    当你在一个特定的Class实例上调用getMethod[s]时,比如bean.getClass(),你可能会得到Method实例,其getDeclaringClass()不是public,所以不允许调用它们,即使这些方法实际上正在重写/实现public类或接口的public方法

    这是getObjectName的情况,当从声明接口获取Method时可以调用它

    Object bean = ManagementFactory.getClassLoadingMXBean();
    Method method = ClassLoadingMXBean.class.getMethod("getObjectName");
    System.out.println(method.getName()+": "+method.invoke(bean).toString());
    

    但是,当然,这没有任何优势

    ClassLoadingMXBean bean = ManagementFactory.getClassLoadingMXBean();
    System.out.println("getObjectName: "+bean.getObjectName());
    

    如果要动态收集属性,应该使用MBeanInfo,它正是用于此目的:

    ClassLoadingMXBean bean = ManagementFactory.getClassLoadingMXBean();
    final MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
    
    MBeanAttributeInfo[] attr = mBeanServer.getMBeanInfo(bean.getObjectName()).getAttributes();
    String[] attrNames = new String[attr.length];
    for(int ix=0; ix<attr.length; ix++) attrNames[ix] = attr[ix].getName();
    
    for(Attribute a: mBeanServer.getAttributes(bean.getObjectName(), attrNames).asList())
        System.out.println(a.getName()+": "+a.getValue());
    

    这个查询甚至不需要bean实例,因为可以用ObjectName.getInstance(ManagementFactory.CLASS_LOADING_MXBEAN_NAME)的结果替换bean.getObjectName()

  2. # 2 楼答案

    无法传递bean实例来调用该方法,因为该类不是public。您应该首先检查类的可见性:

    if (!Modifier.isPublic(bean.getClass().getModifiers())) {
        System.out.println(bean + " is not public");
        return;
    }
    

    另一种可能性是将方法设置为可访问:

    method.setAccessible(true);