2017-08-24 14 views
2

Javaの場合、java.lang.reflect.Methodを使用する場合、仮想呼び出しを行わずに関数を呼び出すにはどうすればよいですか?リフレクションを使用した非仮想メソッド呼び出し

I.e.私はこのコードではなく、それが現在何の "良い" をプリントしたい、 "悪い" のプリントである:

Foo.java:

public class Foo { 
    public void doit() { 
    System.out.println("good"); 
    } 
} 

Bar.java:

import java.lang.reflect.Method; 

public class Bar extends Foo { 
    public void doit() { 
    System.out.println("bad"); 
    } 

    public static void main(String[] args) throws Exception { 
    Bar b = new Bar(); 
    /* Using Foo.class ought to do it right? */ 
    Method m = Foo.class.getDeclaredMethod("doit", new Class[]{}); 
    /* Surely if that didn't do it casting to Foo would? */ 
    m.invoke((Foo)b, new Object[]{}); 
    } 
} 

ナッシング私は反射を使用して "良い"印刷に成功しました。

私の期待はFooinvokeの最初の引数をキャストの一つ以上を使用して、および/またはFoo.class.getDeclaredMethodの代わりBar.classを使用することは十分であろうということでした。明らかに私はそれについて間違っていますが、どのようにしてリフレクションを使って希望の振る舞いを得ることができますか?

答えて

3

最も簡単な解決策をシミュレートし、invokespecial指示方法がunreflectSpecial呼ばれたjava.lang.invokeパッケージを使用するようです:

確か

を「良い」印刷ん
import java.lang.reflect.Method; 
import java.lang.invoke.*; 

public class Bar extends Foo { 
    public void doit() { 
    System.out.println("bad"); 
    } 

    public static void main(String[] args) throws Throwable { 
    Bar b = new Bar(); 
    Method m = Foo.class.getDeclaredMethod("doit", new Class[]{}); 
    MethodHandle h = MethodHandles.lookup().unreflectSpecial(m, Bar.class); 
    h.invoke(b); 
    } 
}