Globale Variablen in Java

217

Wie definieren Sie globale Variablen in Java?

aTJ
quelle
20
Können Sie uns sagen, warum Sie globale Variablen in Java definieren möchten?
Adam Paynter
44
Zugriff auf die Variable von außerhalb der Klasse
aTJ
5
Vielleicht sollten Sie Ihre Frage so bearbeiten, dass sie einen Beispielcode enthält, der genau zeigt, was Sie wollen. Es würde uns helfen, die beste Lösung zu empfehlen.
Adam Paynter
7
@Adam: Ich sollte in der Lage sein, den Wert einer Variablen in einer Klasse von einer anderen Klasse zu ändern.
aTJ
2
Das tust du nicht. In Java gibt es keine globalen Variablen.
Marquis von Lorne

Antworten:

261

Um eine globale Variable zu definieren, können Sie ein statisches Schlüsselwort verwenden

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

Jetzt können Sie von überall aus auf a und b zugreifen, indem Sie anrufen

Example.a;

Example.b;
Abi
quelle
6
"Global" ist der Name der Klasse.
Jerome
12
Seien Sie dabei vorsichtig - wenn die Global-Klasse entladen wird, sind die Variablen undefiniert null. Wenn Sie Ihre App verkaufen, wird dies früher oder später passieren und Sie suchen überall nach Fehlern, aber nicht dort ....
user387184
10
Das staticSchlüsselwort macht Variablen global zugänglich, während ihre Klasse geladen wird.
Sjas
22
Informationen zum Entladen von Klassen: Wenn eine starke Referenzkette von einem GC-Stamm zu einer Instanz von Global oder seinen untergeordneten Elementen oder eine Referenz zur Kompilierungszeit von einer geladenen und nicht entladbaren Klasse zu Global vorhanden ist, ist das Klassenobjekt relativ zu Global stark erreichbar, und daher auch der ClassLoader, der Global geladen hat; Dies macht das Entladen von Global unmöglich (da das Entladen von Klassen nur erfolgen kann, nachdem der GC alle starken Verweise auf den ClassLoader, der eine bestimmte Klasse geladen hat, vollständig entfernt hat). Wenn Sie überhaupt keine Referenzen haben, wie könnte das Entladen ein Problem sein?
Bruno Reis
4
@Abi Ich würde vorschlagen, dass Sie Ihre Klasse von Globaletwas anderem ( TestClass?) Umbenennen , um den Eindruck zu erwecken, dass es so etwas wie ein GlobalJava-Schlüsselwort gibt. Besser sicher als leid :)
Nicolas Rinaudo
53

Das tust du nicht. Das ist beabsichtigt. Sie sollten es nicht tun, selbst wenn Sie könnten.

Davon abgesehen können Sie eine Reihe von öffentlichen statischen Mitgliedern in einer Klasse namens Globals erstellen.

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

aber du solltest es wirklich nicht :). Ernsthaft ... tu es nicht.

Mihai Toader
quelle
6
Was ist dann der bessere Ansatz, um Konstanten zu deklarieren, damit alle Klassenmethoden darauf zugreifen können?
Alston
6
Beiträge dieser Art sind der Grund, warum Anfänger eine globale variable Phobie entwickeln, und dann sehen wir, dass alle möglichen ungeheuerlichen Techniken entwickelt werden, um das globale variable Tabu zu umgehen, aber den gleichen Effekt erzielen.
Evgeni Sergeev
38
Stimmen Sie ab, wenn Sie sagen: "Tun Sie es nicht." ohne zu erklären oder sich auf eine Erklärung zu beziehen, warum.
Jeff McCune
4
@ JeffMcCune: Um Ihre Aussage klarer zu machen, ist "Tu es nicht" eigentlich Schwachsinn. Mach es, wenn es nützlich ist. Zum Beispiel muss ich meinen Code mit etwas IAbstractLoggerBullshit debuggen und natürlich funktioniert System.err in dieser überentwickelten Umgebung nicht. Ich kann meinen Code nicht wegwerfen, wenn er zwischen Hunderten nutzloser Adapterklassen um den Logger-Mist herumgeht.
Jo So
6
Ich werde es machen.
Floating Sunfish
40

Eine andere Möglichkeit besteht darin, eine Schnittstelle wie die folgende zu erstellen:

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

Jede Klasse, die sie verwenden muss, muss nur die Schnittstelle implementieren:

