Zmienne globalne w Javie


217

Jak definiujesz zmienne globalne w Javie?


20
Czy możesz nam powiedzieć, dlaczego chcesz zdefiniować zmienne globalne w Javie?
Adam Paynter,

44
Aby uzyskać dostęp do zmiennej spoza klasy
aTJ

5
Być może powinieneś edytować swoje pytanie, aby uwzględnić przykładowy kod dokładnie ilustrujący to, czego chcesz. Pomoże nam to polecić najlepsze rozwiązanie.
Adam Paynter,

7
@Adam: Powinienem być w stanie zmienić wartość zmiennej w jednej klasie z innej klasy.
aTJ

2
Ty nie. W Javie nie ma zmiennych globalnych.
Markiz Lorne

Odpowiedzi:


261

Aby zdefiniować zmienną globalną, możesz użyć statycznego słowa kluczowego

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

teraz możesz uzyskać dostęp do aib z dowolnego miejsca, dzwoniąc

Example.a;

Example.b;

6
„Globalny” to nazwa klasy.
Jerome,

12
Bądź przy tym ostrożny - kiedy klasa Global zostanie rozładowana, zmienne będą niezdefiniowane. Jeśli sprzedasz swoją aplikację, stanie się to wcześniej czy później i nadal będziesz szukać błędów wszędzie, ale nie tam ....
user387184

10
Słowo statickluczowe sprawia, że ​​zmienne są globalnie dostępne, podczas gdy ich klasa jest ładowana.
sjas

22
O rozładowaniu klasy: jeśli istnieje jakikolwiek silny łańcuch referencyjny z dowolnego katalogu głównego GC do instancji Global lub jego elementów podrzędnych, lub jakiekolwiek odniesienie w czasie kompilacji z załadowanej i niemożliwej do rozładowania klasy do Global, wówczas obiekt Class względem Global jest silnie osiągalny, a zatem i ClassLoader, który załadował Global; co uniemożliwia rozładowanie Globalnego (ponieważ rozładowanie klasy może nastąpić dopiero po całkowitym usunięciu przez GC jakiegokolwiek silnego odwołania do ClassLoadera, który załadował daną klasę). Jeśli nie masz żadnych referencji, w jaki sposób rozładowanie może być problemem?
Bruno Reis,

4
@Abi Sugeruję, abyś zmienił nazwę swojej klasy Globalna inną ( TestClass?), Aby nie sprawiać wrażenia, że ​​istnieje coś takiego jak Globalsłowo kluczowe Java. Lepiej bezpieczniej niż przykro :)
Nicolas Rinaudo

53

Ty nie. To z założenia. Nie powinieneś tego robić, nawet jeśli możesz.

Biorąc to pod uwagę, możesz stworzyć zestaw publicznych statycznych członków w klasie o nazwie Globals.

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

ale naprawdę nie powinieneś :). Poważnie ... nie rób tego.


6
Więc jakie jest lepsze podejście, że mogę zadeklarować stałe, aby wszystkie metody klas miały do ​​nich dostęp?
Alston,

6
Posty tego rodzaju są powodem, dla którego nowicjusze rozwijają globalną fobię zmiennych, a następnie widzimy różnego rodzaju rażące techniki mające na celu obejście tabu zmiennych globalnych, ale osiągające ten sam efekt.
Evgeni Sergeev

39
Głosuj w dół za powiedzenie „nie rób tego”. bez wyjaśniania lub odwoływania się do wyjaśnienia dlaczego.
Jeff McCune,

4
@JeffMcCune: aby wyjaśnić twoje oświadczenie, „nie rób tego” to bzdury. Zrób to, gdy jest to przydatne. Na przykład muszę debugować kod za pomocą IAbstractLoggerBullshit i oczywiście System.err nie działa w tym nadinżynieryjnym środowisku. Nie mogę zaśmiecać mojego kodu przechodzącego przez bzdury rejestratora między setkami bezużytecznych klas adapterów.
Jo So

6
Zrobię to.
Floating Sunfish

40

Innym sposobem jest utworzenie takiego interfejsu:

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

Każda klasa, która musi z nich korzystać, musi jedynie zaimplementować interfejs:

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

Zastanawiam się, dlaczego ta odpowiedź (przed moją) nie ma głosów up. Czy nie stanowi rozsądnej alternatywy dla odpowiedzi udzielonej przez wszystkie pozostałe odpowiedzi?
M_M,

