Variabili globali in Java


217

Come si definiscono le variabili globali in Java?


20
Puoi dirci perché vuoi definire le variabili globali in Java?
Adam Paynter,

44
Per accedere alla variabile dall'esterno della classe
aTJ

5
Forse dovresti modificare la tua domanda per includere un codice di esempio che illustri esattamente ciò che desideri. Ci aiuterebbe a raccomandare la soluzione migliore.
Adam Paynter,

7
@Adam: dovrei essere in grado di cambiare il valore di una variabile in una classe da un'altra classe.
aJ

2
Tu no. Non ci sono variabili globali in Java.
Marchese di Lorne,

Risposte:


261

Per definire la variabile globale è possibile utilizzare parole chiave statiche

public class Example {
    public static int a;
    public static int b;
}

ora puoi accedere a eb da qualsiasi luogo chiamando

Example.a;

Example.b;

6
"Global" è il nome della classe.
Girolamo

12
Fai attenzione quando esegui questa operazione: quando la classe Global viene scaricata, le variabili non saranno definite nulle. Se vendi la tua app questo accadrà prima o poi e continuerai a cercare errori ovunque ma non lì ....
user387184

10
La staticparola chiave rende le variabili accessibili a livello globale, mentre la loro classe viene caricata.
sabato

22
Informazioni sullo scarico di classe: se esiste una catena di riferimento forte da qualsiasi radice GC a un'istanza di Global o dei suoi figli, o qualsiasi riferimento in fase di compilazione da una classe caricata e non scaricabile a Global, l'oggetto Class relativo a Global è fortemente raggiungibile, e quindi anche il ClassLoader che ha caricato Global; il che rende impossibile scaricare Global (poiché lo scaricamento di classe può avvenire solo dopo che il GC ha rimosso completamente qualsiasi riferimento forte al ClassLoader che ha caricato una determinata classe). Se non hai alcun riferimento, come potrebbe essere un problema lo scarico ???
Bruno Reis,

4
@Abi Suggerirei di rinominare la tua classe Globalin qualcos'altro ( TestClass?) Per non dare alle persone l'impressione che esista una Globalparola chiave Java. Meglio prevenire che curare :)
Nicolas Rinaudo,

53

Tu no. Questo è di progettazione. Non dovresti farlo anche se potessi.

Detto questo, potresti creare un insieme di membri statici pubblici in una classe chiamata Globals.

public class Globals {
   public static int globalInt = 0;
   ///
}

ma non dovresti davvero :). Seriamente .. non farlo.


6
Allora qual è l'approccio migliore che posso dichiarare le costanti in modo che tutti i metodi di classe possano accedervi?
Alston,

6
Messaggi di questa natura sono la ragione per cui i novizi sviluppano la fobia variabile globale, e quindi vediamo ogni sorta di tecniche egregie ideate per aggirare il tabù della variabile globale, ma ottenere lo stesso effetto.
Evgeni Sergeev,

38
Giù voto per dire "non farlo". senza spiegare o fare riferimento a una spiegazione del perché.
Jeff McCune,

4
@JeffMcCune: per rendere più chiara la tua affermazione, "non farlo" è in realtà una stronzata. Fallo quando è utile. Ad esempio, devo eseguire il debug del mio codice utilizzando alcuni IAbstractLoggerBullshit e, naturalmente, System.err non funziona in questo ambiente ingegnerizzato. Non riesco a sporcare il mio codice passando per la merda del logger tra centinaia di classi di adattatori inutili.
Jo So,

6
Lo farò.
Floating Sunfish,

40

Un altro modo è creare un'interfaccia come questa:

public interface GlobalConstants
{
  String name = "Chilly Billy";
  String address = "10 Chicken head Lane";
}

Qualsiasi classe che deve usarli deve solo implementare l'interfaccia:

public class GlobalImpl implements GlobalConstants
{
  public GlobalImpl()
  {
     System.out.println(name);
  }
}

Mi chiedo perché questa risposta non abbia (prima del mio) nessun voto positivo. Non fornisce una risposta alternativa ragionevole a quella fornita da tutte le altre risposte?
M_M,

