2015-05-12 23 views
2

我不太清楚如何反思只具有包級訪問的類。我知道如何反映了公共接入任何一類,但我無法弄清楚如何反映下面的例子:只反映包級訪問的類

public class Main { 
    public static void main(String[] args) { 
     test t = new test(); 
     Constructor<one.oneimpl> con = one.oneimpl.class.getDeclaredConstructor(test.class); 
     oneimpl o = con.newInstance(t); 
     o.doIt(); 
    } 
} 

=================== ===

package one; 
// implementation class for mimicking android api 
class oneimpl extends one { 
    Test mTest; 
    private oneimpl(test t){mTest = t;} 
    public void doIt(){System.out.println("Do It!");} 
    public void dontDoit(){System.out.println("Don't Do It!");} 
} 

======================

package one; 
// abstract class for mimicking android api 
abstract class one { 
    public void doIt(); 
    public void dontDoIt(); 
} 

=========== ===========

package one; 
// empty class for mimicking android api 
public class test {} 

如您所見,類one僅具有程序包級訪問權限。這使我反思這門課很困難。我繼續得到,指出編譯器錯誤:,但即使是最閱讀的「類似的問題」後

Main.java:4: error: oneimpl is not public in one; cannot be accessed from outside package 
oneimpl o = con.newInstance(t); 

我查看了幾個帖子,要解決這個我自己,讀AccessibilityObject API,閱讀通用的反射程序,我還不清楚如何實現這一點。

最終,我試圖做的是反映API的特定部分來構建對象,以便菸灰/火花可以構建適當的調用圖。我實際上並沒有在android API裏面工作。

+0

你需要調用「setAccessible」。請參閱:http://stackoverflow.com/questions/5629706/java-accessing-private-constructor-with-type-parameters – slipperyseal

+0

這個特殊的例子是比你提供的鏈接有點不同。假定示例中給出的類位於相同的包中,並且構造函數是私有的。我有一個具有包級訪問類的公共構造函數。我的代碼甚至不會編譯。看到上面生成的錯誤。 – lilott8

+0

其實你有一個私人的構造函數,仔細看看'oneimpl'中的聲明:'private oneimpl(test t){mTest = t;}'。即使它是公開的,你仍然必須調用'setAccessible',因爲在不可訪問的類中的公共構造函數/方法被認爲是不可訪問的。 – neuronaut

回答

3

你需要在每一步都使用反射來完成你想要做的事情。

首先,因爲你不能直接在包one從包的外部引用一個包範圍的類,你需要動態加載類(也注意使用?而不是直接使用oneimpl的):

Class<?> oneImplClass = Class.forName("one.oneimpl"); 

然後你就可以得到構造函數和方法doIt(確保你設置這兩個可訪問的,否則你會得到運行時錯誤):

Constructor<?> constructor = oneImplClass.getDeclaredConstructor(test.class); 
constructor.setAccessible(true); 
Method doIt = oneImplClass.getDeclaredMethod("doIt"); 
doIt.setAccessible (true); 

接下來,實例化類。你必須將它轉換爲Object,因爲你不能直接引用類):

Object oneImpl = (Object) constructor.newInstance(); 

最後,你可以調用doIt方法:

doIt.invoke(oneImpl); 

隨着最後一個音符:你應遵循命名類時的Java命名約定:oneimpl應該是OneImpltest應該是Test。否則像one.oneimpl這樣的東西最終看起來像一個包名,而不是完全合格的類名。

+0

所以我知道怎麼做,我只是沒有把所有的東西放在一起:(謝謝! – lilott8

0
public static void main(String[] args) throws Exception { 
    test t = new test(); 
    Class<?> oneimpl = Main.class.getClassLoader().loadClass("one.oneimpl"); 
    Constructor<?> con = oneimpl.getDeclaredConstructor(test.class); 
    con.setAccessible(true); 
    Object o = con.newInstance(t); 
    Method m = oneimpl.getDeclaredMethod("doIt"); 
    m.setAccessible(true); 
    m.invoke(o); 
}