Java:检查类是否存在并调用特定方法(如果存在)

时间:2017-02-17 08:17:06

标签: java reflection

有没有办法做到以下几点?检查一个类是否存在(在同一个包中)并且是否存在,检查是否存在特定方法,如果存在,则调用它?

假设我有类X.在X类的某些方法中,我想执行以下操作:

if (class Y exists) { //Maybe use Class.forName("Y")?
  if ( Y has method a(String, String) ) {
    call Y.a("hello", "world");
  }
}

这样的事情可能吗?并且这样做是否合理?感谢。

6 个答案:

答案 0 :(得分:5)

  

这样的事情可能吗?并且这样做是否合理?   感谢。

当然有可能。
如果你开发一个程序或一个必须动态发现某些类的库,这是一个非常合理的事情 如果不是这样,那就不可能。

如果您的需要有意义,您应该问一个额外的问题:您应该调用静态方法还是实例方法?

以下是两个解决方案的示例示例:

ReflectionClass包含使用反射的逻辑:

import java.lang.reflect.Method;

public class ReflectionCalls {
    public static void main(String[] args) {
        new ReflectionCalls();
    }

    public ReflectionCalls() {
        callMethod(true);
        callMethod(false);
    }

    private void callMethod(boolean isInstanceMethod) {

        String className = "DiscoveredClass";
        String staticMethodName = "methodStatic";
        String instanceMethodName = "methodInstance";
        Class<?>[] formalParameters = { int.class, String.class };
        Object[] effectiveParameters = new Object[] { 5, "hello" };
        String packageName = getClass().getPackage().getName();

        try {
            Class<?> clazz = Class.forName(packageName + "." + className);

            if (!isInstanceMethod) {
                Method method = clazz.getMethod(staticMethodName, formalParameters);
                method.invoke(null, effectiveParameters);
            }

            else {
                Method method = clazz.getMethod(instanceMethodName, formalParameters);
                Object newInstance = clazz.newInstance();
                method.invoke(newInstance, effectiveParameters);

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

DiscoveredClass(我们在示例中操作的类)

  package reflectionexp;

    public class DiscoveredClass {

        public static void methodStatic(int x, String string) {
            System.out.println("static method with " + x + " and " + string);
        }

        public void methodInstance(int x, String string) {
            System.out.println("instance method with " + x + " and " + string);
        }

    }

输出:

  

实例方法,带5和hello

     

使用5和hello

的静态方法

答案 1 :(得分:2)

是的,这可以做到。我在与当前类相同的Package中创建了一个Test类。

import java.lang.reflect.Method;

public class Sample {

    public static void main(String[] args) {
        Class<?> clazz = null;
        try {
            clazz = Class.forName("Test");
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        if (clazz == null) {
            System.out.println("class not found. Go eat some waffles and correct the name");
            return;
        }

        Method m = null;
        try {
            m = clazz.getMethod("foo", null);
        } catch (NoSuchMethodException | SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        if (m == null) {
            System.out.println("method not found. Go eat some waffles and correct the name");
            return;
        }
        Test t;
        try {
            t = (Test) clazz.newInstance();
            m.invoke(t, null);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


    }

}

public class Test {

    static {
        System.out.println("test...");
    }

    public void foo() {
        System.out.println("foo");
    }
}

O / P:

test...
foo

答案 2 :(得分:1)

您可以使用Class.forName

try {
    Class yourClass = Class.forName( "classname" );
    Object o = yourClass.newInstance();
} catch( ClassNotFoundException e ) {
    //Throw error or whatever
}

要检查方法是否存在,您可以在try / catch

中使用NoSuchMethodError e

答案 3 :(得分:1)

您可以使用反射执行此操作,但是除非您尝试访问可能在运行时不存在的类或者您尝试访问私有字段或隐藏字段,否则它不是真正实用的。示例如下。

public static void reflectionDemo(){

    //Here we attempt to get the common URI class
    //If it is found, we attempt to get the create method
    //We then invoke the create method and print the class name of the result.

    try {
        Class<?> uriClass = Class.forName("java.net.URI");
        //getMethod(String name, Class<?>... args);
        java.lang.reflect.Method create = uriClass.getMethod("create", String.class);

        //The first parameter is null because this is a static method.
        //invoke(Object target, Object... args);
        System.out.println(create.invoke(null, "some/uri").getClass());
        //Will print class java.net.URI

    } catch (ClassNotFoundException e) {
        // If class doesnt exist
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        // If method doesnt exist
        e.printStackTrace();
    } catch (SecurityException e) {
        // See Javadoc
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        // From invoke
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        // From invoke
        e.printStackTrace();
    } catch (java.lang.reflect.InvocationTargetException e) {
        // From invoke
        e.printStackTrace();
    }
}

答案 4 :(得分:0)

您可以使用Class.forName("classname");

检查班级是否存在

请参阅此问题:Check if class exists somewhere in package

如果存在方法,则可以在try / catch中使用NoSuchMethodError

请参阅此问题:Check if method exists at Runtime in Java

try {
  Object object = Class.forName("Y").newInstance();
  object.a(String, String);
} catch( ClassNotFoundException | NoSuchMethodError ex) {
  //do Something else
}

答案 5 :(得分:0)

要查找类是否存在,可以在Class上使用forName()方法。 要查找方法是否存在,可以在Class上使用getMethod()方法。 文档:

https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#forName(java.lang.String) https://docs.oracle.com/javase/7/docs/api/java/lang/Class.html#getMethod(java.lang.String,%20java.lang.Class...)

对于您的课程问题,您需要使用以下代码:

try {
    Class.forName("Y");
}
catch (ClassNotFoundException e) {

}

对于方法问题,您需要使用以下代码:

try {
    Class.getMethod(a);
}
catch (NoSuchMethodException e) {

}