12
Efficace Java di Joshua Bloch, Capitolo 4: Classi e interfacce, elemento 19: utilizzare le interfacce solo per definire i tipi "Il modello di interfaccia costante è un uso scarso delle interfacce". Vale la pena leggere questo libro! :)
MariuszS,

1
Inoltre da JDK 1.5+ è possibile utilizzare l'importazione statica per le variabili globali, l'implementazione non è necessaria.
MariuszS,

9
.... Giusto, questo in realtà non spiega nulla, che dice solo che alcuni libri hanno detto che era male.
linkhyrule5,

14
Ecco un preventivo per te. Oracle dice: "Per ovviare a ciò, le persone a volte inseriscono membri statici in un'interfaccia ed ereditano da quell'interfaccia. Questa è una cattiva idea. In realtà, è una cattiva idea che c'è un nome per questo: l'Antipasto Interfaccia Costante (vedi Articolo Java effettivo 17.) Il problema è che l'uso di una classe dei membri statici di un'altra classe è un mero dettaglio di implementazione. Quando una classe implementa un'interfaccia, diventa parte dell'API pubblica della classe. API pubbliche ".
Jolta

23

Stai meglio usando l'iniezione delle dipendenze:

public class Globals {
    public int a;
    public int b;
}

public class UsesGlobals {
    private final Globals globals;
    public UsesGlobals(Globals globals) {
        this.globals = globals;
    }
}

5
È vero, anche se penso che il tuo uso di "Globals" confonda un po 'le cose :-). Qualcosa come "Parametri" sarebbe più appropriato poiché non è necessariamente globale.
Mark Peters,

11

Molte buone risposte, ma voglio dare questo esempio in quanto è considerato il modo più appropriato per accedere alle variabili di una classe da un'altra classe: usare getter e setter.

Il motivo per cui usi getter e setter in questo modo invece di rendere pubblica la variabile è il seguente. Diciamo che il tuo var sarà un parametro globale che non vuoi MAI cambiare qualcuno durante l'esecuzione del tuo programma (nel caso in cui stai sviluppando codice con un team), qualcosa come forse l'URL di un sito web. In teoria questo potrebbe cambiare e potrebbe essere usato molte volte nel tuo programma, quindi vuoi usare un var globale per poterlo aggiornare tutto in una volta. Ma non vuoi che qualcun altro entri e cambi questo var (possibilmente senza rendersi conto di quanto sia importante). In tal caso semplicemente non includi un metodo setter e includi solo il metodo getter.

public class Global{
    private static int var = 5;

    public static int getVar(){
        return Global.var;
    }

    //If you do not want to change the var ever then do not include this
    public static void setVar(int var){
        Global.var = var;
    }
}

10

Non esiste una variabile globale in Java

Tuttavia, ciò che abbiamo è una staticparola chiave e questo è tutto ciò di cui abbiamo bisogno. Non esiste nulla al di fuori della classe in Java. La staticparola chiave rappresenta una variabile di classe che, contrariamente alla variabile di istanza, ha solo una copia e che trascende attraverso tutte le istanze di quella classe creata, il che significa che il suo valore può essere modificato e accessibile in tutte le istanze in qualsiasi momento.

Se hai bisogno di una variabile globale a cui è possibile accedere oltre gli ambiti, questa è la variabile di cui hai bisogno, ma il suo ambito esiste solo dove si trova la classe e sarà tutto.


9

In verità, non esiste un concetto di "GLOBALE" in un programma OO Java

Tuttavia c'è qualche verità dietro la tua domanda perché ci saranno alcuni casi in cui vuoi eseguire un metodo in qualsiasi parte del programma. Ad esempio il metodo --- random () nell'app Phrase-O-Matic; è un metodo che può essere richiamato da qualsiasi programma.

Quindi, al fine di soddisfare le cose come sopra "Dobbiamo avere variabili e metodi di tipo globale"

DICHIARARE UN VARIABILE COME GLOBALE.

 1.Mark the variable as public static final While declaring.

