【问题标题】:Java: check if a class exists and call a specific method if it existsJava:检查类是否存在,如果存在则调用特定方法
【发布时间】:2017-07-06 16:08:56
【问题描述】:

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

假设我有X类。在X类的某些方法中,我想做以下事情:

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

这样的事情可能吗?而做这样的事情合理吗?谢谢。

【问题讨论】:

  • 是否合理,看你的要求。在大多数情况下,这是不合理的。在极少数情况下,它合理的,您很可能会确切地了解自己在做什么以及为什么要这样做。

标签: java reflection


【解决方案1】:

这样的事情可能吗?而做这样的事情合理吗? 谢谢。

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


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

这是一个包含两种解决方案的示例:

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 的静态方法

【讨论】:

  • 看起来不错,尤其展示了如何调用静态和非静态方法。谢谢!
【解决方案2】:

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

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

【讨论】:

  • 大部分都是有道理的,但在这种情况下,我们不能将类型转换为 Test 类,因为它可能不存在,不是吗?如,我认为这段代码不会编译。
【解决方案3】:

你可以使用Class.forName:

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

要检查方法是否存在,您可以在 try/catch 中使用 NoSuchMethodError e

【讨论】:

  • 类需要在同一个包中还是在我的主包中的任何地方?
【解决方案4】:

您可以使用反射来做到这一点,但它实际上并不实用,除非您尝试访问可能在运行时不存在的类,或者您尝试访问私有或隐藏字段。下面的例子。

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

【讨论】:

    【解决方案5】:

    要查找一个类是否存在,可以使用 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) {
    
    }
    

    【讨论】:

      【解决方案6】:

      您可以使用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
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-05-04
        • 1970-01-01
        • 1970-01-01
        • 2017-08-28
        • 2017-01-26
        • 1970-01-01
        相关资源
        最近更新 更多