Глобальні змінні в Java


217

Як ви визначаєте глобальні змінні в Java?


20
Чи можете ви сказати нам, чому ви хочете визначити глобальні змінні в Java?
Адам Пейнтер

44
Для доступу до змінної поза класом
травня

5
Можливо, вам слід відредагувати своє запитання, щоб включити якийсь зразок коду, що точно ілюструє те, що ви хочете. Це допоможе нам рекомендувати найкраще рішення.
Адам Пейнтер

7
@Adam: Я повинен мати можливість змінити значення змінної в одному класі з іншого класу.
травня

2
Ви цього не робите. У Java немає глобальних змінних.
Маркіз Лорн

Відповіді:


261

Для визначення глобальної змінної можна скористатися статичним ключовим словом

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

тепер ви можете отримати доступ до a і b з будь-якого місця, зателефонувавши

Example.a;

Example.b;

6
"Global" - це назва класу.
Ієронім

12
Будьте обережні, роблячи це - коли глобальний клас вивантажується, змінні стануть невизначеними. Якщо ви продаєте свою програму, це станеться рано чи пізно, і ви продовжуєте шукати помилки скрізь, але не там ....
user387184

10
staticКлючове слово робить змінні глобально доступною, при завантаженому їх клас.
sjas

22
Про розвантаження класу: якщо є який-небудь сильний посилальний ланцюг від будь-якого кореня GC до екземпляра Global або його дочірніх даних, або будь-яка посилання часу компіляції з завантаженого і не завантажуваного класу до Global, то об'єкт класу відносно Global сильно доступний, і, отже, такий є ClassLoader, який завантажив Global; що робить неможливим вивантаження глобального (оскільки вивантаження класу може відбутися лише після того, як GC повністю видалить будь-які чіткі посилання на ClassLoader, який завантажив даний клас). Якщо у вас взагалі немає посилань, як може бути проблема розвантаження ???
Бруно Рейс,

4
@Abi Я б запропонував перейменувати свій клас Globalна щось інше ( TestClass?), Щоб не створювати людям враження, що існує таке поняття, як Globalключове слово Java. Краще безпечніше, ніж вибачте :)
Nicolas Rinaudo

53

Ви цього не робите. Це за дизайном. Ви не повинні робити цього, навіть якщо могли.

За словами, ви можете створити набір публічних статичних членів у класі на ім'я Globals.

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

але ти справді не повинен :). Серйозно .. не робіть цього.


6
Тоді який кращий підхід, що я можу оголосити константи, щоб усі методи класу мали доступ до них?
Елстон

6
Повідомлення такого характеру є причиною того, що новачки розробляють глобальну змінну фобію, і тоді ми бачимо, що всілякі жахливі методи розробляються, щоб обходити табу глобальної змінної, але досягають такого ж ефекту.
Євгеній Сергєєв

39
Проголосуйте за те, щоб сказати: "не робіть цього". не пояснюючи і не посилаючись на пояснення того, чому.
Джефф Маккун

4
@JeffMcCune: щоб зробити вашу заяву яснішою, "не робіть цього" - це насправді фігня. Робіть це, коли це корисно. Наприклад, мені доведеться налагоджувати код за допомогою IAbpositeLoggerBullshit і, звичайно, System.err не працює в цьому переобладнаному середовищі. Я не можу засмітити свій код, проходячи навколо лайки між сотнями непотрібних класів адаптерів.
Jo So

6
Я збираюся це зробити.
Плаваюча Сонячна

40

Ще один спосіб - створити такий інтерфейс:

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

Будь-який клас, який потребує їх використання, повинен реалізувати лише інтерфейс:

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

Мені цікаво, чому ця відповідь (до моєї) не має голосів. Чи не дає вона розумної альтернативної відповіді на ту, яку надають усі інші відповіді?
M_M