DICHIARARE UN METODO COME GLOBALE .

 1. Mark the method as public static While declaring.

Poiché ho dichiarato variabili e metodi globali come statici, puoi chiamarli ovunque tu voglia semplicemente con l'aiuto del seguente codice

ClassName.X

NOTA : X può essere il nome del metodo o il nome della variabile secondo il requisito e ClassName è il nome della classe in cui sono stati dichiarati.


9

Nulla dovrebbe essere globale, tranne le costanti.

public class MyMainClass {
    public final static boolean DEBUGMODE=true;
}

Inserisci questo nella tua classe principale. In altri file .java, usalo attraverso:

if(MyMainClass.DEBUGMODE) System.out.println("Some debugging info");

Assicurati di spostare il codice dal pavimento della sala di taglio e di rilasciarlo rimuovendo o commentando questa funzionalità.

Se hai un metodo cavallo di battaglia, come un randomizzatore, ti suggerisco di creare un pacchetto "Toolbox"! Tutti i programmatori dovrebbero averne uno, quindi ogni volta che vuoi usarlo in un .java, importalo!


5

Non esiste una variabile veramente globale in Java. Ogni variabile statica deve appartenere a una classe (come System.out), ma quando hai deciso in quale classe andrà, puoi farvi riferimento da qualsiasi punto caricato dallo stesso classloader.

Si noti che le variabili statiche devono sempre essere protette durante l'aggiornamento per evitare condizioni di gara.


1
java non fornisce una variabile globale funzionalmente ma se vuoi avere un concetto di variabile globale, possiamo usare una parola chiave statica
Abi

3
public class GlobalClass {
     public static int x = 37;
     public static String s = "aaa";
}

In questo modo è possibile accedervi con GlobalClass.xeGlobalClass.s


2
public class GlobalImpl {   

 public static int global = 5;

}

puoi chiamare dove vuoi:

GlobalImpl.global // 5

1

Come probabilmente indovini dalla risposta, non ci sono variabili globali in Java e l'unica cosa che puoi fare è creare una classe con membri statici:

public class Global {
    public static int a;
}

Puoi usarlo con Global.aaltrove. Tuttavia, se usi Java 1.5 o meglio, puoi usare la import staticmagia per renderlo ancora più una vera variabile globale:

import static test.Global.*;

public class UseGlobal {
    public void foo() {
        int i = a;
    }
}

E voilà !

Ora questa è tutt'altro che una buona pratica, come puoi vedere negli spot pubblicitari: non farlo a casa


1

Non ci sono variabili globali in Java, ma ci sono classi globali con campi pubblici. È possibile utilizzare la funzione di importazione statica di java 5 per far sembrare quasi variabili globali.


1

La variabile generalmente globale (suppongo che la stia confrontando con C, Cpp) definisce come public static final

piace

class GlobalConstant{
    public static final String CODE  = "cd";
}

Gli ENUM sono utili anche in tale scenario:

Per esempio Calendar.JANUARY)


Una variabile globale deve essere definitiva? Perché?
Konerak,

1
"finale" significa "costante", quindi questa è una costante globale.
Duffymo,

1
no, questo è ciò che significa variabile globale se vuoi condividere quella variabile e cambiare anche i dati, quindi rimuovi finalma dipende sicuramente da come vuoi condividere, dove stai usando e tutto il resto,
Jigar Joshi

Di che tipo è CODEin questo esempio? Dove è definito?
M_M,

Nota anche: CODICE è in maiuscolo, in quanto la sua comune notazione java utilizza tutti i maiuscoli per le variabili dichiarate come definitive e che non si intende modificare nel corso di un programma.
Dan Ciborowski - MSFT,

1

Creazione di un file indipendente, ad es. Esempio.java di usare la prima soluzione, va bene. Puoi farlo anche all'interno dell'app, se ad esempio le variabili globali sono speciali per la tua app corrente, ecc .:

Crea una classe all'inizio e dichiara le tue variabili lì dentro:

class Globals {
  static int month_number;
  static String month_name;
}

