是否有可能使用Javareflection创build一个嵌套类的实例?

代码示例:

public class Foo { public class Bar { public void printMesg(String body) { System.out.println(body); } } public static void main(String[] args) { // Creating new instance of 'Bar' using Class.forname - how? } } 

有没有可能创build一个名为Bar的新实例? 我试着用:

 Class c = Class.forName("Foo$Bar") 

它find类,但是当我使用c.newInstance()它会引发InstantiationException。

你需要跳过几个箍来做到这一点。 首先,您需要使用Class.getConstructor()来查找要调用的Constructor对象:

返回一个Constructor对象,该对象反映由此Class对象表示的类的指定公共构造函数。 parameterTypes参数是一个Class对象的数组,以声明的顺序标识构造函数的forms参数types。 如果此Class对象表示在非静态上下文中声明的内部类,则forms参数types将显式封闭实例作为第一个参数。

然后你使用Constructor.newInstance() :

如果构造函数的声明类是非静态上下文中的内部类,则构造函数的第一个参数需要是封闭实例

如果不先构造父类,则内部类实际上不能构造。 它不能存在于父类之外。 在进行reflection时,必须传递父类的实例。 嵌套类是static ,可以独立于父类使用,也可以在进行reflection时使用。

这是一个展示所有东西的SSCCE 。

 package mypackage; import java.lang.reflect.Modifier; public class Parent { public static class Nested { public Nested() { System.out.println("Nested constructed"); } } public class Inner { public Inner() { System.out.println("Inner constructed"); } } public static void main(String... args) throws Exception { // Construct nested class the normal way: Nested nested = new Nested(); // Construct inner class the normal way: Inner inner = new Parent().new Inner(); // Construct nested class by reflection: Class.forName("mypackage.Parent$Nested").newInstance(); // Construct inner class by reflection: Object parent = Class.forName("mypackage.Parent").newInstance(); for (Class<?> cls : parent.getClass().getDeclaredClasses()) { if (!Modifier.isStatic(cls.getModifiers())) { // This is an inner class. Pass the parent class in. cls.getDeclaredConstructor(new Class[] { parent.getClass() }).newInstance(new Object[] { parent }); } else { // This is a nested class. You can also use it here as follows: cls.getDeclaredConstructor(new Class[] {}).newInstance(new Object[] {}); } } } } 

这应该产生

嵌套构build
内部构build
嵌套构build
内部构build
嵌套构build

快速和肮脏的代码:

 Foo.Bar.class.getConstructors()[0].newInstance(new Foo()); 

说明:您必须告诉酒吧它的封闭Foo。

是。 请记住,您需要将外部实例提供给内部类。 使用javap来查找构造函数。 你将需要通过java.lang.reflect.Constructor而不是依靠邪恶的Class.newInstance

 Compiled from "Foo.java" public class Foo$Bar extends java.lang.Object{ final Foo this$0; public Foo$Bar(Foo); public void printMesg(java.lang.String); } 

javap -c在构造函数中很有趣,因为(假设-target 1.4或更高版本,现在是隐式的)在调用超级构造函数(以前是非法的)之前,您将获得一个实例字段的赋值。

 public Foo$Bar(Foo); Code: 0: aload_0 1: aload_1 2: putfield #1; //Field this$0:LFoo; 5: aload_0 6: invokespecial #2; //Method java/lang/Object."<init>":()V 9: return 

其他答案已经解释了你如何能够做到你想做的事情。

但是我想告诉你,你需要这样做的事实表明你的系统devise有些问题。 我build议你在封闭类上需要一个(非静态的)工厂方法,或者你需要声明内部类是静态的。

reflection性地创build(非静态)内部类实例具有破碎封装的“气味”。

这并不是完全最佳的,但它适用于内部类和内部静态类的深度。

 public <T> T instantiateClass( final Class<T> cls ) throws CustomClassLoadException { try { List<Class<?>> toInstantiate = new ArrayList<Class<?>>(); Class<?> parent = cls; while ( ! Modifier.isStatic( parent.getModifiers() ) && parent.isMemberClass() ) { toInstantiate.add( parent ); parent = parent.getDeclaringClass(); } toInstantiate.add( parent ); Collections.reverse( toInstantiate ); List<Object> instantiated = new ArrayList<Object>(); for ( Class<?> current : toInstantiate ) { if ( instantiated.isEmpty() ) { instantiated.add( current.newInstance() ); } else { Constructor<?> c = current.getConstructor( instantiated.get( instantiated.size() - 1 ).getClass() ); instantiated.add( c.newInstance( instantiated.get( instantiated.size() - 1 ) ) ); } } return (T) instantiated.get( instantiated.size() - 1 ); } catch ( InstantiationException e ) { throw new CustomClassLoadException( "Failed to load class.", e ); } catch ( IllegalAccessException e ) { throw new CustomClassLoadException( "Failed to load class.", e ); } catch ( SecurityException e ) { throw new CustomClassLoadException( "Failed to load class.", e ); } catch ( NoSuchMethodException e ) { throw new CustomClassLoadException( "Failed to load class.", e ); } catch ( IllegalArgumentException e ) { throw new CustomClassLoadException( "Failed to load class.", e ); } catch ( InvocationTargetException e ) { throw new CustomClassLoadException( "Failed to load class.", e ); } } 

这里嵌套类(静态内部)的答案:在我的情况下,我需要通过它的完全限定的名称获取types

 Class.forName(somePackage.innerClass$outerClass).getConstructor().newInstance(); 

' $ '是至关重要的!

用一个点你会得到类“package.innerClass.outerClass”的ClassNotFoundException。 这是个例外: – (。