如何仅获取Java内部类构造方法的显式参数?
Java内部类构造方法隐式参数的问题
根据Constructor.getParameterTypes()的文档说明:
请注意,某些内部类的构造方法除了显式声明的参数外,可能还有一个隐式声明的参数。
我对一个无参构造的非静态内部类调用该方法时,得到的构造方法却带有一个外部类类型的参数(示例代码如下),想请教两个问题:
- 有没有简便方法仅获取显式声明的参数?
- 如何确定第一个参数100%是隐式的?除了非静态内部类外,还有哪些情况内部类不会有这个隐式参数?
示例代码:
import java.lang.reflect.*; import java.util.*; import java.util.stream.*; public class TestInner{ public class Inner{} public static void main(String[] args) throws ClassNotFoundException { Class<?> innerClass = Class.forName("TestInner$Inner"); Constructor<?>[] constructors = innerClass.getConstructors(); String str = Arrays.stream(constructors).map(TestInner::stringifyConstructor).collect(Collectors.joining(", ")); System.out.println(str); } public static String stringifyConstructor(Constructor c){ return "("+Arrays.stream(c.getParameterTypes()).map(e->e.getName()).collect(Collectors.joining(", "))+")"; } }
问题1:获取显式参数的简便方法
可以通过以下逻辑过滤掉隐式的外部类参数:
- 先判断构造方法所属的类是否为非静态成员内部类(即定义在外部类成员位置、未被
static修饰的类); - 再验证构造方法的第一个参数类型是否等于外部类的类型;
- 同时满足以上两个条件时,去掉第一个参数,剩下的就是显式声明的参数。
修改后的工具方法示例:
public static String stringifyConstructor(Constructor<?> c) { Class<?> declaringClass = c.getDeclaringClass(); List<Class<?>> paramTypes = new ArrayList<>(Arrays.asList(c.getParameterTypes())); // 判断是否是非静态成员内部类,且第一个参数是外部类实例 if (declaringClass.isMemberClass() && !Modifier.isStatic(declaringClass.getModifiers())) { Class<?> enclosingClass = declaringClass.getEnclosingClass(); if (!paramTypes.isEmpty() && paramTypes.get(0).equals(enclosingClass)) { paramTypes.remove(0); } } return "(" + paramTypes.stream().map(Class::getName).collect(Collectors.joining(", ")) + ")"; }
问题2:确定隐式参数的条件&无隐式参数的内部类场景
如何100%确定第一个参数是隐式的
只有同时满足以下两个条件时,第一个参数才是编译器自动添加的隐式外部类实例参数:
- 构造方法所属的类是非静态成员内部类(
declaringClass.isMemberClass() && !Modifier.isStatic(declaringClass.getModifiers())); - 构造方法的第一个参数类型严格等于外部类的类型(
paramTypes[0].equals(declaringClass.getEnclosingClass()))。
哪些内部类不会有这个隐式参数
除了静态嵌套类(不属于内部类范畴),还有以下场景的内部类不会生成隐式外部类参数:
- 静态上下文中的局部内部类:比如在静态方法、静态代码块里定义的局部类,这类类无法访问外部类的非静态成员,编译器不会添加隐式参数;
- 静态上下文中创建的匿名内部类:如果匿名内部类没有捕获外部类的非静态成员或实例(比如在静态方法里
new Runnable且未访问外部类非静态变量),构造方法不会带隐式参数; - 通过字节码工具手动生成的特殊内部类:这类自定义生成的类不受编译器规则约束,可能没有隐式参数(属于极端场景)。
内容的提问来源于stack exchange,提问作者Awes
相关产品推荐
相关产品推荐

