2012-01-19 140 views
3

虽然想在这里对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

为了完整性我加了一些其他情况一个d这些都是可区分的(除了当前是在列表的最后):

  • “正常”内部类(class Outer { class Inner {}})具有一个声明类和被标记为成员类
  • “正常”静态内部类(class Outer { static class Inner {}})具有一个声明类,是成员类具有静态类改性剂
  • 在实例方法创建的内部类具有一个封闭的方法在静态方法中创建
  • 内部类具有它具有一个eclosing方法静态修饰符
  • 在初始化(静态或实例)创建内部类在这里描述的情况和除了在构造函数中没有什么不同参数
+0

我没有看到任何内部类,只是一个静态变量和一个实例变量。 – GriffeyDog

+0

@GriffeyDog:仔细看看 - 注意'new A(...){}'末尾的大括号。 –

+0

@Jon你是对的,我错过了那些。 – GriffeyDog

回答

0

您在声明中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 
    } 
} 
+0

不幸的是,修饰符是相等的。那是我测试的第一件事情之一。 :) – Thomas

+0

除此之外,'Outer.class.getDeclaredClasses()'返回一个空数组。 – Thomas