[英]Calling a method in java using reflection
使用Java反射调用方法时出现以下异常,
假设我有以下课程,
package hello;
public class SimpleService {
public void SayHello(){
System.out.println("Hello World!");
}
}
并将该类压缩到一个名为hello.jar的jar文件中
然后我从另一个名为TestHello.jar的jar中的另一个类调用SayHello(),这是一个简单的Swing应用程序。
public class TestPanel extends javax.swing.JPanel{
.
.
jButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton1ActionPerformed(evt);
}
});
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
try {
String jarPath = "/SayHello/SayHello" + ".jar";
URL[] classpathURLs = new URL[]{new File(jarPath).toURI().toURL()};
ClassLoader loader = new URLClassLoader(classpathURLs);
Class helloClass = loader.loadClass("hello.SimpleService");
Method sayHello = helloClass.getMethod("SayHello");
int modifiers = sayHello.getModifiers();
if (Modifier.isPublic(modifiers)) {
sayHello.invoke(this, null);
} else {
throw new NoSuchMethodException();
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
.
.
上面的TestPanel类也使用Java反射创建,然后将该面板添加到JFrame中。
除了单击jButton1以外,所有其他东西都正常运行,出现以下异常,
java.lang.IllegalArgumentException: object is not an instance of declaring class
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
.
.
.
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
at java.awt.Component.processMouseEvent(Component.java:6504)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6269)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4860)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2713)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
at java.awt.EventQueue.access$000(EventQueue.java:101)
at java.awt.EventQueue$3.run(EventQueue.java:666)
at java.awt.EventQueue$3.run(EventQueue.java:664)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:680)
at java.awt.EventQueue$4.run(EventQueue.java:678)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
sayHello.invoke(this, null);
第一个参数应该是SimpleService
。 更改为:
sayHello.invoke(helloClass.newInstance(), null);
为了清楚起见,您可以这样更改代码:
sayHello.invoke(helloClass.newInstance(), (Object[]) null);
或这个:
sayHello.invoke(helloClass.newInstance());
否则可能会被误解为:
sayHello.invoke(helloClass.newInstance(), (Object) null);
或这个:
sayHello.invoke(helloClass.newInstance(), new Object[]{null});
SayHello
方法不带任何参数,因此在进行反射式调用时,除了实例之外,不要传递任何东西。 另外,第一个参数应该是SimpleService的实例:
替换为:
sayHello.invoke(this, null);
有了这个:
sayHello.invoke(helloClass.newInstance());
确保“ this”是TestPanel类型,而不是SimpleService类型
请尝试以下操作:
Class helloClass = loader.loadClass("hello.SimpleService");
Object args1[] = new Object[] {};
Constructor<SimpleService> constructor = helloClass.getConstructor(args1);
Object simpleService = constructor.newInstance();
sayHello.invoke(simpleService, null);
或更短
Class helloClass = loader.loadClass("hello.SimpleService");
sayHello.invoke(helloClass.newInstance(), null);
注意这一行: sayHello.invoke(this, null);
使用Method.invoke
您需要提供该Method
为实例的Class
的实例。 因此,要调用sayHello.invoke
您需要提供一个SimpleService
实例。
其次,由于SayHello
不接受任何参数,因此调用应为sayHello.invoke(myinstance)
。 注意没有第二个参数。
对于
sayHello.invoke(this, null);
this
( TestPanel
)不是SimpleService
的实例。 您需要一个SimpleService
实例,或者可以使SayHello
方法为静态方法:
public static void SayHello()
然后可能会传递null
来代替正确性:( “如果基础方法是静态的,则忽略指定的obj参数。它可以为null。”
sayHello.invoke(null, null);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.