12
Ефективна Java Джошуа Блоха, Глава 4: Класи та інтерфейси, Пункт 19: Використовуйте інтерфейси лише для визначення типів "Постійна модель інтерфейсу - це погане використання інтерфейсів". Цю книгу варто прочитати! :)
MariuszS

1
Крім того, з JDK 1.5+ ви можете використовувати статичний імпорт для своїх глобальних змінних, реалізація не потрібна.
MariuszS

9
.... Правильно, це насправді нічого не пояснює, це просто говорить про те, що в якійсь книзі було сказано, що це погано.
linkhyrule5

14
Ось цитата для вас. Oracle каже: "Для того, щоб обійти це, люди іноді ставлять статичні члени в інтерфейс і успадковують цей інтерфейс. Це погана ідея. Насправді, це така погана ідея, що існує назва: Постійний інтерфейс Antipattern (див. Ефективний пункт Пункт 17). Проблема полягає в тому, що використання статичних членів іншого класу класом є простою деталлю реалізації. Коли клас реалізує інтерфейс, він стає частиною загальнодоступного API API. Деталі впровадження не повинні просочуватися загальнодоступні API ».
Джолта

23

Вам краще використовувати ін'єкцію залежності:

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

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

5
Щоправда, хоча я думаю, що ваше використання "Глобалів" дещо плутає речі :-). Щось на зразок "Параметри" було б більш придатним, оскільки це не обов'язково глобально.
Марк Петерс

11

Дуже багато хороших відповідей, але я хочу навести цей приклад, оскільки це вважається більш правильним способом доступу до змінних класу іншим класом: за допомогою getters та setters.

Причина, чому ви використовуєте геттери та сетери таким чином, а не просто оприлюднювати змінну, полягає в наступному. Скажімо, ваш var стане глобальним параметром, який ви НІКОЛИ не бажаєте, щоб хтось міняв під час виконання вашої програми (у випадку, коли ви розробляєте код з командою), на зразок URL-адреси веб-сайту. Теоретично це може змінитися і може використовуватися багато разів у вашій програмі, тому ви хочете використовувати глобальний var, щоб мати можливість оновити все це відразу. Але ви не хочете, щоб хтось інший заходив і міняв цю вару (можливо, не усвідомлюючи, наскільки це важливо). У такому випадку ви просто не включаєте метод setter, а включаєте лише метод 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

У Java немає глобальної змінної

Однак у нас є staticключове слово, і це все, що нам потрібно. На Java нічого не існує поза класом. ThestaticКлючове слово являє собою змінний клас , який, в відміну від змінного екземпляра, має тільки одну копії і яка виходить за межі у всіх примірниках цього класу , створених, а це значить , що його значення може бути змінено і доступом в усіх випадках , в будь-який момент.

Якщо вам потрібна глобальна змінна, до якої можна отримати доступ понад рамки, то ця змінна вам потрібна, але її область існує лише там, де є клас, і це буде все.


9

По-справжньому, в програмі java OO не існує поняття "GLOBAL"

Тим не менш, за вашим запитанням є якась правда, оскільки в деяких випадках програми ви хочете запустити метод. Наприклад --- метод random () у додатку Phrase-O-Matic; це метод, який слід викликати з будь-якої програми програми.

Отже, щоб задовольнити такі речі, як Вище "Нам потрібно мати глобальні змінні та методи"

ДЕКЛАРАЦІЮВАТИ ВАРІАНТУ ЯК ГЛОБАЛЬНО.

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

ДЕКЛАСУВАТИ МЕТОД ЯК ГЛОБАЛЬНИЙ .

 1. Mark the method as public static While declaring.

Оскільки я оголосив глобальні змінні та метод статичними, ви можете викликати їх куди завгодно, просто за допомогою наступного коду

ClassName.X

ПРИМІТКА : X може бути ім'ям методу або ім'ям змінної відповідно до вимоги, а ClassName - іменем класу, в якому ви їх оголосили.


9

