说我有jar文件jarA和jarB.
class A在jarA:
class A {
public static final String SQL = "select `col1`, `col2`, ... `col50` from `table`";
}
Run Code Online (Sandbox Code Playgroud)
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
}
}
Run Code Online (Sandbox Code Playgroud)
当我在类路径中运行(以及稍后调试)jarB时jarA,发生了奇怪的事情:
执行的sql丢失了col25,就像是select col1, col2, ..., col24, col26, ..., col50 from ...
当我调试它,在executeSQL(sql)事情之前的某个地方暂停时,我在下面运行了一些表达式:
A.SQL返回正确的字符串(with col25)
a.SQL 也正确返回
sql几乎是正确的,除非col25那里没有
我-verbose:class在启动时添加,我可以看到class A确实是从中加载的jarA.然后我解压缩jarA,发现A.class,逆向工程,我可以看到字符串SQL是正确的.
我知道肯定有问题.但是我应该研究哪些建议,或者任何疯狂的猜测?
SQL是一个编译时常量.这意味着,在编译 B类时,A.SQL字符串值将以B的字节码内联.
所以,我的猜测是在A.SQL中缺少col25,B是针对这个不正确的类编译的,然后A.SQL被修复并重新编译,但是B没有被重新编译.所以它的字节码仍然包含不正确的sql字符串.
重新编译B,或者,如果SQL实际上不是常量(即永远不会改变的值),则不要将其公开为公共常量.相反,定义一个返回SQL字符串的方法,并使用B类中的该方法.