如果 class 存在,调用构造函数
If class exists, call constructor
我有这个 Java 代码片段:
try {
Class.forName(command);
} catch (ClassNotFoundException ex) {
}
其中 "command" 是一个在运行时手动输入的字符串。为了这个问题,我们假设用户输入 "Foo".
它检查是否有一个名为 Foo 的 class。检查后我想做的事情是从 Foo 调用一个方法。
Foo.execute();
如何在不为每个 classes 制作特殊 "if" 案例的情况下执行此操作?有没有办法使用别名之类的东西,$command.execute() 其中 $command 将是(在这种情况下)my Foo Class?
您必须像这样使用反射和调用方法:
Object o = m.invoke(t, new Locale(args[1], args[2], args[3]));
详见本教程:https://docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html
我的第一直觉是,对于任何 class 你希望能够从 name 执行的是让每个实现一个通用接口。
示例:
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,代码将 运行 class 的具体执行方法。
这会打印 "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");
}
唯一不好的是您必须使用完全限定的 class 名称。因此,它可能不是 Foo
,而是像 com.mycompany.something.Foo
这样丑陋的东西。或者你真的必须确保那些 classes 不在包中。
我认为 Nappa 有一个很好、实用的答案。如果您想更高级一点,可以使用 Class
方法使用 isAssignableFrom()
检查您的 class 是否属于层次结构。
下面的代码使用内置层次结构(StringBuilder
实现了 CharSequence
接口)。当它找到类型为 CharSequence
的 class 时,它会转换 class,然后对其调用 length()
。
您可以在不抛出异常的情况下保持对 class 类型的控制,这在某些情况下可能更简洁。
请注意,如果您拼错 class 的名字,此代码仍会抛出 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)
我有这个 Java 代码片段:
try {
Class.forName(command);
} catch (ClassNotFoundException ex) {
}
其中 "command" 是一个在运行时手动输入的字符串。为了这个问题,我们假设用户输入 "Foo".
它检查是否有一个名为 Foo 的 class。检查后我想做的事情是从 Foo 调用一个方法。
Foo.execute();
如何在不为每个 classes 制作特殊 "if" 案例的情况下执行此操作?有没有办法使用别名之类的东西,$command.execute() 其中 $command 将是(在这种情况下)my Foo Class?
您必须像这样使用反射和调用方法:
Object o = m.invoke(t, new Locale(args[1], args[2], args[3]));
详见本教程:https://docs.oracle.com/javase/tutorial/reflect/member/methodInvocation.html
我的第一直觉是,对于任何 class 你希望能够从 name 执行的是让每个实现一个通用接口。
示例:
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,代码将 运行 class 的具体执行方法。
这会打印 "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");
}
唯一不好的是您必须使用完全限定的 class 名称。因此,它可能不是 Foo
,而是像 com.mycompany.something.Foo
这样丑陋的东西。或者你真的必须确保那些 classes 不在包中。
我认为 Nappa 有一个很好、实用的答案。如果您想更高级一点,可以使用 Class
方法使用 isAssignableFrom()
检查您的 class 是否属于层次结构。
下面的代码使用内置层次结构(StringBuilder
实现了 CharSequence
接口)。当它找到类型为 CharSequence
的 class 时,它会转换 class,然后对其调用 length()
。
您可以在不抛出异常的情况下保持对 class 类型的控制,这在某些情况下可能更简洁。
请注意,如果您拼错 class 的名字,此代码仍会抛出 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)