Variables globales en Java

217

Comment définissez-vous les variables globales en Java?

aTJ
la source
20
Pouvez-vous nous dire pourquoi vous souhaitez définir des variables globales en Java?
Adam Paynter
44
Pour accéder à la variable depuis l'extérieur de la classe
aTJ
5
Vous devriez peut-être modifier votre question pour inclure un exemple de code illustrant précisément ce que vous voulez. Cela nous aiderait à recommander la meilleure solution.
Adam Paynter
7
@Adam: Je devrais pouvoir changer la valeur d'une variable dans une classe d'une autre classe.
aTJ
2
Non. Il n'y a pas de variables globales en Java.
Marquis de Lorne

Réponses:

261

Pour définir la variable globale, vous pouvez utiliser un mot-clé statique

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

vous pouvez maintenant accéder à a et b de n'importe où en appelant

Example.a;

Example.b;
Abi
la source
6
"Global" est le nom de la classe.
Jerome
12
Soyez prudent lorsque vous faites cela - lorsque la classe Global est déchargée, les variables seront null non définies. Si vous vendez votre application, cela se produira tôt ou tard et vous continuerez à chercher des erreurs partout mais pas là ....
user387184
10
Le staticmot-clé rend les variables accessibles globalement, tandis que leur classe est chargée.
sjas
22
À propos du déchargement de classe: s'il existe une chaîne de référence forte depuis n'importe quelle racine GC vers une instance de Global ou ses enfants, ou toute référence de compilation d'une classe chargée et non déchargeable vers Global, alors l'objet Class relatif à Global est fortement accessible, et donc le ClassLoader qui a chargé Global; ce qui rend impossible le déchargement de Global (puisque le déchargement de classe ne peut avoir lieu qu'après que le GC a complètement supprimé toute référence forte au ClassLoader qui a chargé une classe donnée). Si vous n'avez aucune référence, comment le déchargement pourrait-il être un problème ???
Bruno Reis
4
@Abi Je vous suggère de renommer votre classe Globalen quelque chose d'autre ( TestClass?) Afin de ne pas donner aux gens l'impression qu'il existe un Globalmot clé Java. Mieux vaut prévenir que guérir :)
Nicolas Rinaudo
53

Non. C'est par conception. Vous ne devriez pas le faire même si vous le pouviez.

Cela étant dit, vous pouvez créer un ensemble de membres statiques publics dans une classe nommée Globals.

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

mais vous ne devriez vraiment pas :). Sérieusement .. ne le faites pas.

Mihai Toader
la source
6
Alors, quelle est la meilleure approche pour déclarer des constantes afin que toutes les méthodes de classe puissent y accéder?
Alston
6
Des messages de cette nature sont la raison pour laquelle les novices développent une phobie des variables globales, puis nous voyons toutes sortes de techniques flagrantes conçues pour contourner le tabou des variables globales, mais obtenir le même effet.
Evgeni Sergeev
38
Votez pour dire "ne le faites pas". sans expliquer ni se référer à une explication de pourquoi.
Jeff McCune
4
@JeffMcCune: pour rendre votre déclaration plus claire, "ne le faites pas" est en fait une connerie. Faites-le quand c'est utile. Par exemple, je dois déboguer mon code à l'aide de IAbstractLoggerBullshit et bien sûr System.err ne fonctionne pas dans cet environnement sur-conçu. Je ne peux pas jeter mon code en passant autour de la merde de l'enregistreur entre des centaines de classes d'adaptateur inutiles.
Jo So
6
Je vais le faire.
Sunfish flottant
40

Une autre façon est de créer une interface comme celle-ci:

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

Toute classe qui a besoin de les utiliser n'a qu'à implémenter l'interface:

