Java中的全局变量


217

您如何在Java中定义全局变量?


20
您能告诉我们为什么要用Java定义全局变量吗?
亚当·佩恩特

44
从班级外部访问变量
aTJ 2011年

5
也许您应该编辑问题,以包含一些示例代码,以精确说明您想要的内容。这将帮助我们推荐最佳解决方案。
亚当·佩恩特

7
@Adam:我应该能够从另一个类中更改一个类中变量的值。
2011年

2
你不知道 Java中没有全局变量。
罗恩侯爵

Answers:


261

要定义全局变量,您可以使用静态关键字

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

现在您可以通过调用从任何地方访问a和b

Example.a;

Example.b;

6
“全局”是类的名称。
杰罗姆(Jerome)

12
这样做时要小心-卸载Global类时,变量将为undefined null。如果您出售您的应用,这将迟早发生,并且您一直在到处寻找错误,但并不在那里....
2011年

10
static关键字使变量全局访问,而他们的类加载。
sjas 2012年

22
关于类卸载:如果从任何GC根目录到Global或其子实例的任何强引用链,或从已加载且不可卸载的类到Global的任何编译时引用,则相对于Global的Class对象都是强是可访问的,因此加载Global的ClassLoader也是可访问的;这使得无法卸载全局(因为类卸载只能在GC完全删除对加载给定类的ClassLoader的任何强引用之后进行)。如果您根本没有引用,那么如何卸载会成为问题???
布鲁诺·雷斯

4
@Abi我建议您将类重命名Global为其他名称(TestClass?),以免给人以GlobalJava关键字之类的印象。安全胜过遗憾:)
尼古拉斯·里纳

53

你不知道 那是设计使然。即使可以,也不应该这样做。

话虽如此,您可以在名为Globals的类中创建一组公共静态成员。

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

但您实际上不应该:)。认真..不要这样做。


6
那么,可以声明常量以便所有类方法都可以访问它们的更好的方法是什么呢?
Alston 2014年

6
这种性质的帖子是新手发展全局变量恐惧症的原因,然后我们看到各种可恶的技术都被设计用来规避全局变量忌讳,但达到相同的效果。
Evgeni Sergeev

38
拒绝投票,说:“不要这样做。” 无需解释或提及原因的解释。
Jeff McCune 2015年

4
@JeffMcCune:为了使您的陈述更清楚,“不要这样做”实际上是胡说八道。在有用时执行此操作。例如,我必须使用一些IAbstractLoggerBullshit调试代码,而System.err当然在这种过度设计的环境中不起作用。我无法在数百个无用的适配器类之间的记录程序废话中传递代码。
所以所以

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 2012年

12
Joshua Bloch撰写的有效Java,第4章:类和接口,项目19:仅使用接口定义类型“常量接口模式是对接口的不良使用。” 这本书值得一读!:)
MariuszS

1
此外,从JDK 1.5+开始,您可以对全局变量使用静态导入,而无需实现。
MariuszS

9
....是的,实际上并没有任何解释,只是说有些书说那是不好的。
linkhyrule5

14
这是给你的报价。甲骨文说:“为了解决这个问题,人们有时将静态成员放到一个接口中并从该接口继承。这是一个坏主意。实际上,它有一个名字很糟糕:常量接口反模式(请参阅有效的Java项目17。)问题在于,一个类对另一个类的静态成员的使用仅是实现细节。当一个类实现接口时,它将成为该类的公共API的一部分。实现细节不应泄漏到公共API。”
2015年

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
没错,尽管我认为您对“ Globals”的使用会使事情有些混乱:-)。像“参数”这样的东西会更合适,因为它不一定是全局的。
马克·彼得斯

11

很多好的答案,但是我想举这个例子,因为它被认为是另一个类访问一个类的变量的更合适的方法:使用getter和setter方法。

之所以以这种方式使用getter和setter而不是仅仅将变量公开的原因如下。可以说,您的var将是一个全局参数,您永远不要希望有人在程序执行期间更改它(例如,当您与团队一起开发代码时),例如网站的URL。从理论上讲,这可能会更改,并且在您的程序中可能会多次使用,因此您希望使用全局变量来一次更新所有变量。但是您不希望其他人进入并更改此变量(可能没有意识到它的重要性)。在那种情况下,您仅不包括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类之外没有任何东西。的static关键字代表一个类变量,相反,实例变量,仅具有一个拷贝和创建跨所有类的实例,这意味着它的值可以在任何时候被改变和访问在所有实例超越。

