Pergunta

I acontecer vir através de um código Java no meu local de trabalho. Aqui está o cenário:. Existem 2 classes - ClassA e ClassB

ClassA não tem nada, exceto 4 valores static final String públicas dentro dela. Seu objetivo é usar esses valores como ClassA.variable (não me pergunte porquê, não é o meu código).

importações ClassB ClassA. Eu editei os valores de cadeia no ClassA e compilou. Quando eu corri ClassB Eu podia ver que ele estava usando os valores antigos - e não os novos valores. Eu tive que ClassB recompilação para torná-lo usar os novos valores a partir ClassA! (Eu tinha que recompilar outras classes que as importações ClassA!)

Este é apenas por causa do JDK 1.6 ou eu deveria ter conhecido mais cedo para ClassB recompilação também! Me esclareça. :)

Foi útil?

Solução

Se os valores das variáveis ??final de ClassA classe acontecer a ser constantes de tempo de compilação, o compilador poderia ter inline-los nas classes usando ClassA em vez de gerar uma referência de tempo de execução. Eu acho, isso é o que aconteceu no caso que você descreveu.

Exemplo:

public class Flags {
    public static final int FOO = 1;
    public static final int BAR = 2;
}

public class Consumer {
    public static void main(String[] args) {
         System.out.println(Flags.FOO);
    }
}

Neste exemplo, o compilador provavelmente incorporar o valor de FOO no código gerada por Consumer em vez de gerar a referência de tempo de execução equivalente. Se o valor da FOO muda mais tarde, você terá que Consumer re-compilação, a fim de que ele use o novo valor.

Esta é uma otimização, que tem algumas vantagens em relação à eficiência e velocidade do programa compilado. Por exemplo, inlining o valor pode permitir novas otimizações nas expressões, que o utilizam, por exemplo:

int x = Flags.FOO * 10;

Neste exemplo, inlining o valor (aqui: 1) permite que o compilador para o aviso prévio, que a multiplicação não faz diferença, e pode ser omitido alltogether

.

Outras dicas

É um problema de compatibilidade binária. Referências a campos constantes são resolvidas em tempo de compilação. O comportamento que você está vendo é correta; Se você alterar os valores da classe A, em seguida, você terá que re-compilar o cliente (classe B). Para evitar tais problemas consideram constantes acrescentando que utilizam um tipo de enumeração, introduzida em versão Java 5.0.

Por que você está tentando compilar as classes individualmente?

Use um sistema de compilação como o Maven ou formiga ou apenas deixar o seu IDE fazê-lo.

A única coisa segura a fazer é recompilar todos os java que depende de uma classe java que mudou até que cada classe que pode ser efectuada foi re-compilados.

Se você não estiver usando os valores em um interruptor que você pode fazer isso em vez disso:

public class A
{
    public static final int FOO;
    public static final String BAR;

    static
    {
        FOO = 42;
        BAR = "Hello, World!";
    }
}

então o compilador não será mais duro código os valores nas outras classes que estão usando-os.

Suponha que ClassA parece com isso:

public class ClassA {
    public static final int FOO = 1;
    public static final int BAR = 2;
}

Se você recompilar-lo, ClassB continuará usando os valores antigos. Eu acho que poderia depender do compilador, mas acho que este é o comportamento típico. Se você não quiser recompilar ClassB toda uma constante em mudanças ClassA, você vai ter que fazer algo como isto:

public class ClassA {
    public static final int FOO = CONST(1);
    public static final int BAR = CONST(2);

    public static int CONST(int i) { return i; }
}

Becuase agora javac não está disposto para inline as constantes. Em vez disso, irá chamar o método CONST (int) quando estática de ClassA initializer executado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top