Caricamento classe vs inizializzazione: variabile finale statica Java [duplicato]

Aug 22 2020

Esempio.java

public class Example {

    static final int i = 10;
    static int j = 20;
    static {
        System.out.println("Example class loaded and initialized");
    }
}

Use.java

import java.util.Scanner;
public class Use {
    public static void main(String args[]){
        Scanner sc = new Scanner(System.in);
        int ch = 1;
        while(ch != 0) {
            System.out.print("Enter choice: ");
            ch = sc.nextInt();

            if (ch == 1) {
                System.out.println("Example's i = " + Example.i);
            } else if(ch == 2){
                System.out.println("Example's j = " + Example.j);
            }
        }
    }
}

Quando eseguo con java -verbose:class Use, e fornisco input, l' 1output è 10cioè il ivalore costante . Ma la Exampleclasse non è ancora stata caricata. Tuttavia, quando fornisco input come 2, solo allora la Example classe viene caricata nella JVM, come visibile dall'output dettagliato , quindi viene eseguito il blocco statico all'interno di Example e anche jil valore di viene inizializzato e quindi stampato.

La mia domanda è: se per l'input, 1ovvero quando il valore finale statico (costante) di una classe Exampleviene richiesto in un'altra classe Use, da dove viene prelevato il valore costante se la classe Examplenon è mai stata caricata nella JVM fino ad allora? Quando e come è stato iinizializzato il finale statico e archiviato nella memoria JVM?

Risposte

2 Joni Aug 22 2020 at 17:31

Secondo la sezione 12.4.1 delle specifiche del linguaggio Java (enfasi aggiunta):

Una classe o un'interfaccia di tipo T verrà inizializzata immediatamente prima della prima occorrenza di uno qualsiasi dei seguenti:

  • T è una classe e viene creata un'istanza di T.

  • Viene invocato un metodo statico dichiarato da T.

  • Viene assegnato un campo statico dichiarato da T.

  • Viene utilizzato un campo statico dichiarato da T e il campo non è una variabile costante (§4.12.4).

Una variabile costante è una variabile finale inizializzata con un'espressione costante . Nel codice Example.iè una variabile costante e quindi non causa il caricamento della classe.

Quindi, se la classe non viene caricata, da dove viene il valore com?

La specifica del linguaggio richiede che il compilatore inline il suo valore. Dalla sezione della compatibilità binaria 13.1 :

  1. Un riferimento a un campo che è una variabile costante (§4.12.4) deve essere risolto in fase di compilazione al valore V indicato dall'inizializzatore della variabile costante.

    Se tale campo è statico, nessun riferimento al campo dovrebbe essere presente nel codice in un file binario, inclusa la classe o l'interfaccia che ha dichiarato il campo. Tale campo deve sempre sembrare inizializzato (§12.4.2); il valore iniziale di default del campo (se diverso da V) non deve mai essere rispettato.