Ніщо не повинно бути глобальним, крім констант.

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

Покладіть це в свій основний клас. В інших .java-файлах використовуйте його через:

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

Переконайтеся, що коли ви переміщуєте код з підлоги різальної кімнати, а у звільненні ви видаляєте та коментуєте цю функціональність.

Якщо у вас є метод робочого коня, як-от рандомізатор, я пропоную створити пакет "Toolbox"! Усі кодери повинні мати його, тоді, коли ви хочете використовувати його в .java, просто імпортуйте його!


5

По-справжньому глобальної змінної у Java не існує. Кожна статична змінна повинна належати до якогось класу (наприклад, System.out), але коли ви вирішили, до якого класу він буде входити, ви можете посилатися на нього звідусіль, завантаженого одним і тим же завантажувачем.

Зауважте, що статичні змінні завжди повинні бути захищені під час оновлення, щоб уникнути перегонів.


1
java не надає глобальну змінну функціонально, але якщо ви хочете мати глобальну концепцію змінної, ми можемо скористатися статичним ключовим словом
Abi

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

Таким чином ви можете отримати доступ до них за допомогою GlobalClass.xтаGlobalClass.s


2
public class GlobalImpl {   

 public static int global = 5;

}

Ви можете зателефонувати куди завгодно:

GlobalImpl.global // 5

1

Як ви, напевно, здогадуєтесь з відповіді, у Java немає глобальних змінних, і єдине, що ви можете зробити, це створити клас зі статичними членами:

public class Global {
    public static int a;
}

Ви можете використовувати його з Global.aіншими місцями. Однак якщо ви використовуєте Java 1.5 або вище, ви можете використовувати import staticмагію, щоб вона виглядала ще більше як реальна глобальна змінна:

import static test.Global.*;

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

І вуаля !

Зараз це далеко не найкраща практика, так що ви можете бачити в рекламних роликах: не робіть цього вдома


1

У Java немає глобальних змінних, але є глобальні класи з публічними полями. Ви можете використовувати статичну функцію імпорту java 5, щоб вона виглядала майже як глобальні змінні.


1

Взагалі глобальну змінну (я припускаю, ви порівнюєте її з C, Cpp) визначають як public static final

подібно до

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

ENUM також корисні в такому сценарії:

Наприклад Calendar.JANUARY)


Чи глобальна змінна повинна бути остаточною? Чому?
Конерак

1
"остаточний" означає "константа", тому це глобальна константа.
duffymo

1
ні, ось що означає глобальна змінна, якщо ви хочете поділитися цією змінною та змінити дані, а потім просто видаліть, finalале це, безумовно, залежить від того, як ви хочете поділитися, де ви використовуєте і все,
Jigar Joshi

Який тип CODEу цьому прикладі? Де це визначено?
M_M

Також зауважте: CODE є у всіх обмеженнях, оскільки його загальна нотація Java використовує всі обмеження для змінних, які ви оголошуєте як остаточні та не збираєтесь змінювати протягом програми.
Dan Ciborowski - MSFT

1

Створення незалежного файлу, наприклад. Example.java для використання 1-го рішення, просто чудово. Це можна зробити і в додатку, якщо, наприклад, глобальні змінні є спеціальними для вашої поточної програми тощо:

Створіть клас на початку та декларуйте там свої змінні:

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

Потім ви можете отримати доступ до цих змінних - використовуючи їх як "Globals.month_number" тощо. - з будь-якого місця у вашій програмі.


Замість того, щоб схилитись, скажіть, будь ласка, що не так у цьому рішенні? Я використовую його постійно і це найзручніше. Тож я не можу зробити інакше, якщо розглядати цей потвор як особисту річ або просто зроблену дурною людиною.
Апостолос

1

Якщо вам потрібно оновити глобальну властивість, простий клас getter / setter обгортки може використовуватися як глобальна змінна. Типовий приклад показаний нижче.

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