public class GlobalImpl implements GlobalConstants
{
  public GlobalImpl()
  {
     System.out.println(name);
  }
}
Evan Lévesque
quelle
Ich frage mich, warum diese Antwort (vor meiner) keine Up-Votes hat. Bietet es keine vernünftige alternative Antwort zu der Antwort aller anderen Antworten?
M_M
12
Effektives Java von Joshua Bloch, Kapitel 4: Klassen und Schnittstellen, Punkt 19: Verwenden Sie Schnittstellen nur, um Typen zu definieren. "Das konstante Schnittstellenmuster ist eine schlechte Verwendung von Schnittstellen." Es lohnt sich dieses Buch zu lesen! :)
MariuszS
1
Darüber hinaus können Sie ab JDK 1.5+ den statischen Import für Ihre globalen Variablen verwenden. Eine Implementierung ist nicht erforderlich.
MariuszS
9
.... Richtig, das erklärt eigentlich nichts, das sagt nur, dass ein Buch gesagt hat, es sei schlecht.
Linkhyrule5
14
Hier ist ein Angebot für Sie. Oracle sagt: "Um dies zu umgehen, fügen Leute manchmal statische Elemente in eine Schnittstelle ein und erben von dieser Schnittstelle. Dies ist eine schlechte Idee. Tatsächlich ist es eine so schlechte Idee, dass es einen Namen dafür gibt: das Antipattern der konstanten Schnittstelle (siehe Effektives Java-Element 17). Das Problem besteht darin, dass die Verwendung der statischen Elemente einer anderen Klasse durch eine Klasse lediglich ein Implementierungsdetail ist. Wenn eine Klasse eine Schnittstelle implementiert, wird sie Teil der öffentlichen API der Klasse. Implementierungsdetails sollten nicht verloren gehen öffentliche APIs. "
Jolta
23

Mit der Abhängigkeitsinjektion sind Sie besser dran:

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
quelle
5
Stimmt, obwohl ich denke, dass Ihre Verwendung von "Globals" die Dinge ein wenig verwirrt :-). So etwas wie "Parameter" wäre passender, da es nicht unbedingt global ist.
Mark Peters
11

Viele gute Antworten, aber ich möchte dieses Beispiel geben, da es als der geeignetere Weg angesehen wird, auf Variablen einer Klasse durch eine andere Klasse zuzugreifen: mithilfe von Gettern und Setzern.

Der Grund, warum Sie Getter und Setter auf diese Weise verwenden, anstatt nur die Variable öffentlich zu machen, ist folgender. Nehmen wir an, Ihre Variable wird ein globaler Parameter sein, den NIEMALS während der Ausführung Ihres Programms geändert werden soll (falls Sie Code mit einem Team entwickeln), beispielsweise die URL für eine Website. Theoretisch könnte sich dies ändern und in Ihrem Programm häufig verwendet werden. Sie möchten daher eine globale Variable verwenden, um alles auf einmal aktualisieren zu können. Sie möchten jedoch nicht, dass jemand anderes diese Variable ändert (möglicherweise ohne zu wissen, wie wichtig sie ist). In diesem Fall schließen Sie einfach keine Setter-Methode ein und nur die Getter-Methode.

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
quelle
10

In Java gibt es keine globale Variable

Was wir jedoch haben, ist ein staticSchlüsselwort und das ist alles , was wir brauchen. Außerhalb der Klasse existiert in Java nichts. Dasstatic Schlüsselwort stellt eine Klassenvariable dar, die im Gegensatz zur Instanzvariablen nur eine Kopie hat und über alle Instanzen dieser erstellten Klasse hinausgeht. Dies bedeutet, dass ihr Wert jederzeit geändert und auf alle Instanzen zugegriffen werden kann.

Wenn Sie eine globale Variable benötigen, auf die außerhalb des Bereichs zugegriffen werden kann, ist dies die Variable, die Sie benötigen, deren Bereich jedoch nur dort vorhanden ist, wo sich die Klasse befindet, und das ist alles.

Nishant
quelle
9

Wirklich, es gibt kein Konzept von "GLOBAL" in einem Java OO-Programm

Trotzdem steckt etwas Wahres hinter Ihrer Frage, da es einige Fälle geben wird, in denen Sie eine Methode in einem beliebigen Teil des Programms ausführen möchten. Zum Beispiel --- random () -Methode in der Phrase-O-Matic-App; diese Methode sollte von überall in einem Programm aufgerufen werden können.

Um die oben genannten Dinge zu erfüllen: "Wir brauchen global ähnliche Variablen und Methoden."

Eine Variable als global deklarieren.

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

EINE METHODE ALS GLOBAL ERKLÄREN .

 1. Mark the method as public static While declaring.

Da ich globale Variablen und Methoden als statisch deklariert habe, können Sie sie überall aufrufen, indem Sie einfach den folgenden Code verwenden

ClassName.X

HINWEIS : X kann je nach Anforderung entweder Methodenname oder Variablenname sein, und Klassenname ist der Name der Klasse, in der Sie sie deklariert haben.

JAVA
quelle
9

Nichts sollte global sein, außer Konstanten.

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

Setzen Sie dies in Ihre Hauptklasse ein. Verwenden Sie es in anderen Java-Dateien über:

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

