簡體   English   中英

如何調用私有內部類中存在的私有方法

[英]How to call a private method that exists inside a private inner class

我想測試一個私有內部類中存在的私有方法

 public class MyBigClass {
    private class MyInnerClass {
       private void wantedMethod() {
       }
    }
 }

我想調用wantedMethod()來測試它

這是我的代碼

Class[] classes = MyBigClass.class.getDeclaredClasses();
    for (int i = 0; i < classes.length; i++) {
        // this code print "MyInnerClass"
        System.out.println(">> inner classes >> " + classes[i].getSimpleName());
        if (classes[i].getSimpleName().equals("MyInnerClass")) {
            Class clazz = classes[i];
            // Constructor c=clazz.getConstructor();
            Method[] methods = clazz.getDeclaredMethods();
            // this code print "wantedMethod"
            for (int j = 0; j < methods.length; j++) {
                System.out.println("inner class methods >>  " + methods[i].getName());
            }

        }

    }    

問題 :我無法調用wantedMethod()

如果要調用非靜態方法,則需要告知要調用它的對象。 在您的情況下,您需要內部類對象,但由於您還沒有內部類對象,因此您需要創建它。 由於Java不能在沒有外部類對象的情況下創建內部類對象,因此您還需要創建該外部對象。

所以這些是您需要采取的步驟:

  • 創建外部類對象(如果沒有),
  • 使用外部類對象創建內部類對象,
  • 調用內部類對象的方法。

你可以這樣做:
(你只需要記住默認構造函數與其類的可見性具有相同的可見性,因此私有類將具有私有構造函數,在我們能夠使用它之前我們需要使它們可訪問)

try {
    //creating parent object
    Object outer = new MyBigClass();

    //creating inner class object
    Class<?> innerClass = Class.forName("MyBigClass$MyInnerClass");
    Constructor<?> constructor = innerClass.getDeclaredConstructor(MyBigClass.class);//inner object must know type of outer class
    constructor.setAccessible(true);//private inner class has private default constructor
    Object child = constructor.newInstance(outer);//inner object must know about its outer object

    //invoking method on inner class object
    Method method = innerClass.getDeclaredMethod("wantedMethod",new Class<?>[]{});
    method.setAccessible(true);//in case of unaccessible method
    method.invoke(child,new Object[]{});

} catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e1) {
    // TODO Auto-generated catch block
    e1.printStackTrace();
}

您可以在此問題中找到有關通過反射創建內部類對象的更多信息

這是因為您的類未命名為CodeCircuit 刪除if條件,它將工作。

同時刪除行Constructor c=clazz.getConstructor(); 因為它拋出異常。

進行這些更改后,將打印您自己的代碼

>> inner classes >> MyInnerClass
inner class methods >>  wantedMethod

編輯

使用此代碼執行該方法。

    Class<?>[] classes = MyBigClass.class.getDeclaredClasses();

    for (Class<?> clazz : classes) {
        if(clazz.getSimpleName().equals("MyInnerClass")) {
            Method method = clazz.getDeclaredMethod("wantedMethod", new Class[] {});
            method.setAccessible(true);
            method.invoke(clazz.getDeclaredConstructor(MyBigClass.class).newInstance(new MyBigClass()), new Object[] {});
        }
    }

語法有點奇怪,使您可以使用外部類來獲取內部類構造函數。 它的行為就好像你有一個構造函數,在你的內部類中定義了以下簽名:

public MyInnerClass(MyBigClass bigClass) {
}

但是,我認為這是Java如何使用反射處理內部(嵌套)類。

請注意,您必須為內部類提供public構造函數。

public class MyBigClass {
    private class MyInnerClass {
        public MyInnerClass() {
            System.out.println("hello");
        }
        private void wantedMethod() {
            System.out.println("world");
        }
    }
}

您還必須在私有方法上設置setAccessible(true)才能調用它。

編輯2

經過進一步調查,當我反編譯生成的MyBigClass$MyInnerClass.class類時,我發現我的預感是正確的:

public class MyBigClass$MyInnerClass {
    public MyBigClass$MyInnerClass(MyBigClass paramMyBigClass) {
        System.out.println("hello");
    }
    private void wantedMethod() {
        System.out.println("world");
    }
}

如果有人可以對這種行為有所啟發,那真的很高興

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM