【问题标题】:Instantiating an inner class实例化一个内部类
【发布时间】:2009-04-08 07:13:23
【问题描述】:

我有一个实用方法,当从中删除不相关的逻辑时,简化的方法将如下所示:

public static <A extends Foo> List<A> getFooList(Class<A> clazz) {
   List<A> returnValue = new ArrayList<A>();
   for(int i=0; i < 5; i++) {
        A object = clazz.newInstance();
        returnValue.add(object);
   }

   return returnValue;
}

问题是,如果clazz 是一个内部类,例如Foo.Bar.class,那么即使Bar 是公共的,newInstance() 方法也将不起作用,因为它会抛出一个java.lang.InstantiationException

有没有办法动态实例化内部类?

【问题讨论】:

    标签: java inner-classes


    【解决方案1】:

    如果它是真正的 inner 类而不是 nested(静态)类,则有一个隐式构造函数参数,它是对外部类实例的引用。在那个阶段你不能使用Class.newInstance - 你必须得到适当的构造函数。这是一个例子:

    import java.lang.reflect.*;
    
    class Test
    {
        public static void main(String[] args) throws Exception
        {
            Class<Outer.Inner> clazz = Outer.Inner.class;
    
            Constructor<Outer.Inner> ctor = clazz.getConstructor(Outer.class);
    
            Outer outer = new Outer();
            Outer.Inner instance = ctor.newInstance(outer);
        }
    }
    
    class Outer
    {
        class Inner
        {
            // getConstructor only returns a public constructor. If you need
            // non-public ones, use getDeclaredConstructors
            public Inner() {}
        }
    }
    

    【讨论】:

      【解决方案2】:

      更通用的东西:

          public static <T> T createInstance(final Class<T> clazz) throws SecurityException, NoSuchMethodException,
                  IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
      
                  T instanceToReturn = null;
                  Class< ? > enclosingClass = clazz.getEnclosingClass();
      
                  if (enclosingClass != null) {
                      Object instanceOfEnclosingClass = createInstance(enclosingClass);
      
                      Constructor<T> ctor = clazz.getConstructor(enclosingClass);
      
                      if (ctor != null) {
                          instanceToReturn = ctor.newInstance(instanceOfEnclosingClass);
                      }
                  } else {
                      instanceToReturn = clazz.newInstance();
                  }
      
                  return instanceToReturn;
           }
      

      【讨论】:

        【解决方案3】:

        仅当 clazz 表示抽象类或接口时才会抛出此异常。您确定要传递一个代表具体类的 Class 对象吗?

        【讨论】:

          【解决方案4】:

          在 Jmockit 1.41 中,使用这个:

          ConstructorReflection.newInstance

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-01-03
            • 2020-01-01
            • 2011-05-03
            • 1970-01-01
            • 1970-01-01
            • 2010-11-15
            • 1970-01-01
            • 2015-05-03
            相关资源
            最近更新 更多