За принципом, глобальні змінні, також відомі як змінна інстанція, є змінними рівня класу, тобто вони визначаються всередині класу, але поза методами. Для того, щоб зробити їх доступними повністю та використовувати їх, надайте статичне ключове слово. Отже, якщо я пишу програму для простої арифметичної роботи, і їй потрібна пара чисел, то дві змінні екземпляра визначаються як такі:

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

Крім того, використання статичного ключового слова до змінних екземплярів дозволяє нам не вказувати типи даних для одних і тих же змінних знову і знову. Просто запишіть змінну безпосередньо.


1
У Java немає глобальних змінних; вони також не відомі як змінні екземпляри; визначення їх як static"не робить їх доступними повністю". Перший абзац - це нісенітниця. Приклад - погана практика.
Маркіз Лорн

0

Загалом, у Java немає глобальних змінних. Крім локальних змінних, всі змінні підпадають під область будь-якого класу, визначеного в програмі. Ми можемо мати статичні змінні, щоб мати область глобальних змінних.


0

без staticцього теж неможливо:

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

Об'єктно-орієнтоване програмування побудоване з розумінням того, що область змінних тісно виключає об'єкт класу, який інкапсулює ці змінні.

Проблема створення "глобальних змінних" полягає в тому, що це не галузевий стандарт для Java. Це не галузевий стандарт, оскільки він дозволяє декільком класам маніпулювати асинхронізованими даними, якщо ви використовуєте багатопотокове додаток, це стає трохи складніше і небезпечніше з точки зору безпеки потоку. Існують різні інші причини, чому використання глобальних змінних малоефективне, але якщо ви хочете цього уникнути, я пропоную скористатися програмою, орієнтованою на аспекти .

Аспект-орієнтоване програмування знімає цю проблему, ставлячи батьківський клас відповідаючи за область дії через щось, що називається "поради", що додає додатковій поведінці коду, не змінюючи його фактично. Він пропонує рішення наскрізних проблем або глобального використання змінних.

Spring - це програма Java, яка використовує AOP, і хоча вона традиційно використовується для веб-додатків, основний додаток може використовуватися універсально у всій системі Java (включено 8.0). Це може бути напрямок, який ви хочете вивчити більше.


0

Розуміння проблеми

Я розглядаю кваліфікацію глобальної змінної як змінну, до якої можна отримати доступ і змінити будь-де в коді, не піклуючись про статичний / виклик екземпляра або передачу будь-якої посилання з одного класу в інший.

Зазвичай, якщо у вас клас А

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

і хочете отримати доступ та оновити myvarв класі B,

public class B{

    private A a;

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

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

вам потрібно мати посилання на екземпляр класу A і оновити значення в класі 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

Рішення

Тож моє рішення цього питання (навіть якщо я не впевнений, чи це хороша практика) полягає у використанні синглтона:


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

Тепер ви можете отримати унікальний глобальний екземпляр будь-де за допомогою:

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
Що ця відповідь додає, що інші відповіді не відповідають? У цій відповіді я не бачу жодного "нового" значення.
EWit

-2

Для визначення глобальної змінної можна скористатися статичним ключовим словом

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

тепер ви можете отримати доступ до a і b з будь-якого місця, зателефонувавши

Tools.a;
Tools.b;

Yoy правильно ... спеціально в J2ME ... Ви можете уникнути NullPointerException, помістивши всередину свого конструктора MidLet (ініціалізація прогресії) цей рядок коду:

new Tools();

Це гарантує, що Інструменти будуть виділені перед будь-якою інструкцією, яка ним користується.

Це воно!


3
Гм ... Вибачте, але що це додає, що вже не охоплені наявними відповідями?
Містичний

Можливо, ти маєш рацію .. але ця відповідь пояснює такі речі, як розподіл пам'яті.
користувач2616742

Немає статичних класів вищого рівня в java
Андремоній
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.