在Java中,是否可以通过某种方式(反射等)访问方法中定义的类?怎么样?
例如,我想在下面的示例中创建InnerClass的实例:
class Example {
public void outerMethod() {
class InnerClass {
double d = 0;
}
}
public void testMethod() {
outerMethod::InnerClass instance = new outerMethod::InnerClass();
}
}
感谢您的回答。
答案 0 :(得分:0)
不,那是不可能的。在方法内声明的名称只能在方法本身内引用。本地类(以您的情况为例)在Java 8语言规范的第14.3节中定义。
https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-Block。
答案 1 :(得分:0)
技术上有可能。
实际上这是一种黑客攻击,你应该避免在生产代码中使用这种做法。
示例:
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
class Example {
public void outerMethod() {
class InnerClass {
private double d = 7.62;
@Override
public String toString() {
return String.format("[%s] d = %f", this.getClass().getName(), d);
}
}
}
public void testMethod() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
final Class<?> clazz = Class.forName("Example$1InnerClass");
final Constructor<?> constructor = clazz.getDeclaredConstructor(Example.class);
constructor.setAccessible(true);
final Object instance = constructor.newInstance(this);
System.out.println(instance);
}
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
Example instance = new Example();
instance.testMethod();
}
}
这里我们首先通过他们的名字为我们的本地课程获取Class<?>
。
本地类名生成规则是编译器实现细节,可能会有所不同。 AFAIK javac
和ECJ
使用不同的方法
然后我们通过反射得到我们感兴趣的类的构造函数。
由于类没有定义构造函数,因此编译器会自动生成它,并且此构造函数不是公共的。所以我们在这里使用getDeclaredConstructor()
方法
由于此类不是静态的(本地类不能定义为静态),因此构造函数的第一个也是唯一的参数是外部类引用。在我们的案例中Example
之后我们通过调用constructor.newInstance(this)
来创建一个类的实例
this
作为参数传递给构造函数。请参阅上面有关构造函数参数的说明。
最后,我们打印刚创建的对象,隐式调用InnerClass::toString()