如何通过反射将Server实例传入RequestResponse的doSomething方法?
问题描述
ServerParams通过Jackson的ObjectMapper从JSON文件映射获取信息,这部分代码较为常规故未贴出。
IServerParams是抽象类,包含若干方法,Server类继承自它。
setupReflection方法是核心实现代码所在,RequestResponse类的doSomething方法接收IServerParams类型的参数,而Server继承自IServerParams。
需要通过反射将Server的实例传入doSomething方法,但尝试多种方式均出现NoSuchMethodException、ArgumentMismatchException或NullPointerException异常,推测遗漏了关键步骤。
相关代码
@AllArgsConstructor @NoArgsConstructor @Data public class ServerParams { @JsonProperty("server") public Server serverparam; // More fields } @EqualsAndHashCode(callSuper = true) @AllArgsConstructor @NoArgsConstructor @Data public class Server extends IServerParams { @JsonProperty("host") public String host; @JsonProperty("port") public long port; @Override public String getUsername() { return ""; } @Override public String getPassword() { return ""; } } public class RequestResponse { public void doSomething(final IServerParams iServerParams) { final String host = iServerParams.getHost(); final long port = iServerParams.getPort(); } } @Target({ANNOTATION_TYPE, METHOD}) @Retention(RUNTIME) public @interface Configuration { @NonNull Class<? extends IServerParams> value(); } public void setupReflection(final ExtensionContext extensionContext, final TestRunner testRunner) { final ServerParams serverParams = testRunner.createServerConfig(extensionContext); //creates a new object of serverParams and will contain what the .json file has. final Method method = extensionContext.getRequiredTestMethod(); final Configuration[] configurations = method.getAnnotationsByType(Configuration.class); final Class<?> annotationValue = Arrays.stream(configurations) .map(Configuration::value) .findFirst() .orElseThrow(); final Field[] declaredFields = serverParams.getClass().getDeclaredFields(); final Field field = Arrays.stream(declaredFields) .filter(type -> type.getType().getTypeName().equals(annotationValue.getTypeName())) .findFirst() .orElseThrow(() -> new RuntimeException("Cannot get instance of the configuration provided")); Class<?> classType = field.getType(); boolean isIt = IServerParams.class.isAssignableFrom(classType); // everything passes upto here, below is where I am stuck if (isIt) { RequestResponse requestResponse = new RequestResponse(); requestResponse.doSomething(field.get); // This is where I am not sure how to } }
解决方案
你卡住的核心问题是没有正确调用反射获取字段值的方法,同时需要处理访问权限和类型转换,修正后的代码如下:
if (isIt) { RequestResponse requestResponse = new RequestResponse(); try { // 设置字段可访问(即使字段是private也能读取,避免IllegalAccessException) field.setAccessible(true); // 从serverParams实例中获取该字段对应的Server对象 IServerParams serverInstance = (IServerParams) field.get(serverParams); // 传入doSomething方法 requestResponse.doSomething(serverInstance); } catch (IllegalAccessException e) { throw new RuntimeException("无法访问配置字段", e); } }
关键说明:
field.get(Object obj)方法需要传入字段所属的实例对象,这里就是serverParams,因为field是ServerParams类的成员字段,必须从具体的serverParams实例中取值。- 调用
field.setAccessible(true)确保即使字段是私有也能正常访问,避免权限异常。 - 将获取到的字段值强转为
IServerParams类型,因为Server是它的子类,类型匹配符合多态要求,能直接传入doSomething方法。 - 捕获
IllegalAccessException并包装成运行时异常抛出,适配当前方法的异常处理逻辑。
内容的提问来源于stack exchange,提问作者user1126946
相关产品推荐
相关产品推荐