public class GlobalImpl implements GlobalConstants
{
  public GlobalImpl()
  {
     System.out.println(name);
  }
}
Evan Lévesque
la source
Je me demande pourquoi cette réponse n'a (avant la mienne) aucun vote positif. N'apporte-t-il pas une réponse alternative raisonnable à celle fournie par toutes les autres réponses?
M_M
12
Java efficace par Joshua Bloch, Chapitre 4: Classes et interfaces, Article 19: Utiliser les interfaces uniquement pour définir les types "Le modèle d'interface constant est une mauvaise utilisation des interfaces." Ce livre mérite d'être lu! :)
MariuszS
1
De plus, à partir de JDK 1.5+, vous pouvez utiliser l'importation statique pour vos variables globales, l'implémentation n'est pas nécessaire.
MariuszS
9
.... D'accord, cela n'explique en fait rien, cela dit simplement qu'un livre a dit que c'était mauvais.
linkhyrule5
14
Voici un devis pour vous. Oracle dit: "Pour contourner ce problème, les gens mettent parfois des membres statiques dans une interface et héritent de cette interface. C'est une mauvaise idée. En fait, c'est une si mauvaise idée qu'il y a un nom pour cela: le Constant Interface Antipattern (voir Élément Java effectif 17). Le problème est que l'utilisation par une classe des membres statiques d'une autre classe n'est qu'un simple détail d'implémentation. Lorsqu'une classe implémente une interface, elle devient partie intégrante de l'API publique de la classe. Les détails d'implémentation ne doivent pas pénétrer dans API publiques. "
Jolta
23

Il vaut mieux utiliser l'injection de dépendance:

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

public class UsesGlobals {
    private final Globals globals;
    public UsesGlobals(Globals globals) {
        this.globals = globals;
    }
}
Peter Lawrey
la source
5
C'est vrai, bien que je pense que votre utilisation de "Globals" brouille un peu les choses :-). Quelque chose comme "Paramètres" serait plus approprié car ce n'est pas nécessairement Global.
Mark Peters
11

Beaucoup de bonnes réponses, mais je veux donner cet exemple car il est considéré comme le moyen le plus approprié d'accéder aux variables d'une classe par une autre classe: en utilisant des getters et des setters.

La raison pour laquelle vous utilisez les getters et setters de cette façon au lieu de simplement rendre la variable publique est la suivante. Disons que votre var va être un paramètre global que vous ne voulez JAMAIS que quelqu'un change pendant l'exécution de votre programme (dans le cas où vous développez du code avec une équipe), quelque chose comme peut-être l'URL d'un site Web. En théorie, cela peut changer et peut être utilisé plusieurs fois dans votre programme, vous devez donc utiliser une variable globale pour pouvoir tout mettre à jour en même temps. Mais vous ne voulez pas que quelqu'un d'autre vienne modifier cette variable (peut-être sans se rendre compte de son importance). Dans ce cas, vous n'incluez simplement pas de méthode setter et n'incluez que la méthode 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;
    }
}
Dan Ciborowski - MSFT
la source
10

Il n'y a pas de variable globale en Java

Néanmoins, ce que nous avons est un staticmot-clé et c'est tout ce dont nous avons besoin. Rien n'existe en dehors de la classe en Java. Le staticmot-clé représente une variable de classe qui, contrairement à la variable d'instance, n'a qu'une seule copie et qui transcende toutes les instances de cette classe créée, ce qui signifie que sa valeur peut être modifiée et accessible dans toutes les instances à tout moment.

Si vous avez besoin d'une variable globale accessible au-delà des étendues, alors c'est la variable dont vous avez besoin, mais sa portée n'existe que là où se trouve la classe, et ce sera tout.

Nishant
la source
9

À vrai dire, il n'y a pas de concept de "GLOBAL" dans un programme Java OO

Néanmoins, il y a une certaine vérité derrière votre question, car il y aura des cas où vous voudrez exécuter une méthode à n'importe quelle partie du programme. Par exemple --- méthode random () dans l'application Phrase-O-Matic; c'est une méthode qui devrait être appelable de n'importe où dans un programme.

Donc, pour satisfaire les choses comme ci-dessus "Nous devons avoir des variables et des méthodes de type global"

DÉCLARER UNE VARIABLE GLOBALE.

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

DÉCLARER UNE MÉTHODE COMME GLOBALE .

 1. Mark the method as public static While declaring.

Parce que j'ai déclaré les variables globales et la méthode comme statiques, vous pouvez les appeler où vous le souhaitez en utilisant simplement le code suivant

ClassName.X

REMARQUE : X peut être un nom de méthode ou un nom de variable selon l'exigence et ClassName est le nom de la classe dans laquelle vous les avez déclarés.

JAVA
la source
9

Rien ne devrait être global, à l'exception des constantes.

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

Mettez cela dans votre classe principale. Dans d'autres fichiers .java, utilisez-le via:

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

