Java中的一个神秘字符串

时间:2015-12-08 12:58:42

标签: java

说我有jar文件jarAjarB

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时,发生了奇怪的事情:

  1. 执行的sql缺少col25,就像select col1, col2, ..., col24, col26, ..., col50 from ...

  2. 当我调试它时,暂停在executeSQL(sql)之前的某个地方,我在下面运行了一些表达式:

    A.SQL返回正确的字符串(使用col25

    a.SQL也正确返回

    除了sql不存在

  3. 之外,

    col25几乎是正确的

    我在启动时添加了-verbose:class,我可以看到class A确实是从jarA加载的。然后我解压jarA,找到A.class,对其进行逆向工程,我可以看到字符串SQL是正确的。

    我知道肯定有问题。但是我应该研究哪些建议,或者任何猜测?

1 个答案:

答案 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类中的该方法。