Puoi quindi accedere a queste variabili, usandole come "Globals.month_number", ecc. - da qualsiasi punto della tua app.


Invece di effettuare il downgrade, puoi dirmi cosa c'è di sbagliato in questa soluzione? Lo sto usando su base costante ed è il più conveniente. Quindi non posso fare diversamente che considerare questo downvote come una cosa personale o appena fatto da una persona stupida.
Apostolos il

1

Se è necessario aggiornare la proprietà globale, una semplice classe wrapper getter / setter può essere utilizzata come variabile globale. Un esempio tipico è mostrato di seguito.

public class GlobalHolder {

    private static final GlobalHolder INSTANCE = new GlobalHolder();

    private volatile int globalProperty;

    public static GlobalHolder getInstance() {
        return INSTANCE;
    }

    public int getGlobalProperty() {
        return globalProperty;
    }

    public void setGlobalProperty(int globalProperty) {
        this.globalProperty = globalProperty;
    }

    public static void main(String[] args) {
        GlobalHolder.getInstance().setGlobalProperty(10);
        System.out.println(GlobalHolder.getInstance().getGlobalProperty());
    }
}

0

Seguendo il concetto, le variabili globali, note anche come variabili di istanza sono le variabili a livello di classe, cioè sono definite all'interno di una classe ma metodi esterni. Per renderli completamente disponibili e utilizzarli, fornire direttamente la parola chiave statica. Quindi, se sto scrivendo un programma per una semplice operazione aritmetica e richiede una coppia di numeri, allora due variabili di istanza sono definite come tali:

public class Add {
    static int a;
    static int b; 
    static int c;

    public static void main(String arg[]) {
        c=sum();
        System.out.println("Sum is: "+c); 
    }

    static int sum() {
       a=20;
       b=30;
       return a+b;   
    }
}

Output: Sum is: 50

Inoltre, l'uso di parole chiave statiche prima delle variabili di istanza ci consente di non specificare più volte tipi di dati per le stesse variabili. Basta scrivere direttamente la variabile.


1
Non ci sono variabili globali in Java; non sono noti anche come variabili di istanza; definendoli in quanto staticnon li "rende completamente disponibili". Il primo paragrafo è una sciocchezza. L'esempio è una cattiva pratica.
Marchese di Lorne,

0

In generale, Java non ha variabili globali. Oltre alle variabili locali, tutte le variabili rientrano nell'ambito di qualsiasi classe definita nel programma. Possiamo avere variabili statiche per avere l'ambito delle variabili globali.


0

senza staticquesto è anche possibile:

class Main {
  String globalVar = "Global Value";

  class Class1 {
    Class1() {
      System.out.println("Class1: "+globalVar);
      globalVar += " - changed";
  } }
  class Class2 {
    Class2() {
      System.out.println("Class2: "+globalVar);
  } }

  public static void main(String[] args) {  
    Main m = new Main();
    m.mainCode();
  }
  void mainCode() {
    Class1 o1 = new Class1();
    Class2 o2 = new Class2();
  }
}

/*
Output:
Class1: Global Value
Class2: Global Value - changed
*/

0

La programmazione orientata agli oggetti è costruita con la consapevolezza che l'ambito delle variabili è strettamente esclusivo dell'oggetto classe che incapsula tali variabili.

Il problema con la creazione di "variabili globali" è che non è uno standard industriale per Java. Non è uno standard industriale perché consente a più classi di manipolare i dati asincronati, se si esegue un'applicazione multi-thread, questo diventa un po 'più complicato e pericoloso in termini di sicurezza dei thread. Vi sono vari altri motivi per cui l'uso delle variabili globali è inefficace, ma se si desidera evitarlo, suggerisco di ricorrere alla programmazione orientata agli aspetti .

La programmazione orientata all'aspetto annulla questo problema mettendo la classe genitrice responsabile dell'ambito attraverso qualcosa chiamato "consigli", che aggiunge un ulteriore comportamento al codice senza modificarlo effettivamente. Offre soluzioni a problemi trasversali o utilizzo variabile globale.