Assurez-vous que lorsque vous déplacez votre code hors du sol de la salle de découpe et dans la version, vous supprimez ou commentez cette fonctionnalité.

Si vous avez une méthode de travail, comme un randomiseur, je vous suggère de créer un package "Toolbox"! Tous les codeurs devraient en avoir un, puis chaque fois que vous souhaitez l'utiliser dans un .java, importez-le simplement!

David Bowman
la source
5

Il n'existe pas de variable véritablement globale en Java. Chaque variable statique doit appartenir à une classe (comme System.out), mais lorsque vous avez décidé dans quelle classe elle ira, vous pouvez vous y référer de partout chargée par le même chargeur de classe.

Notez que les variables statiques doivent toujours être protégées lors de la mise à jour pour éviter les conditions de concurrence.

Thorbjørn Ravn Andersen
la source
1
java ne fournit pas de variable globale fonctionnellement mais si vous voulez avoir un concept de variable globale, nous pouvons utiliser un mot
Abi
3
public class GlobalClass {
     public static int x = 37;
     public static String s = "aaa";
}

De cette façon, vous pouvez y accéder avec GlobalClass.xetGlobalClass.s

Mark Baijens
la source
2
public class GlobalImpl {   

 public static int global = 5;

}

vous pouvez appeler où vous voulez:

GlobalImpl.global // 5

la source
1

Comme vous le devinez probablement dans la réponse, il n'y a pas de variables globales en Java et la seule chose que vous pouvez faire est de créer une classe avec des membres statiques:

public class Global {
    public static int a;
}

Vous pouvez l'utiliser avec Global.aailleurs. Cependant, si vous utilisez Java 1.5 ou mieux, vous pouvez utiliser la import staticmagie pour la faire apparaître encore plus comme une vraie variable globale:

import static test.Global.*;

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

Et voilà !

Maintenant, c'est loin d'être une bonne pratique, comme vous pouvez le voir dans les publicités: ne faites pas cela à la maison

gabuzo
la source
1

Il n'y a pas de variables globales en Java, mais il existe des classes globales avec des champs publics. Vous pouvez utiliser la fonction d'importation statique de java 5 pour la faire ressembler presque à des variables globales.

fastcodejava
la source
1

Généralement la variable globale (je suppose que vous la comparez avec C, Cpp) définit comme public static final

comme

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

Les ENUM sont également utiles dans un tel scénario:

Par exemple Calendar.JANUARY )

Jigar Joshi
la source
Une variable globale doit-elle être définitive? Pourquoi?
Konerak
1
"final" signifie "constant", c'est donc une constante globale.
duffymo
1
non, c'est ce que signifie la variable globale si vous souhaitez partager cette variable et modifier également les données, puis supprimez-les, finalmais cela dépend certainement de la façon dont vous souhaitez partager, où vous utilisez et tout,
Jigar Joshi
Quel est le type de CODEdans cet exemple? Où est-il défini?
M_M
Notez également: CODE est dans toutes les majuscules, comme sa notation java commune pour utiliser toutes les majuscules pour les variables que vous déclarez définitives, et n'ont pas l'intention de changer au cours d'un programme.
Dan Ciborowski - MSFT
1

Création d'un fichier indépendant, par exemple. Example.java pour utiliser la 1ère solution, c'est très bien. Vous pouvez le faire également dans l'application, par exemple si les variables globales sont spéciales pour votre application actuelle, etc.:

Créez une classe au début et déclarez vos variables dedans:

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

Vous pouvez ensuite accéder à ces variables - en les utilisant comme «Globals.month_number», etc. - à partir de partout dans votre application.

Apostolos
la source
Au lieu de voter vers le bas, pouvez-vous me dire ce qui ne va pas avec cette solution? Je l'utilise sur une base constante et c'est la plus pratique. Je ne peux donc pas faire autrement que de considérer ce downvote comme une chose personnelle ou simplement par une personne stupide.
Apostolos
1

Si vous devez mettre à jour la propriété globale, une simple classe wrapper getter / setter peut être utilisée comme variable globale. Un exemple typique est illustré ci-dessous.

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());
    }
}
Turkdogan Tasdelen
la source
0

