簡體   English   中英

區分初始化程序中聲明的實例和靜態內部類

[英]Distinguish instance and static inner classes declared in the initializer

在嘗試回答SO的問題時,我遇到了一個理論問題,我不確定是否存在更好的解決方案:

假設我們有以下設置:

class A {
  public A(Outer o) {
  }
}

class Outer {
  static A staticA = new A( new Outer() ) {
    ...
  };

  A innerA = new A( new Outer() ) {
    ...
  };
} 

如何使用反射區分內部類和靜態內部類?

從我的測試中我只能通過檢查構造函數的參數類型來判斷哪個是靜態內部類,即innerA類只提供一個帶有兩個Outer實例的構造函數。 (我測試了我能想到的封閉類/方法的每一個標志或數據,一切都是平等的 - 但我可能錯過了一些東西。)

當比較這兩個類時,我可以通過檢查哪個構造函數具有較少的外部類型參數來確定哪一個是靜態內部類(在這種情況下,靜態內部類'構造函數將少一個)。

但是,假設我對該類知之甚少,我特別不知道構造函數是否具有外部類型的任何顯式參數,即A是否具有無參數構造函數或采用Outer參數的構造函數(如上面的案例)。 在那種情況下,我無法確定該類是內部還是靜態內部類。

還有另一種,即安全的方式嗎?

只是為了記錄:這是一個理論問題,我目前沒有嘗試做任何事情。

編輯

這是我的SSCCE:

package sscce;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Arrays;

public class ReflectionTest {
  public static void main(String... args) {
    Outer o = new Outer();

    o.innerA.reflect();
    o.staticA.reflect();
  }
}

class A {

  public A( Outer o ) {

  }

  public void reflect() {
    Class<?> c = getClass();
    Class<?> e = c.getEnclosingClass();
    Class<?> d = c.getDeclaringClass();
    Constructor<?> enc = c.getEnclosingConstructor();
    Method m = c.getEnclosingMethod();

    System.out.println("class: " + c.getName());
    System.out.println("-------------------");
    System.out.println("enclosing class: " + e);
    System.out.println("enclosing ctor: " + enc);
    System.out.println("enclosing method: " + m);
    System.out.println("declaring class: " + d);

    System.out.println("anonymous: " + c.isAnonymousClass());
    System.out.println("local: " + c.isLocalClass());
    System.out.println("synth: " + c.isSynthetic());
    System.out.println("member: " + c.isMemberClass());
    System.out.println("modifiers: " + c.getModifiers());

    for( Constructor<?> ctr : c.getDeclaredConstructors() ) {
      System.out.println("constructor params:"  + Arrays.toString( ctr.getParameterTypes()) );
    }

    System.out.println();
  }
}

class Outer {
  public static A staticA = new A(new Outer()) {};
  public A innerA = new A(this) {};
}

並輸出:

class: sscce.Outer$2 //this is innerA
-------------------
enclosing class: class sscce.Outer
enclosing ctor: null
enclosing method: null
declaring class: null
anonymous: true
local: false
synth: false
member: false
modifiers: 0
constructor params:[class sscce.Outer, class sscce.Outer]

class: sscce.Outer$1  //this is staticA 
-------------------
enclosing class: class sscce.Outer
enclosing ctor: null
enclosing method: null
declaring class: null
anonymous: true
local: false
synth: false
member: false
modifiers: 0
constructor params:[class sscce.Outer] 

編輯2

為了完整性,我添加了一些其他案例,這些案例都是可區分的(除了列表中最后的當前案例):

  • “普通”內部類( class Outer { class Inner {}} )具有聲明類,並被標記為成員類
  • “Normal”靜態內部類( class Outer { static class Inner {}} )具有聲明類,是成員類具有靜態類修飾符
  • 在實例方法中創建的內部類具有封閉方法
  • 在靜態方法中創建的內部類具有eclosing方法,該方法具有static修飾符
  • 在初始化程序(靜態或實例)中創建的內部類是這里描述的情況,除了構造函數參數之外沒有區別

你在Outer中聲明了兩個匿名的內部類。

從理論上講(即我沒有測試它),我想你可以打電話:

Class<?>[] classes = Outer.class.getDeclaredClasses();
for(Class<?> c : classes) {
  if ((c.getModifiers() & Modifier.STATIC) != 0) {
    // its a static inner class (or interface)
  }
  else {
    // its a non static inner class or interface
  }
}

暫無
暫無

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

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