java - 尝试更改静态非最终字段会引发 IllegalArgument 异常

标签 java reflection

具有私有(private)静态非最终字段的类

package sample;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class App {
   private static Logger logger = LoggerFactory.getLogger(App.class);

   public void doSomething() {
      logger.error("Cannot do something");
   }
}

尝试通过反射设置该字段

package sample;

import org.apache.logging.log4j.core.Logger;
import org.junit.jupiter.api.Test;
import org.springframework.test.util.ReflectionTestUtils;

import static org.mockito.Mockito.mock;

public class AppTest {

    @Test
    public void doSomething() throws Exception {
        App app = new App();

        Logger mockedLogger = mock(Logger.class);

        ReflectionTestUtils.setField(App.class, "logger", mockedLogger);
    }
}

导致 IllegalArgumentException

Can not set static org.slf4j.Logger field sample.App.logger to org.apache.logging.log4j.core.Logger$MockitoMock$1185285221
java.lang.IllegalArgumentException: Can not set static org.slf4j.Logger field sample.App.logger to org.apache.logging.log4j.core.Logger$MockitoMock$1185285221
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at sun.reflect.UnsafeStaticObjectFieldAccessorImpl.set(UnsafeStaticObjectFieldAccessorImpl.java:79)
    at java.lang.reflect.Field.set(Field.java:764)
    at org.springframework.util.ReflectionUtils.setField(ReflectionUtils.java:633)

根据调用方法的JavaDocs

https://docs.spring.io/spring-framework/docs/5.2.20.RELEASE/javadoc-api/org/springframework/test/util/ReflectionTestUtils.html#setField-java.lang.Class-java.lang.String-java.lang.Object-

Set the static field with the given name on the provided targetClass to the supplied value.

支持设置静态字段。

最佳答案

由于根据堆栈跟踪,java.lang.reflect.Field.set 抛出了 IllegalArgumentException,javadoc for Field.set具体原因可咨询。

它指出:

IllegalArgumentException - if the specified object is not an instance of the class or interface declaring the underlying field (or a subclass or implementor thereof), or if an unwrapping conversion fails.

比较您提供的 App 和 AppTest 类可以发现 AppTest 导入 org.apache.logging.log4j.core.Logger 而 App 导入 org.slf4j.Logger

由于您尝试注入(inject)记录器的模拟,因此请将 AppTest 中的第一个导入更改为 org.slf4j.logger

关于java - 尝试更改静态非最终字段会引发 IllegalArgument 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/76794027/

相关文章:

java - 自定义对象中的方法应该具有破坏性吗?

java - Codenameone 上的 YouTube 播放器

java - 如果则 else 逻辑未从 String targetID = ((Node) targetId.item(0)).getNodeValue(); 中获取结果

Java 解包参数列表

java - 反射和元数据之间的区别

java - 一个类中有多个具有相同参数类型的方法

java - 为什么消息从未发送?

java - 如何将数据从servlet发送到rest api

reflection - 获得当前类(class)

c# - 如何从其访问器中获取属性的唯一标识符