Spring è un framework Java che utilizza AOP e, sebbene sia tradizionalmente utilizzato per applicazioni Web, l'applicazione principale può essere utilizzata universalmente in tutto il framework Java (8.0 incluso). Questa potrebbe essere una direzione che vuoi esplorare di più.


0

Comprensione del problema

Considero la qualificazione della variabile globale come una variabile a cui è possibile accedere e modificare in qualsiasi punto del codice senza preoccuparsi della chiamata statica / di istanza o passando qualsiasi riferimento da una classe all'altra.

Di solito se hai la classe A

public class A {
    private int myVar;

    public A(int myVar) {
        this.myVar = myVar;
    }

    public int getMyVar() {
        return myVar;
    }

    public void setMyVar(int mewVar) {
        this.myVar = newVar;
    }
}

e vuoi accedere e aggiornare myvarin una classe B,

public class B{

    private A a;

    public void passA(A a){
        this.a = a;
    }

    public void changeMyVar(int newVar){
        a.setMyvar(newVar);
    }
}

dovrai avere un riferimento a un'istanza della classe A e aggiornare il valore nella classe B in questo modo:

int initialValue = 2;
int newValue = 3;
A a = new A(initialValue);
B b = new B();
b.passA(a);
b.changeMyVar(newValue);
assertEquals(a.getMyVar(),newValue); // true

Soluzione

Quindi la mia soluzione a questo, (anche se non sono sicuro che sia una buona pratica), è usare un singleton:


public class Globals {
    private static Globals globalsInstance = new Globals();

    public static Globals getInstance() {
        return globalsInstance;
    }

    private int myVar = 2;

    private Globals() {
    }

    public int getMyVar() {
        return myVar;
    }

    public void setMyVar(int myVar) {
        this.myVar = myVar;
    }
}

Ora puoi ottenere l'istanza unica globale ovunque con:

Globals globals = Globals.getInstance();
// and read and write to myVar with the getter and setter like 
int myVar = globals.getMyVar();
global.setMyVar(3);

-1
// Get the access of global while retaining priveleges.
// You can access variables in one class from another, with provisions.
// The primitive must be protected or no modifier (seen in example).

// the first class
public class farm{

  int eggs; // an integer to be set by constructor
  fox afox; // declaration of a fox object

  // the constructor inits
  farm(){
    eggs = 4;
    afox = new fox(); // an instance of a fox object

    // show count of eggs before the fox arrives
    System.out.println("Count of eggs before: " + eggs);

    // call class fox, afox method, pass myFarm as a reference
    afox.stealEgg(this);

    // show the farm class, myFarm, primitive value
    System.out.println("Count of eggs after : " + eggs);

  } // end constructor

  public static void main(String[] args){

    // instance of a farm class object
    farm myFarm = new farm();

  }; // end main

} // end class

// the second class
public class fox{

  // theFarm is the myFarm object instance
  // any public, protected, or "no modifier" variable is accessible
  void stealEgg(farm theFarm){ --theFarm.eggs; }

} // end class

2
Cosa aggiunge questa risposta che le altre risposte no? Non riesco a vedere alcun valore "nuovo" in questa risposta.
EWit

-2

Per definire la variabile globale è possibile utilizzare parole chiave statiche

public final class Tools {
  public static int a;
  public static int b;
}

ora puoi accedere a eb da qualsiasi luogo chiamando

Tools.a;
Tools.b;

Hai ragione ... specialmente in J2ME ... Puoi evitare NullPointerException inserendo nel tuo costruttore MidLet (inizializzazione non corretta) questa riga di codice:

new Tools();

Ciò garantisce che gli strumenti vengano allocati prima di qualsiasi istruzione che lo utilizza.

Questo è tutto!


3
Um ... Mi dispiace, ma cosa aggiunge questo che non è già coperto dalle risposte esistenti?
Mistico il

Forse hai ragione..ma questa risposta spiega cose come l'allocazione della memoria.
user2616742

Non ci sono classi statiche di primo livello in Java
Andremoniy,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.