1

Java リフレクションを使用してメソッドを呼び出すと、次の例外が発生します。

次のクラスがあるとしましょう。

package hello;

public class SimpleService {

    public void SayHello(){
        System.out.println("Hello World!");
    }
}

このクラスは、hello.jar という jar ファイルに圧縮されます。

次に、単純な Swing アプリケーションである TestHello.jar という別の jar 内の別のクラスから SayHello() を呼び出しています。

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)
4

5 に答える 5

3
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});
于 2013-07-02T11:53:47.483 に答える
1

このSayHelloメソッドは引数をとらないため、反射的に呼び出すときは、インスタンス以外は何も渡さないでください。また、最初のパラメーターは SimpleService のインスタンスである必要があります。

これを置き換えます:

sayHello.invoke(this, null);

これとともに:

sayHello.invoke(helloClass.newInstance());
于 2013-07-02T11:59:51.440 に答える
1

確かに、「これ」はタイプ 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);
于 2013-07-02T12:01:23.100 に答える
0

為に

sayHello.invoke(this, null);

this( TestPanel) は のインスタンスではありませんSimpleService。のインスタンスが必要です。または、メソッドを静的SimpleServiceにすることができます。SayHello

public static void SayHello()

そして、おそらくnull代わりに正しいことを渡します: ( 「基になるメソッドが静的である場合、指定された obj 引数は無視されます。null の可能性があります。」 )

sayHello.invoke(null, null);
于 2013-07-02T11:55:26.730 に答える
0

次の行に注意してください。sayHello.invoke(this, null);

を使用する場合、 がインスタンスでMethod.invokeある のインスタンスを提供する必要があります。したがって、呼び出すには、のインスタンスを提供する必要があります。ClassMethodsayHello.invokeSimpleService

第 2 に、SayHelloは引数を取らないため、呼び出しは である必要がありますsayHello.invoke(myinstance)。2 番目の引数がないことに注意してください。

于 2013-07-02T11:54:42.560 に答える