Domanda

mi capita di incontrare un codice Java al mio posto di lavoro. Ecco lo scenario:. Ci sono 2 classi - ClassA e ClassB

ClassA non ha nulla, tranne 4 valori di stringa finale public static all'interno di esso. Il suo scopo è quello di utilizzare questi valori come ClassA.variable (non chiedetemi perchè, non è il mio codice).

importazioni ClassB ClassA. Ho modificato i valori di stringa in ClassA e compilato. Quando ho eseguito ClassB ho potuto vedere che stava usando i vecchi valori - non i nuovi valori. Ho dovuto ricompilare ClassB per rendere l'uso di nuovi valori da ClassA! (Ho dovuto ricompilare altre classi che le importazioni ClassA!)

E 'questo solo a causa del JDK 1.6 o avrei dovuto sapere prima di ricompilare ClassB anche! Illuminami. :)

È stato utile?

Soluzione

Se i valori delle variabili final dalla classe ClassA capita di essere costanti di compilazione, il compilatore avrebbe loro inline nelle classi usando ClassA invece di generare un riferimento di run-time. Credo che questo è ciò che è accaduto nel caso da te descritto.

Esempio:

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);
    }
}

In questo esempio, il compilatore probabilmente comprende il valore di FOO nel codice generato per Consumer invece di generare il riferimento runtime equivalenti. Se il valore dei cambiamenti FOO in seguito, si dovrà ricompilare Consumer al fine di avere esso uso il nuovo valore.

Questa è un'ottimizzazione, che ha alcuni vantaggi rispetto alla efficienza e la velocità del programma compilato. Ad esempio, il valore inlining potrebbe consentire ulteriori ottimizzazioni nelle espressioni, che lo utilizzano, ad esempio:

int x = Flags.FOO * 10;

In questo esempio, il valore inlining (qui: 1). Consente al compilatore di notare che la moltiplicazione fa differenza, e può essere omesso alltogether

Altri suggerimenti

E 'un problema di compatibilità binaria. I riferimenti ai campi costanti vengono risolti in fase di compilazione. Il comportamento che state vedendo è corretta; se si modificano i valori in classe A, allora si dovrà ricompilare il client (classe B). Per evitare tali problemi in considerazione l'aggiunta costanti utilizzando un tipo enum, introdotto in Java versione 5.0.

Perché stai cercando di compilare le classi singolarmente?

Utilizzare un sistema di compilazione, come Maven o formica o semplicemente lasciare che il vostro IDE farlo.

L'unica cosa sicura da fare è ricompilare ogni java che dipende di una classe Java che ha cambiato fino a quando ogni classe che potrebbe essere effettuato è stato ri-compilato.

Se non si utilizzano i valori in uno switch si può fare questo, invece:

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

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

il compilatore non sarà più difficile codificare i valori nelle altre classi che li utilizzano.

Supponiamo ClasseA assomiglia a questo:

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

Se si ricompila esso, ClassB continuerà ad utilizzare i vecchi valori. Credo che potrebbe dipendere dal compilatore, ma penso che questo è il comportamento tipico. Se non si desidera ricompilare ClassB ogni volta una costante nei cambiamenti ClassA, dovrete fare qualcosa di simile:

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 ora javac non è disposta a inline le costanti. Invece chiamerà il metodo CONST (int) quando inizializzatore statico di ClassA corre.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top