说我有jar文件jarA
和jarB
。
class A
位于jarA
:
class A {
public static final String SQL = "select `col1`, `col2`, ... `col50` from `table`";
}
class B
位于jarB
:
class B {
public void loadData() {
String sql = "some other sql";
...
A a = null;
sql = a.SQL + " where something = something"; //This actually works, I never thought about it before I saw this code.
executeSQL(sql); //jdbc stuff
}
}
当我在类路径中运行(并稍后调试)jarB
jarA
时,发生了奇怪的事情:
执行的sql缺少col25
,就像select col1, col2, ..., col24, col26, ..., col50 from ...
当我调试它时,暂停在executeSQL(sql)
之前的某个地方,我在下面运行了一些表达式:
A.SQL
返回正确的字符串(使用col25
)
a.SQL
也正确返回
sql
不存在 col25
几乎是正确的
醇>
我在启动时添加了-verbose:class
,我可以看到class A
确实是从jarA
加载的。然后我解压jarA
,找到A.class
,对其进行逆向工程,我可以看到字符串SQL
是正确的。
我知道肯定有问题。但是我应该研究哪些建议,或者任何猜测?
答案 0 :(得分:5)
SQL是一个编译时常量。这意味着,当编译 B类时,const int n = SOME_VALUE;
int arr[n][n];
//rest remains same
字符串值将以B&#39的字节码内联。
所以,我的猜测是在A.SQL中缺少col25,B是针对这个不正确的类编译的,然后A.SQL被修复并重新编译,但是B没有被重新编译。所以它的字节码仍然包含不正确的sql字符串。
重新编译B,或者,如果SQL实际上不是常数(即永远不会改变的值),则不要将其作为公共常量公开。相反,定义一个返回SQL字符串的方法,并使用B类中的该方法。