Stellen Sie sicher, dass Sie diese Funktionalität entfernen oder auskommentieren, wenn Sie Ihren Code vom Boden des Schneidraums entfernen und freigeben.

Wenn Sie eine Arbeitspferd-Methode wie einen Randomizer haben, empfehle ich, ein "Toolbox" -Paket zu erstellen! Alle Codierer sollten einen haben. Wenn Sie ihn in einer .java-Datei verwenden möchten, importieren Sie ihn einfach!

David Bowman
quelle
5

In Java gibt es keine wirklich globale Variable. Jede statische Variable muss zu einer Klasse gehören (wie System.out). Wenn Sie jedoch entschieden haben, in welche Klasse sie eingefügt werden soll, können Sie von überall auf sie verweisen, die von demselben Klassenladeprogramm geladen wird.

Beachten Sie, dass statische Variablen beim Aktualisieren immer geschützt werden sollten, um Rennbedingungen zu vermeiden.

Thorbjørn Ravn Andersen
quelle
1
Java bietet keine globale Variable funktional, aber wenn Sie ein globales Variablenkonzept haben möchten, können wir das statische Schlüsselwort verwenden
Abi
3
public class GlobalClass {
     public static int x = 37;
     public static String s = "aaa";
}

Auf diese Weise können Sie mit GlobalClass.xund auf sie zugreifenGlobalClass.s

Mark Baijens
quelle
2
public class GlobalImpl {   

 public static int global = 5;

}

Sie können anrufen, wo immer Sie wollen:

GlobalImpl.global // 5

quelle
1

Wie Sie wahrscheinlich anhand der Antwort erraten haben, gibt es in Java keine globalen Variablen. Sie können lediglich eine Klasse mit statischen Elementen erstellen:

public class Global {
    public static int a;
}

Sie können es mit Global.aanderen verwenden. Wenn Sie jedoch Java 1.5 oder besser verwenden, können Sie die import staticMagie verwenden, um es noch mehr als echte globale Variable erscheinen zu lassen:

import static test.Global.*;

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

Und voilà !

Dies ist alles andere als eine bewährte Methode, wie Sie in den Werbespots sehen können: Tun Sie dies nicht zu Hause

gabuzo
quelle
1

In Java gibt es keine globalen Variablen, aber es gibt globale Klassen mit öffentlichen Feldern. Sie können die statische Importfunktion von Java 5 verwenden, damit es fast wie globale Variablen aussieht.

fastcodejava
quelle
1

Im Allgemeinen wird die globale Variable (ich nehme an, Sie vergleichen sie mit C, Cpp) als definiert public static final

mögen

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

ENUMs sind auch in solchen Szenarien nützlich:

Zum Beispiel Calendar.JANUARY)

Jigar Joshi
quelle
Muss eine globale Variable endgültig sein? Warum?
Konerak
1
"final" bedeutet "konstant", dies ist also eine globale Konstante.
Duffymo
1
Nein, das ist, was globale Variable bedeutet, wenn Sie diese Variable teilen und die Daten auch ändern möchten, dann entfernen finalSie einfach, aber es hängt sicherlich davon ab, wie Sie teilen möchten, wo Sie verwenden und alles,
Jigar Joshi
Was ist die Art CODEin diesem Beispiel? Wo ist es definiert?
M_M
Beachten Sie auch: CODE steht in Großbuchstaben, da es die übliche Java-Notation ist, alle Großbuchstaben für Variablen zu verwenden, die Sie als endgültig deklarieren, und die Sie im Verlauf eines Programms nicht ändern möchten.
Dan Ciborowski - MSFT
1

Erstellen einer unabhängigen Datei, z. Beispiel.java, um die 1. Lösung zu verwenden, ist in Ordnung. Sie können dies auch innerhalb der App tun, wenn z. B. die globalen Variablen speziell für Ihre aktuelle App sind, usw.:

Erstellen Sie am Anfang eine Klasse und deklarieren Sie dort Ihre Variablen:

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

Sie können dann von überall in Ihrer App auf diese Variablen zugreifen - indem Sie sie als 'Globals.month_number' usw. verwenden.

Apostolos
quelle
Können Sie mir bitte sagen, was mit dieser Lösung nicht stimmt, anstatt abzustimmen? Ich benutze es ständig und es ist das bequemste. Ich kann es also nicht anders machen, wenn ich diese Ablehnung als eine persönliche Sache betrachte oder nur von einer dummen Person.
Apostolos
1

Wenn Sie die globale Eigenschaft aktualisieren müssen, kann eine einfache Getter / Setter-Wrapper-Klasse als globale Variable verwendet werden. Ein typisches Beispiel ist unten gezeigt.

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
quelle
0