12
Efektywna Java autorstwa Joshua Blocha, Rozdział 4: Klasy i interfejsy, pozycja 19: Używaj interfejsów tylko do definiowania typów „Stały wzorzec interfejsu to słabe użycie interfejsów”. Ta książka jest warta przeczytania! :)
MariuszS

1
Dodatkowo z JDK 1.5+ możesz użyć importu statycznego do zmiennych globalnych, implementacja nie jest wymagana.
MariuszS

9
.... Tak, to właściwie nic nie wyjaśnia, tylko mówi, że jakaś książka powiedziała, że ​​była zła.
linkhyrule5

14
Oto oferta dla ciebie. Oracle mówi: „Aby obejść ten problem, ludzie czasami umieszczają statyczne elementy w interfejsie i dziedziczą po tym interfejsie. To zły pomysł. W rzeczywistości jest to tak zły pomysł, że istnieje na to nazwa: Constant Interface Antipattern (patrz Efektywna Java pozycja 17). Problem polega na tym, że użycie statycznych elementów innej klasy jest jedynie szczegółem implementacji. Kiedy klasa implementuje interfejs, staje się częścią publicznego interfejsu API klasy. Szczegóły implementacji nie powinny wyciekać do publiczne interfejsy API ”.
Jolta,

23

Lepiej jest użyć wstrzykiwania zależności:

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

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

5
To prawda, choć myślę, że twoje użycie „Globali” nieco myli rzeczy :-). Coś w rodzaju „parametrów” byłoby bardziej odpowiednie, ponieważ niekoniecznie jest globalne.
Mark Peters,

11

Wiele dobrych odpowiedzi, ale chcę podać ten przykład, ponieważ jest on uważany za bardziej właściwy sposób uzyskiwania dostępu do zmiennych klasy przez inną klasę: za pomocą metod pobierających i ustawiających.

Powód, dla którego używasz getterów i seterów w ten sposób, zamiast po prostu upubliczniać zmienną, jest następujący. Powiedzmy, że twój var będzie globalnym parametrem, którego NIGDY nie chcesz, aby ktoś zmienił podczas wykonywania twojego programu (w przypadku, gdy tworzysz kod z zespołem), coś w rodzaju adresu URL strony internetowej. Teoretycznie może się to zmienić i może być używane wiele razy w twoim programie, więc chcesz użyć globalnego var, aby móc zaktualizować wszystko naraz. Ale nie chcesz, aby ktoś inny wszedł i zmienił ten var (być może nie zdając sobie sprawy z tego, jak ważne jest). W takim przypadku po prostu nie podajesz metody ustawiającej, a jedynie metodę gettera.

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

W Javie nie ma globalnej zmiennej

Niemniej jednak mamy staticsłowo kluczowe i to wszystko, czego potrzebujemy. W Javie nie ma nic poza klasą. Thestatic kluczowe reprezentuje zmienną klasy, która w przeciwieństwie do zmiennej instancji, ma tylko jedną kopię i która przekracza wszystkie instancje utworzonej klasy, co oznacza, że ​​jej wartość można zmienić i uzyskać do niej dostęp we wszystkich instancjach w dowolnym momencie.

Jeśli potrzebujesz zmiennej globalnej, do której można uzyskać dostęp poza zasięgiem, jest to zmienna, której potrzebujesz, ale jej zakres istnieje tylko tam, gdzie jest klasa, i to wszystko.


9

Prawdę mówiąc, nie ma pojęcia „GLOBALNY” w programie Java OO

Niemniej jednak za twoim pytaniem kryje się trochę prawdy, ponieważ będą przypadki, w których będziesz chciał uruchomić metodę w dowolnej części programu. Na przykład --- metoda random () w aplikacji Phrase-O-Matic; jest to metoda, którą można wywoływać z dowolnego programu.

Aby więc spełnić powyższe wymagania „Musimy mieć globalne zmienne i metody”

OŚWIADCZENIE O ZMIENNEJ JAKO GLOBALNEJ.

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

OŚWIADCZENIE METODY JAKO GLOBALNEJ .

 1. Mark the method as public static While declaring.

Ponieważ zadeklarowałem zmienne globalne i metodę jako statyczne, możesz je wywoływać w dowolnym miejscu, po prostu za pomocą następującego kodu

ClassName.X

UWAGA : X może być nazwą metody lub nazwą zmiennej zgodnie z wymaganiami, a ClassName to nazwa klasy, w której je zadeklarowano.


9

Nic nie powinno być globalne, z wyjątkiem stałych.

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