如果您需要一个可以在范围之外访问的全局变量,那么这就是您需要的变量,但是它的范围仅在类所在的位置存在,并且仅此而已。


9

坦白地说,Java OO程序中没有“ GLOBAL”的概念

不过,您的问题背后还有一些真相,因为在某些情况下,您想在程序的任何部分运行方法。例如,Phrase-O-Matic应用程序中的--- random()方法;该方法应可从程序的任何位置调用。

因此,为了满足上述条件,“我们需要具有类似于全局的变量和方法”

声明全球变量。

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

宣告一种全球方法-2.45155

 1. Mark the method as public static While declaring.

因为我将全局变量和方法声明为静态,所以您只需在以下代码的帮助下即可在任意位置调用它们

类名.X

注意:根据要求,X可以是方法名称或变量名称,而ClassName是在其中声明它们的类的名称。


9

除了常量之外,什么都不应该是全局的。

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

将其放在您的主类中。在其他.java文件中,可通过以下方式使用它:

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

确保当您将代码从剪裁室地板移开并释放时,请删除或注释掉此功能。

如果您使用随机分配器等主力方法,建议您创建一个“工具箱”包!所有编码器都应该有一个,然后只要您想在.java中使用它,只需将其导入即可!


5

Java中没有真正的全局变量。每个静态变量都必须属于某个类(例如System.out),但是当您决定将其放入哪个类时,可以从同一类加载器加载的所有位置引用它。

请注意,在更新时应始终保护静态变量,以避免出现竞争情况。


1
Java在功能上不提供全局变量,但是如果您想使用全局变量概念,我们可以使用static关键字
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";
}

枚举在这种情况下也很有用:

例如 Calendar.JANUARY


全局变量是否需要为最终变量?为什么?
Konerak 2011年

1
“ final”表示“常数”,因此这是一个全局常数。
duffymo 2011年

1
不,如果您想共享该变量并更改数据然后删除final,那也就是Global变量的含义,但这当然取决于您要共享的方式,您使用的位置以及所有内容,
Jigar Joshi

CODE此示例中的类型是什么?它在哪里定义?
M_M 2012年

还要注意:CODE是大写的,因为它是通用的Java表示法,用于将所有大写用于声明为final的变量,并且不打算在程序执行过程中进行更改。
Dan Ciborowski-MSFT

1

创建一个独立的文件,例如 使用第一个解决方案的Example.java,就好了。您也可以在应用程序中执行此操作,例如,全局变量对于您当前的应用程序来说是特殊的,等等:

在开头创建一个类,并在其中声明变量:

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

然后,您可以从应用程序的任何位置访问这些变量(将它们用作“ Globals.month_number”等)。


您可以告诉我此解决方案有什么问题吗?我一直在使用它,这是最方便的一种。因此,我不能以其他方式将这种低俗的看法视为个人事或仅由一个愚蠢的人来做。
Apostolos

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

按照这个概念,全局变量(也称为实例变量)是类级别的变量,即,它们是在类内部但在方法外部定义的。为了使它们完全可用并直接使用它们,请提供static关键字。因此,如果我正在编写用于简单算术运算的程序,并且它需要一个数字对,则两个实例变量将定义为:

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

此外,在实例变量之前使用static关键字使我们不必一次又一次为相同变量指定数据类型。只需直接写变量。


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是一个利用AOP的Java框架,尽管它传统上用于Web应用程序,但是核心应用程序可以在整个Java框架(包括8.0)中通用。这可能是您想要探索的方向。


0

了解问题

我认为全局变量的限定条件是可以在代码中的任何位置访问和更改全局变量,而无需关心静态/实例调用或将任何引用从一个类传递给另一个类。

通常如果你有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;
    }
}

并想访问和更新myvarB类,

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 2014年

-2

要定义全局变量,您可以使用静态关键字

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

现在您可以通过调用从任何地方访问a和b

Tools.a;
Tools.b;

Yoy是正确的...特别是在J2ME中...您可以通过将MidLet构造函数(简单的初始化)放入以下代码行来避免NullPointerException:

new Tools();

这样可以确保在使用工具的任何指令之前分配工具。

而已!


3
嗯...抱歉,但是现有答案尚未涵盖的这个新增内容是什么?
Mysticial

也许你是对的..但是这个答案解释了诸如内存分配之类的事情。
user261674213年

Java中没有静态顶级类
Andremoniy 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.