是否可以禁止内联最终字符串?可能这是一个奇怪的要求,但我需要在运行时更改最终字段值。这是单元测试的必要条件。
例如:
class asd {
public static final String value = "sdfmsdkofl";
public String getValue() {
return value;
}
}
我需要以某种方式避免内联value
变量。我无法更改源代码:(。这意味着我无法更改字段的访问方式,添加getter和setter。
一些可以关闭ALL
优化的神奇参数,即便如此简单。
答案 0 :(得分:1)
你做不到。唯一可行的解决方法是使常量不是final
,这使得它不是常数。您应该正在做的是重新组织您的代码,以便可以在没有这种疯狂的情况下进行测试。
答案 1 :(得分:0)
嗯。第一个问题:在生产代码中这是一件坏事。我已经在测试中完成了(切换jdbc驱动程序),但这不是一个好主意。 但是:如果你早做的话,这可能是可行的。 JavaC(假设你使用的是Oracle)没有优化,它都是由JIT完成的。所以,如果你在JIT发挥其魔力之前改变它,那么应该没问题。 理论上,您应该能够在运行时优化之后更改值,因为一旦您更改了字符串,JIT:ed代码应该被标记为不再有效但在这里我确实在非常薄的冰上滑行。 / p>
这是我测试代码的(部分)。
我需要更改此类中的驱动程序:
class MysqlConnection {
private static final String DRIVER_NAME = "com.mysql.jdbc.Driver";
protected Connection instantiateNewConnection() {
try {
// The newInstance() call is a work around for some
// broken Java implementations
Class.forName(DRIVER_NAME).newInstance();
} catch (Exception ex) {
// handle the error
LOG.info("Class Exception: " + ex);
}
}
}
我这样做:
class DBOperation {
static {
Field f = MysqlConnection.class.getDeclaredField("DRIVER_NAME");
f.setAccessible(true);
f.set(f, LocalFlipper.HSQLDB_DRIVER);
}
}
这很有效。可以在java中更改最终字段,这不是一个好主意。 首先我修改有问题的字段,然后我实例化一个实例,DRIVET_NAME字段包含我想要的jdbc驱动程序。
似乎有些怀疑这是否有效,但我可以向你保证,为自己尝试一下。
@LouisWasserman:我已经离开了javap:ed部分代码:
Class.forName(DRIVER_NAME).newInstance();
对应
28: ldc #16; //String com.mysql.jdbc.Driver
30: invokestatic #17; //Method java/lang/Class.forName(Ljava/lang/String;)Ljava/lang/Class;
33: invokevirtual #18; //Method java/lang/Class.newInstance:()Ljava/lang/Object;
如您所见,字符串未内联。此外,如何内联对象(或复杂类型)?您可以自然地内联引用。我同意,如果我们有像
这样的代码Class.forName("com.mysql.jdbc.Driver");
然后无法访问该字符串,因为我们无法获取它的引用。