Umieść to w swojej głównej klasie. W innych plikach .java użyj go poprzez:

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

Upewnij się, że po przeniesieniu kodu z podłogi krojowni i wydaniu usuniesz lub skomentujesz tę funkcję.

Jeśli masz metodę konia pociągowego, taką jak randomizator, sugeruję utworzenie pakietu „Toolbox”! Wszyscy koderzy powinni go mieć, a następnie za każdym razem, gdy chcesz go użyć w .java, po prostu zaimportuj go!


5

W Javie nie ma czegoś takiego jak prawdziwie globalna zmienna. Każda zmienna statyczna musi należeć do jakiejś klasy (np. System.out), ale kiedy zdecydujesz, do której klasy ona wejdzie, możesz odwoływać się do niej z dowolnego miejsca ładowanego przez ten sam moduł ładujący klasy.

Należy pamiętać, że zmienne statyczne należy zawsze chronić podczas aktualizacji, aby uniknąć warunków wyścigu.


1
java nie zapewnia funkcjonalnie zmiennej globalnej, ale jeśli chcesz mieć pojęcie zmiennej globalnej, możemy skorzystać ze statycznego słowa kluczowego
Abi

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

W ten sposób możesz uzyskać do nich dostęp za pomocą GlobalClass.xiGlobalClass.s


2
public class GlobalImpl {   

 public static int global = 5;

}

możesz zadzwonić gdziekolwiek chcesz:

GlobalImpl.global // 5

1

Jak zapewne zgadniesz z odpowiedzi, w Javie nie ma zmiennych globalnych, a jedyne, co możesz zrobić, to stworzyć klasę z elementami statycznymi:

public class Global {
    public static int a;
}

Możesz go używać z Global.ainnym miejscem. Jeśli jednak używasz języka Java 1.5 lub nowszego, możesz użyć import staticmagii, aby wyglądała jeszcze bardziej jak prawdziwa zmienna globalna:

import static test.Global.*;

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

I voila !

Teraz nie jest to najlepsza praktyka, więc jak widać w reklamach: nie rób tego w domu


1

W Javie nie ma globalnych zmiennych, ale istnieją globalne klasy z polami publicznymi. Możesz użyć funkcji importowania statycznego w java 5, aby wyglądała prawie jak zmienne globalne.


1

Ogólnie Zmienna globalna (zakładam, że porównujesz ją z C, Cpp) zdefiniuj jako public static final

lubić

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

ENUM są również przydatne w takim scenariuszu:

Na przykład Calendar.JANUARY)


Czy zmienna globalna musi być ostateczna? Czemu?
Konerak,

1
„końcowy” oznacza „stały”, więc jest to stała globalna.
duffymo,

1
nie, to właśnie oznacza zmienna globalna, jeśli chcesz udostępnić tę zmienną i zmienić dane, a następnie po prostu usuń, finalale na pewno zależy to od tego, jak chcesz udostępnić, gdzie używasz i wszystko,
Jigar Joshi

Jaki jest typ CODEtego przykładu? Gdzie to jest zdefiniowane?
M_M,

Zauważ też: KOD jest wielkimi literami, ponieważ jego powszechną notacją java jest używanie wszystkich wielkich liter dla zmiennych, które zadeklarowałeś jako końcowe i nie zamierzają się zmieniać w trakcie programu.
Dan Ciborowski - MSFT

1

Tworzenie niezależnego pliku, np. Przykład.java, aby użyć pierwszego rozwiązania, jest w porządku. Możesz to zrobić również w aplikacji, jeśli np. Zmienne globalne są specjalne dla bieżącej aplikacji itp .:

Utwórz klasę na początku i zadeklaruj tam swoje zmienne:

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

Następnie możesz uzyskać dostęp do tych zmiennych - używając ich jako „Globals.month_number” itp. - z dowolnego miejsca w aplikacji.


Czy zamiast głosowania w dół, możesz mi powiedzieć, co jest nie tak z tym rozwiązaniem? Używam go na stałe i jest to najwygodniejszy. Nie mogę więc zrobić inaczej niż uznanie tego głosowania za coś osobistego lub po prostu zrobionego przez głupią osobę.
Apostolos

1

Jeśli musisz zaktualizować właściwość globalną, jako zmienną globalną można użyć prostej klasy opakowania gettera / settera. Typowy przykład pokazano poniżej.

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