Nach dem Konzept sind globale Variablen, auch als Instanzvariable bezeichnet, Variablen auf Klassenebene, dh sie werden innerhalb einer Klasse, aber außerhalb von Methoden definiert. Geben Sie das statische Schlüsselwort an, um sie vollständig verfügbar zu machen und direkt zu verwenden. Wenn ich also ein Programm für eine einfache arithmetische Operation schreibe und ein Zahlenpaar benötigt, werden zwei Instanzvariablen als solche definiert:

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

Darüber hinaus können wir durch die Verwendung des statischen Schlüsselworts vor den Instanzvariablen nicht immer wieder Datentypen für dieselben Variablen angeben. Schreiben Sie einfach die Variable direkt.

BIJAY
quelle
1
In Java gibt es keine globalen Variablen. Sie werden nicht auch als Instanzvariablen bezeichnet. Wenn Sie sie so definieren static, dass sie nicht vollständig verfügbar sind. Der erste Absatz ist Unsinn. Beispiel ist schlechte Praxis.
Marquis von Lorne
0

Im Allgemeinen hat Java keine globalen Variablen. Mit Ausnahme lokaler Variablen fallen alle Variablen in den Geltungsbereich einer im Programm definierten Klasse. Wir können statische Variablen haben, um den Umfang globaler Variablen zu haben.

Anfänger
quelle
0

ohne staticdas ist auch möglich:

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
quelle
0

Die objektorientierte Programmierung basiert auf dem Verständnis, dass der Umfang der Variablen eng mit dem Klassenobjekt verbunden ist, das diese Variablen kapselt.

Das Problem beim Erstellen von "globalen Variablen" ist, dass dies kein Industriestandard für Java ist. Dies ist kein Industriestandard, da mehrere Klassen asynchronisierte Daten bearbeiten können. Wenn Sie eine Multithread-Anwendung ausführen, wird dies im Hinblick auf die Thread-Sicherheit etwas komplizierter und gefährlicher. Es gibt verschiedene andere Gründe, warum die Verwendung globaler Variablen unwirksam ist. Wenn Sie dies jedoch vermeiden möchten, empfehlen wir Ihnen, auf aspektorientierte Programmierung zurückzugreifen .

Die aspektorientierte Programmierung hebt dieses Problem auf, indem die übergeordnete Klasse, die für den Bereich verantwortlich ist, durch sogenannte "Ratschläge" versetzt wird, die dem Code zusätzliches Verhalten hinzufügen, ohne ihn tatsächlich zu ändern. Es bietet Lösungen für übergreifende Probleme oder die Verwendung globaler Variablen.

Spring ist ein Java-Framework, das AOP verwendet. Während es traditionell für Webanwendungen verwendet wird, kann die Kernanwendung universell im gesamten Java-Framework verwendet werden (einschließlich 8.0). Dies könnte eine Richtung sein, die Sie genauer erkunden möchten.

SchafiiHD
quelle
0

Das Problem verstehen

Ich betrachte die Qualifizierung einer globalen Variablen als eine Variable, auf die überall im Code zugegriffen und die geändert werden kann, ohne sich um statische / Instanzaufrufe zu kümmern oder einen Verweis von einer Klasse an eine andere zu übergeben.

Normalerweise, wenn Sie Klasse A haben

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

und möchten myvarin einer Klasse B zugreifen und aktualisieren ,

public class B{

    private A a;

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

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

Sie müssen eine Referenz einer Instanz der Klasse A haben und den Wert in der Klasse B wie folgt aktualisieren:

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

Lösung

Meine Lösung für dieses Problem (auch wenn ich nicht sicher bin, ob es eine gute Vorgehensweise ist) besteht darin, einen Singleton zu verwenden:


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

Jetzt können Sie die globale eindeutige Instanz überall abrufen mit:

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
quelle
-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
quelle
2
Was fügt diese Antwort hinzu, was die anderen Antworten nicht tun? Ich kann in dieser Antwort keinen "neuen" Wert sehen.
EWit
-2

Um eine globale Variable zu definieren, können Sie ein statisches Schlüsselwort verwenden

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

Jetzt können Sie von überall aus auf a und b zugreifen, indem Sie anrufen

Tools.a;
Tools.b;

Yoy sind richtig ... speziell in J2ME ... Sie können NullPointerException vermeiden, indem Sie in Ihren MidLet-Konstruktor (proggy Initialisierung) diese Codezeile einfügen:

new Tools();

Dies stellt sicher, dass Tools vor jeder Anweisung zugewiesen werden, die sie verwendet.

Das ist es!

user2616742
quelle
3
Ähm ... Entschuldigung, aber was fügt dies hinzu, das nicht bereits in den vorhandenen Antworten enthalten ist?
Mysticial
Vielleicht haben Sie Recht ... aber diese Antwort erklärt Dinge wie die Speicherzuweisung.
user2616742
Es gibt keine statischen Top-Level-Klassen in Java
Andremoniy