Selon le concept, les variables globales, également connues sous le nom de variable d'instance, sont les variables au niveau de la classe, c'est-à-dire qu'elles sont définies à l'intérieur d'une classe mais à l'extérieur des méthodes. Afin de les rendre complètement disponibles et de les utiliser, fournissez directement le mot-clé statique. Donc, si j'écris un programme pour une opération arithmétique simple et qu'il nécessite une paire de nombres, deux variables d'instance sont définies comme telles:

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

De plus, l'utilisation de mots clés statiques avant les variables d'instance nous permet de ne pas spécifier encore et encore les types de données pour les mêmes variables. Écrivez simplement la variable directement.

BIJAY
la source
1
Il n'y a pas de variables globales en Java; elles ne sont pas également appelées variables d'instance; les définir comme static«ne les rend pas entièrement disponibles». Le premier paragraphe est un non-sens. L'exemple est une mauvaise pratique.
Marquis de Lorne
0

En général, Java n'a pas de variables globales. À l'exception des variables locales, toutes les variables relèvent de la portée de n'importe quelle classe définie dans le programme. Nous pouvons avoir des variables statiques pour avoir la portée des variables globales.

débutant
la source
0

sans staticcela, c'est possible aussi:

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
*/
zemiak
la source
0

La programmation orientée objet est construite avec la compréhension que la portée des variables est étroitement exclusive à l'objet de classe qui encapsule ces variables.

Le problème avec la création de "variables globales" est que ce n'est pas la norme de l'industrie pour Java. Ce n'est pas la norme de l'industrie car il permet à plusieurs classes de manipuler des données asynchronisées, si vous exécutez une application multi-thread, cela devient un peu plus compliqué et dangereux en termes de sécurité des threads. Il existe plusieurs autres raisons pour lesquelles l'utilisation de variables globales est inefficace, mais si vous voulez éviter cela, je vous suggère de recourir à la programmation orientée aspect .

La programmation orientée aspect résout ce problème en mettant la classe parent en charge de la portée via quelque chose appelé "conseils", ce qui ajoute un comportement supplémentaire au code sans le modifier réellement. Il propose des solutions aux préoccupations transversales ou à l'utilisation globale des variables.

Spring est un cadre Java qui utilise AOP, et bien qu'il soit traditionnellement utilisé pour les applications Web, l'application principale peut être utilisée universellement dans tout le cadre Java (8.0 inclus). Cela pourrait être une direction que vous souhaitez explorer davantage.

moutonsiiHD
la source
0

Comprendre le problème

Je considère la qualification de variable globale comme une variable qui peut être consultée et modifiée n'importe où dans le code sans se soucier de l'appel statique / d'instance ni passer de référence d'une classe à une autre.

Habituellement, si vous avez 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;
    }
}

et souhaitez accéder et mettre myvarà jour dans une classe B,

public class B{

    private A a;

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

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

vous devrez avoir une référence d'une instance de la classe A et mettre à jour la valeur dans la classe B comme ceci:

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

Solution

Donc, ma solution à cela (même si je ne suis pas sûr que ce soit une bonne pratique) est d'utiliser 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;
    }
}

Vous pouvez désormais obtenir l'instance unique globale n'importe où avec:

Globals globals = Globals.getInstance();
// and read and write to myVar with the getter and setter like 
int myVar = globals.getMyVar();
global.setMyVar(3);
Mendrika Sandratra
la source
-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
Matt Thomas
la source
2
Qu'est-ce que cette réponse ajoute que les autres réponses ne font pas? Je ne vois aucune "nouvelle" valeur dans cette réponse.
EWit
-2

Pour définir la variable globale, vous pouvez utiliser un mot-clé statique

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

vous pouvez maintenant accéder à a et b de n'importe où en appelant

Tools.a;
Tools.b;

Vous avez raison ... spécialement dans J2ME ... Vous pouvez éviter NullPointerException en mettant à l'intérieur de votre constructeur MidLet (initialisation proggy) cette ligne de code:

new Tools();

Cela garantit que les outils seront alloués avant toute instruction qui l'utilise.

C'est tout!

user2616742
la source
3
Hum ... Désolé, mais qu'est-ce que cet ajout qui n'est pas déjà couvert par les réponses existantes?
Mysticial
Vous avez peut-être raison ... mais cette réponse explique des choses comme l'allocation de mémoire.
user2616742
Il n'y a pas de classes statiques de haut niveau en java
Andremoniy