问题描述
具体来说,我试图为需要使用 File.separatorChar
的方法创建一个单元测试,以在windows和unix上构建路径。代码必须在两个平台上运行,但是当我试图改变这个静态最终字段时,我得到了JUnit的错误。
任何人有任何想法是怎么回事? p>
Field field = java.io.File.class.getDeclaredField(separatorChar);
field.setAccessible(true);
field.setChar(java.io.File.class,'/');
当我这样做的时候,我得到了
IllegalAccessException:无法将静态最终字符字段设置为java.io.File.separatorChar为java.lang.Character
想法?
从:
$ b
所以起初看起来你运气不好,因为 File.separatorChar
是 static
。令人惊讶的是, 是解决这个问题的一种方法:只需使 static
字段不再为 final $ c $通过反思。
我改编了这个解决方案:
$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ b field.setAccessible(true);
//从字段
中删除最终修饰符字段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); //打印#
请谨慎使用此技术。抛开破坏性的后果,以下实际工作:
pre $ setFinalStatic(Boolean.class.getField(FALSE),true);
System.out.format(Everything is%s,false); //一切都是真实的
重要更新:上述解决方案不适用于所有情况。如果该字段在被重置之前通过Reflection访问并读取,则会抛出 IllegalAccessException
。由于Reflection API创建缓存并重用的内部 FieldAccessor
对象(请参阅java.lang.reflect.Field#acquireFieldAccessor(boolean)实现),所以失败。
示例测试代码失败:
字段f = File.class.getField(separatorChar); f.setAccessible(真); f.get(NULL);
//像以前一样调用setFinalStatic:throws IllegalAccessException
Specifically, I'm trying to create a unit test for a method which requires uses File.separatorChar
to build paths on windows and unix. The code must run on both platforms, and yet I get errors with JUnit when I attempt to change this static final field.
Anyone have any idea what's going on?
Field field = java.io.File.class.getDeclaredField( "separatorChar" );
field.setAccessible(true);
field.setChar(java.io.File.class,'/');
When I do this, I get
IllegalAccessException: Can not set static final char field java.io.File.separatorChar to java.lang.Character
Thoughts?
From the documentation for Field.set
:
So at first it seems that you are out of luck, since File.separatorChar
is static
. Surprisingly, there is a way to get around this: simply make the static
field no longer final
through reflection.
I adapted this solution 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);
}
I've tested it and it works:
setFinalStatic(File.class.getField("separatorChar"), '#');
System.out.println(File.separatorChar); // prints "#"
Do exercise extreme caution with this technique. Devastating consequences aside, the following actually works:
setFinalStatic(Boolean.class.getField("FALSE"), true);
System.out.format("Everything is %s", false); // "Everything is true"
Important update: the above solution does not work in all cases. If the field is made accessible and read through Reflection before it gets reset, an IllegalAccessException
is thrown. It fails because the Reflection API creates internal FieldAccessor
objects which are cached and reused (see the java.lang.reflect.Field#acquireFieldAccessor(boolean) implementation).Example test code which fails:
Field f = File.class.getField("separatorChar"); f.setAccessible(true); f.get(null);
// call setFinalStatic as before: throws IllegalAccessException
这篇关于使用反射改变静态最终File.separatorChar单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!