Zgodnie z tym pojęciem zmienne globalne, znane również jako zmienne instancji, są zmiennymi na poziomie klasy, tzn. Są zdefiniowane wewnątrz klasy, ale poza metodami. Aby udostępnić je całkowicie i użyć bezpośrednio, wpisz słowo kluczowe static. Więc jeśli piszę program do prostej operacji arytmetycznej i wymaga on pary liczb, wówczas dwie zmienne instancji są zdefiniowane jako takie:

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

Ponadto użycie statycznego słowa kluczowego przed zmiennymi instancji pozwala nam nie określać typów danych dla tych samych zmiennych raz za razem. Po prostu napisz zmienną bezpośrednio.


1
W Javie nie ma zmiennych globalnych; nie są również znane jako zmienne instancji; zdefiniowanie ich jako static„nie udostępnia ich całkowicie”. Pierwszy akapit to nonsens. Przykładem jest zła praktyka.
Markiz Lorne

0

Ogólnie rzecz biorąc, Java nie ma żadnych zmiennych globalnych. Poza zmiennymi lokalnymi wszystkie zmienne wchodzą w zakres dowolnej klasy zdefiniowanej w programie. Możemy mieć zmienne statyczne, aby mieć zakres zmiennych globalnych.


0

bez statictego możliwe jest również:

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

Programowanie obiektowe jest zbudowane ze zrozumieniem, że zakres zmiennych jest ściśle wyłączny dla obiektu klasy, który zawiera te zmienne.

Problem z tworzeniem „zmiennych globalnych” polega na tym, że nie jest to standard branżowy dla Javy. Nie jest to standard branżowy, ponieważ pozwala wielu klasom na asynchronizację danych. Jeśli korzystasz z aplikacji wielowątkowej, staje się to nieco bardziej skomplikowane i niebezpieczne pod względem bezpieczeństwa wątków. Istnieje wiele innych powodów, dla których używanie zmiennych globalnych jest nieskuteczne, ale jeśli chcesz tego uniknąć, sugeruję skorzystanie z programowania zorientowanego na aspekty .

Programowanie zorientowane na aspekt eliminuje ten problem, powierzając klasie nadrzędnej kontrolę nad zakresem poprzez coś zwanego „poradami”, co dodaje dodatkowe zachowanie do kodu bez jego modyfikacji. Oferuje rozwiązania przekrojowych problemów lub globalnego wykorzystania zmiennych.

Spring jest platformą Java, która wykorzystuje AOP i chociaż jest tradycyjnie używana w aplikacjach internetowych, podstawowa aplikacja może być używana uniwersalnie w całej platformie Java (w tym 8.0). To może być kierunek, w którym chcesz odkryć więcej.


0

Zrozumienie problemu

Rozważam kwalifikację zmiennej globalnej za zmienną, do której można uzyskać dostęp i zmienić ją w dowolnym miejscu kodu bez dbania o wywołanie statyczne / wystąpienie lub przekazywanie referencji z jednej klasy do drugiej.

Zwykle jeśli masz klasę 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;
    }
}

i chcesz uzyskać dostęp i aktualizować myvarw klasie B,

public class B{

    private A a;

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

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

musisz mieć odwołanie do instancji klasy A i zaktualizować wartość w klasie B w następujący sposób:

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

Rozwiązanie

Więc moim rozwiązaniem tego (nawet jeśli nie jestem pewien, czy to dobra praktyka) jest użycie singletonu:


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

Teraz możesz uzyskać globalną unikalną instancję w dowolnym miejscu dzięki:

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
Co ta odpowiedź dodaje, że inne odpowiedzi nie? W tej odpowiedzi nie widzę żadnej „nowej” wartości.
EWit

-2

Aby zdefiniować zmienną globalną, możesz użyć statycznego słowa kluczowego

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

teraz możesz uzyskać dostęp do aib z dowolnego miejsca, dzwoniąc

Tools.a;
Tools.b;

Racja ma rację ... szczególnie w J2ME ... Możesz uniknąć NullPointerException, umieszczając w swoim konstruktorze MidLet (inicjacja progresywna) następujący wiersz kodu:

new Tools();

Zapewnia to przydzielenie Narzędzi przed każdą instrukcją, która ich używa.

Otóż ​​to!


3
Um ... Przepraszam, ale co to dodaje, że nie jest już uwzględnione w istniejących odpowiedziach?
Mysticial

Może masz rację ... ale ta odpowiedź wyjaśnia rzeczy takie jak przydział pamięci.
user2616742,

W java nie ma statycznych klas najwyższego poziomu
Andremoniy,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.