Java 访问任何类型的;闭包变量";在匿名类实例中反射
模糊地说,在Java中,匿名类提供了某种闭包:可以从匿名类内部访问(Java 访问任何类型的;闭包变量";在匿名类实例中反射,java,reflection,Java,Reflection,模糊地说,在Java中,匿名类提供了某种闭包:可以从匿名类内部访问(final)变量。在下面,我将这种变量称为“闭包变量” 是否有一种优雅的方法可以反射性地访问非常量“闭包变量” 下面是我的测试课程,演示了这一挑战: package com.example; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import org.junit.Test; pub
final
)变量。在下面,我将这种变量称为“闭包变量”
是否有一种优雅的方法可以反射性地访问非常量“闭包变量”
下面是我的测试课程,演示了这一挑战:
package com.example;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import org.junit.Test;
public class ReflectiveInstantiationAnonymousClassTest {
@Test
public void testInstantiateConstantAnonymousClassReflectively() {
System.out
.println("About to define anonymous class with constant closure");
final String constantString = "constant String";
System.out.println("constantString is " + constantString);
Class<? extends Object> clazz = new Object() {
public String toString() {
return "Hello with " + constantString;
}
}.getClass();
Object anonymousClassInstance1 = instantiateAnonymousClass(clazz);
Object anonymousClassInstance2 = instantiateAnonymousClass(clazz);
System.out.println(anonymousClassInstance1);
System.out.println(anonymousClassInstance2);
}
@Test
public void testInstantiateNonConstantAnonymousClassReflectively() {
System.out
.println("About to define anonymous class with variable closure");
final String variableString = String.valueOf( System.currentTimeMillis() );
System.out.println("variableString is " + variableString);
Class<? extends Object> clazz = new Object() {
public String toString() {
return "Hello with " + variableString;
}
}.getClass();
Object anonymousClassInstance1 = instantiateAnonymousClass(clazz);
Object anonymousClassInstance2 = instantiateAnonymousClass(clazz);
System.out.println(anonymousClassInstance1);
System.out.println(anonymousClassInstance2);
}
@SuppressWarnings("unchecked")
private <T> T instantiateAnonymousClass(Class<T> clazz) {
T instance = null;
Constructor<?>[] allConstructors = clazz.getDeclaredConstructors();
System.out.println("-+-" + allConstructors.length + " constructor(s) defined by class " + clazz.getName() );
for(Constructor<?> constructor : allConstructors) {
System.out.println(" +- a constructor with " + constructor.getParameterTypes().length + " parameter(s): " + constructor.toGenericString() );
}
System.out.println();
System.out.println("Instantiating anonymous class");
try {
instance = (T) clazz.getDeclaredConstructors()[0].newInstance(this);
// .
// /|\
// how can I provide a variable closure variable there?--------+
} catch (InstantiationException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException
| SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return instance;
}
}
但是测试用例testinstate
非常量类反射式打印出以下内容:
About to define anonymous class with variable closure
variableString is 1371946280882
-+-1 constructor(s) defined by class com.example.ReflectiveInstantiationAnonymousClassTest$2
+- a constructor with 2 parameter(s): com.example.ReflectiveInstantiationAnonymousClassTest$2(com.example.ReflectiveInstantiationAnonymousClassTest,java.lang.String)
Instantiating anonymous class
java.lang.IllegalArgumentException: wrong number of arguments
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:525)
at com.example.ReflectiveInstantiationAnonymousClassTest.instantiateAnonymousClass(ReflectiveInstantiationAnonymousClassTest.java:60)
at com.example.ReflectiveInstantiationAnonymousClassTest.testInstantiateNonConstantAnonymousClassReflectively(ReflectiveInstantiationAnonymousClassTest.java:43)
请注意,对于测试用例testinstate
非ConstantanonymousClassReflective
,将生成不同类型的构造函数。此构造函数需要一个额外的String
参数,因为variableString
无法“烘焙”,只能在运行时确定。我认为您的要求是不可能的。如果变量没有烘焙到匿名类中,那么它们就不会烘焙到匿名类中。通过使用反射,调用方可以提供所有构造函数参数,包括合成参数
newInstance(this, variableString);
对于需要外部实例的内部类构造函数的动态调用,情况也是如此。我注意到,instanceAnonymousClass
依赖于指定的匿名类在同一个类中声明的事实-这允许它只传入这个
。它将如何处理在别处声明的匿名类?你提到这是一种图书馆方法,所以这是一个重要的问题需要考虑。您的方法可以查找它们的外部类并对它们进行实例化,但是如果它们的构造函数需要进一步的参数呢?最终,调用方需要提供动态调用所需的一切。实例化OnymousClass(..)
应该是一个库函数variableString
不在此库的作用域内。@Abdull-那么库中的调用者将需要提供参数,就像任何其他构造函数参数一样。非常量“闭包变量”是否会在生成的构造函数中导致参数类型的确定顺序?如果是这样,您可以创建一个正确排序的列表非恒定OSUREVIABLES
,将其提供给实例化OnyMousClass(clazz,非恒定OSUREVIABLES)
,然后在库内方法调用newInstance(this,nonstantcOSUREVIABLES)
…+1以获得一个编写良好的问题,但我认为你的要求是不可能的。如果变量没有被烘焙,那么它们就没有被烘焙。通过使用反射,调用方需要提供构造函数参数——这与动态调用需要外部实例的内部类构造函数的情况相同。
newInstance(this, variableString);