gpt4 book ai didi

java - 使用反射更改静态最终 File.separatorChar 进行单元测试?

转载 作者:IT老高 更新时间:2023-10-28 21:21:04 29 4
gpt4 key购买 nike

具体来说,我正在尝试为需要使用 File.separatorChar 在 windows 和 unix 上构建路径的方法创建单元测试。代码必须在两个平台上运行,但是当我尝试更改这个静态 final 字段时,我遇到了 JUnit 错误。

有人知道发生了什么吗?

Field field = java.io.File.class.getDeclaredField( "separatorChar" );
field.setAccessible(true);
field.setChar(java.io.File.class,'/');

当我这样做时,我得到

IllegalAccessException: Can not set static final char field java.io.File.separatorChar to java.lang.Character

想法?

最佳答案

来自 Field.set 的文档:

If the underlying field is final, the method throws an IllegalAccessException unless setAccessible(true) has succeeded for this field and this field is non-static.

所以一开始你似乎不走运,因为 File.separatorCharstatic。令人惊讶的是,一种解决此问题的方法:只需通过反射使 static 字段不再是 final

我调整了这个解决方案 from javaspecialist.eu :

static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);

// remove final modifier from field
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);

field.set(null, newValue);
}

我已经测试过了,它可以工作:

setFinalStatic(File.class.getField("separatorChar"), '#');
System.out.println(File.separatorChar); // prints "#"

对这种技术要格外小心。撇开毁灭性的后果不谈,以下实际上是有效的:

setFinalStatic(Boolean.class.getField("FALSE"), true);
System.out.format("Everything is %s", false); // "Everything is true"

重要更新:上述解决方案并非适用于所有情况。如果该字段在重置之前可访问并通过反射读取,则会引发 IllegalAccessException。它失败是因为反射 API 创建了内部 FieldAccessor 对象,这些对象被缓存和重用(请参阅 java.lang.reflect.Field#acquireFieldAccessor(boolean) 实现)。失败的示例测试代码:

Field f = File.class.getField("separatorChar"); f.setAccessible(true); f.get(null);
// call setFinalStatic as before: throws IllegalAccessException

关于java - 使用反射更改静态最终 File.separatorChar 进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2474017/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com