2013-02-24 96 views
1

我有以下類:java-reflection:如何覆蓋私有靜態抽象內部類的方法?

class MyClass{ 

    private static final int VERSION_VALUE = 8; 

    private static final String VERSION_KEY = "versionName"; 

    public boolean myPublicMethod(String str) { 
     try { 
      return myPrivateMethod(str, VERSION_KEY, VERSION_VALUE, 
        new MyInnerClass() { 

        @Override 
      public InputStream loadResource(String name) { 
          //do something important 
         } 
        }); 
     } 
     catch (Exception e) {   
     } 
     return false; 
    } 


private boolean myPrivateMethod(String str, String key, int version, 
      ResourceLoader resourceLoader) throws Exception 
    { 
     //do something 
    } 

    private static abstract class MyInnerClass { 

     public abstract InputStream loadResource(String name); 

    } 
} 

我想寫myPrivateMethod的單元測試,我需要傳遞的ResourceLoader對象,並重寫它的loadResource方法。

這裏是我的測試方法:

@Test 
public void testMyPrivateMethod() throws Exception { 
    Class<?> cls = Class.forName("my.pack.MyClass$MyInnerClass"); 
    Method method = cls.getDeclaredMethod("loadResource", String.class); 
    //create inner class instance and override method 
    Whitebox.invokeMethod(myClassObject, "testValue1", "testValue2", "name1", 10, innerClassObject); 
} 

請注意,我不能改變的代碼。

回答

0

嗯,你可以使用Javassist ...

this question。我沒有試過,但是當你想要重寫,你可以調用這個方法:

public <T extends Object> T getOverride(Class<T> cls, MethodHandler handler) { 
    ProxyFactory factory = new ProxyFactory(); 
    factory.setSuperclass(cls); 
    factory.setFilter(
      new MethodFilter() { 
       @Override 
       public boolean isHandled(Method method) { 
        return Modifier.isAbstract(method.getModifiers()); 
       } 
      } 
     ); 

    return (T) factory.create(new Class<?>[0], new Object[0], handler); 
} 
0

好吧,我與你的代碼中看到的問題是,你在呼喚myPublicMethod和你給第四個參數爲新MyInnerClass ()。現在在你的私有方法中,第四個參數是作爲ResourceLoader給出的,從你的代碼中我看到MyInnerClass和ResourceLoader之間沒有關係。所以你可以嘗試下面的代碼。它可能有幫助。

儘管警告您無法更改代碼,但我已更改代碼,因爲我試圖運行代碼。

class MyClass{ 

    private static final int VERSION_VALUE = 8; 

    private static final String VERSION_KEY = "versionName"; 

    public boolean myPublicMethod(String str) { 
     try { 
      return myPrivateMethod(str, VERSION_KEY, VERSION_VALUE, 
        new MyInnerClass() { 

        @Override 
      public InputStream loadResource(String name) { 
       return null; 
          //do something important 
         } 
        }); 
     } 
     catch (Exception e) {   
     } 
     return false; 
    } 


private boolean myPrivateMethod(String str, String key, int version, 
      MyInnerClass resourceLoader) throws Exception 
    { 
     return false; 
     //do something 
    } 

    private static abstract class MyInnerClass { 

     public abstract InputStream loadResource(String name); 

    } 
} 

希望它有幫助。