【问题标题】:If class exists, call constructor如果类存在,调用构造函数
【发布时间】:2016-02-23 11:02:36
【问题描述】:

我有这个 Java 代码 sn-p:

try {
    Class.forName(command);
} catch (ClassNotFoundException ex) {    
}

其中“command”是在运行时手动输入的字符串。为了这个问题,我们假设用户输入“Foo”。

它检查是否有一个名为 Foo 的类。检查后我想做的事情是从 Foo 调用一个方法。

Foo.execute();

如何在不为我的每个班级制作特殊的“if”案例的情况下做到这一点?有没有办法使用别名之类的东西, ($command).execute() 其中 $command 将是(在这种情况下)我的 Foo 类?

【问题讨论】:

标签: java class methods alias


【解决方案1】:

你必须像这样使用反射和调用方法:

Object o = m.invoke(t, new Locale(args[1], args[2], args[3]));

详见本教程:https://docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html

【讨论】:

    【解决方案2】:

    对于您希望能够从名称执行的任何类,我的第一直觉是让每个类都实现一个通用接口。

    例子:

    public Interface InputClazz {
        public void execute();
    }
    
    public class Foo implements InputClazz {
      public void execute() {
        //do Stuff
      }
    }
    
    public class Bar implements InputClazz {
      public void execute() {
        //do Stuff
      }
    }
    

    如何调用:

    try {
        Class clazz = Class.forName(command);
        InputClazz input = (InputClazz) clazz.newInstance();
        input.execute();
    } catch (ClassNotFoundException ex) {    
    }
    

    然后您可以输入 Foo 或 Bar,代码将运行该类的具体执行方法。

    【讨论】:

      【解决方案3】:

      这会打印“Hello World”

      private static void call(String className, String methodName) {
          try {
              Class<?> clazz = Class.forName(className);
              Object instance = clazz.newInstance();
              Method method = clazz.getMethod(methodName);
              method.invoke(instance);
          } catch (InstantiationException e) {
              e.printStackTrace();
          } catch (IllegalAccessException e) {
              e.printStackTrace();
          } catch (ClassNotFoundException e) {
              e.printStackTrace();
          } catch (NoSuchMethodException e) {
              e.printStackTrace();
          } catch (SecurityException e) {
              e.printStackTrace();
          } catch (IllegalArgumentException e) {
              e.printStackTrace();
          } catch (InvocationTargetException e) {
              e.printStackTrace();
          }
      }
      
      static class Foo {
          public void foo() {
              System.out.println("Hello World");
          }
      }
      
      public static void main(String[] args) {
          call(Foo.class.getName(), "foo");
      }
      

      唯一不太好的是您必须使用完全限定的类名。所以不是Foo,它可能是像com.mycompany.something.Foo这样丑陋的东西。或者你真的必须确保这些类不在包中。

      【讨论】:

        【解决方案4】:

        我认为 Nappa 有一个很好、实用的答案。如果你想更高级一点,可以在 Class 方法上使用 isAssignableFrom() 检查你的类在层次结构中的成员资格。

        下面的代码使用内置的层次结构(StringBuilder 实现了CharSequence 接口)。当它找到CharSequence 类型的类时,它会强制转换该类,然后在其上调用length()

        您可以在不引发异常的情况下保持对类类型的控制,这在某些情况下可能会更简洁一些。

        请注意,如果您拼写错误的类名,此代码仍会抛出 ClassNotFoundExcpetion。您仍然必须捕获该异常。

        public class ReflectionSubclassing
        {
        
           public static void main(String[] args) 
                   throws ClassNotFoundException, InstantiationException, 
                   IllegalAccessException 
           {
              getDoubleValue( "java.lang.StringBuilder" );
              getDoubleValue( "javax.swing.JButton" );
           }
        
           private static void getDoubleValue( String className ) 
                   throws ClassNotFoundException, InstantiationException, 
                   IllegalAccessException
           {
              Class<?> tempClass = Class.forName( className );
              if( java.lang.CharSequence.class.isAssignableFrom( tempClass ) ) {
                 Object charSeq = tempClass.newInstance();
                 CharSequence cs = (java.lang.CharSequence)charSeq;
                 System.out.println( cs.length() );
              } else
                 System.out.println( "nope" );
           }
        }
        

        示例代码输出:

        run:
        0
        nope
        BUILD SUCCESSFUL (total time: 0 seconds)
        

        【讨论】:

          猜你喜欢
          • 2012-10-18
          • 1970-01-01
          • 2016-07-19
          • 1970-01-01
          • 1970-01-01
          • 2011-12-07
          • 2019-03-14
          • 2018-03-31
          • 2018-01-27
          相关资源
          最近更新 更多