【问题标题】:Global variables in JavaJava中的全局变量
【发布时间】:2011-01-10 12:02:05
【问题描述】:

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

【问题讨论】:

  • 你能告诉我们为什么你想在Java中定义全局变量吗?
  • 从类外访问变量
  • 也许您应该编辑您的问题以包含一些示例代码,以准确说明您想要什么。这将帮助我们推荐最佳解决方案。
  • @Adam :我应该能够从另一个类中更改一个类中变量的值。
  • 你没有。 Java 中没有全局变量。

标签: java


【解决方案1】:

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

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

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

Example.a;

Example.b;

【讨论】:

  • 这样做时要小心——当全局类被卸载时,变量将是未定义的空值。如果你卖掉你的应用程序,这迟早会发生,你一直在到处寻找错误,但不是在那里......
  • static 关键字使变量可以全局访问,同时加载它们的类。
  • 关于类卸载:如果从任何 GC Root 到 Global 或其子实例的任何强引用链,或者从已加载和不可卸载的类到 Global 的任何编译时引用,则相对于 Global 的 Class 对象是强可达的,因此加载 Global 的 ClassLoader 也是如此;这使得无法卸载 Global(因为类卸载只能在 GC 完全删除对加载给定类的 ClassLoader 的任何强引用后发生)。如果你根本没有参考,卸载怎么可能是个问题???
  • @Abi 我建议您将您的课程从 Global 重命名为其他名称 (TestClass?),以免给人留下 Global 这样的印象Java 关键字。比抱歉更安全:)
  • @user387184 总而言之,只要有对那个“全局”类的引用,值就不会突然变为空,对吧?
【解决方案2】:

你没有。这是设计使然。即使可以,也不应该这样做。

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

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

但你真的不应该:)。说真的..不要这样做。

【讨论】:

  • 正如我在上面所写的 - 当类被卸载时,变量的值会变为 null 并且您的应用程序将崩溃。
  • 那么我可以声明常量以便所有类方法都可以访问它们的更好方法是什么?
  • 这种性质的帖子是新手产生全局变量恐惧症的原因,然后我们看到各种令人震惊的技术被设计来规避全局变量禁忌,但达到同样的效果。
  • 反对说“不要这样做”。没有解释或提及原因的解释。
  • 我会去做的。
【解决方案3】:

另一种方法是创建这样的界面:

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

任何需要使用它们的类只需要实现接口:

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

【讨论】:

  • 我想知道为什么这个答案(在我之前)没有投票。它是否没有提供所有其他答案所提供的合理替代答案?
  • Effective Java by Joshua Bloch,第 4 章:类和接口,第 19 项:仅使用接口来定义类型“常量接口模式是对接口的不良使用。”这本书值得一读! :)
  • 此外,从 JDK 1.5+ 开始,您可以对全局变量使用静态导入,不需要实现。
  • .... 是的,这实际上并没有解释什么,只是说有些书说它很糟糕。
  • 这是给你的报价。 Oracle 说:“为了解决这个问题,人们有时将静态成员放入接口并从该接口继承。这是一个坏主意。事实上,这是一个坏主意,它有一个名字:常量接口反模式(参见 Effective Java Item 17)。问题是一个类对另一个类的静态成员的使用仅仅是一个实现细节。当一个类实现一个接口时,它成为该类的公共 API 的一部分。实现细节不应该泄漏到公共 API。”
【解决方案4】:

你最好使用依赖注入:

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

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

【讨论】:

  • 是的,虽然我认为您对“Globals”的使用有点让人困惑:-)。像“参数”这样的东西会更合适,因为它不一定是全局的。
【解决方案5】:

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

您以这种方式使用 getter 和 setter 而不是仅仅将变量公开的原因如下。假设您的 var 将成为一个全局参数,您永远不希望有人在程序执行期间更改它(在您与团队一起开发代码的情况下),例如网站的 URL。从理论上讲,这可能会发生变化,并且可能会在您的程序中多次使用,因此您希望使用全局 var 能够一次更新它。但是您不希望其他人进入并更改此 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;
    }
}

【讨论】:

  • 不应该是public static class
  • 这不是一个有效的 java 命令。我不相信它甚至会编译。
  • 如果我们制作Global.java文件,您的意思是类声明无效吗?我实际上把你的“全球”类作为一个子类。
【解决方案6】:

在java OO程序中确实没有“GLOBAL”的概念

尽管如此,您的问题背后还是有一些道理,因为在某些情况下,您希望在程序的任何部分运行方法。 例如---Phrase-O-Matic 应用程序中的random() 方法;它是一个可以从程序的任何位置调用的方法。

所以为了满足上面“我们需要有类似全局的变量和方法”之类的东西

将变量声明为全局变量。

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

将方法声明为全局方法

 1. Mark the method as public static While declaring.

因为我将全局变量和方法声明为静态的,所以您可以通过以下代码在任何地方调用它们

类名.X

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

【讨论】:

    【解决方案7】:

    Java中没有全局变量

    尽管如此,我们所拥有的是 static 关键字,这就是我们所需要的。 在 Java 中,除了类之外什么都不存在。 static 关键字代表一个类变量,与实例变量相反,它只有一个副本,并且跨越创建的该类的所有实例,这意味着它的值可以随时在所有实例中更改和访问。

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

    【讨论】:

      【解决方案8】:

      除了常量之外,没有什么是全局的。

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

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

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

      确保当您将代码从剪辑室地板上移出并发布时,您会删除或注释掉此功能。

      如果你有一个主力方法,比如随机发生器,我建议创建一个“工具箱”包!所有编码人员都应该有一个,然后每当您想在 .java 中使用它时,只需导入它!

      【讨论】:

        【解决方案9】:

        Java 中不存在真正的全局变量。每个静态变量都必须属于某个类(如 System.out),但是当您决定了它将进入哪个类时,您可以从同一个类加载器加载的任何地方引用它。

        请注意,更新时应始终保护静态变量以避免竞争条件。

        【讨论】:

        • java在功能上没有提供全局变量,但是如果你想有一个全局变量的概念,我们可以使用static关键字
        【解决方案10】:

        了解问题

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

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

        并且想要访问和更新 B 类中的 myvar

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

        【讨论】:

          【解决方案11】:
          public class GlobalClass {
               public static int x = 37;
               public static String s = "aaa";
          }
          

          这样您就可以使用GlobalClass.xGlobalClass.s 访问它们

          【讨论】:

            【解决方案12】:

            如果您需要更新全局属性,可以使用一个简单的 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());
                }
            }
            

            【讨论】:

              【解决方案13】:
              public class GlobalImpl {   
              
               public static int global = 5;
              
              }
              

              您可以在任何地方拨打电话:

              GlobalImpl.global // 5
              

              【讨论】:

                【解决方案14】:

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

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

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

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

                【讨论】:

                • 请您告诉我这个解决方案有什么问题,而不是投票?我一直在使用它,它是最方便的。所以我不能这样做,否则我不能把这个反对票看作是个人的事情,或者只是由一个愚蠢的人做的。
                【解决方案15】:

                很简单:

                class UseOfGlobal
                {
                private static int a;
                private static int b;
                }
                

                但尽可能在方法块中定义局部变量总是好的。

                【讨论】:

                  【解决方案16】:

                  正如您可能从答案中猜到的那样,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;
                      }
                  }
                  

                  还有

                  现在这远非最佳做法,正如您在广告中看到的那样:不要在家里这样做

                  【讨论】:

                    【解决方案17】:

                    Java 中没有全局变量,但有带有公共字段的全局类。您可以使用 java 5 的静态导入功能使其看起来几乎像全局变量。

                    【讨论】:

                      【解决方案18】:

                      通常全局变量(我假设您将其与 C、Cpp 进行比较)定义为 public static final

                      喜欢

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

                      ENUM 在这种情况下也很有用:

                      例如Calendar.JANUARY)

                      【讨论】:

                      • 全局变量需要是final的吗?为什么?
                      • “final”的意思是“常数”,所以这是一个全局常数。
                      • 不,这就是全局变量的含义,如果您想共享该变量并更改数据,那么只需删除 final 但这当然取决于您想要共享的方式、使用的位置以及所有,
                      • 这个例子中CODE的类型是什么?它是在哪里定义的?
                      • 另请注意:CODE 全部大写,作为其常见的 java 表示法,对您声明为 final 且不打算在程序过程中更改的变量使用全部大写。
                      【解决方案19】:

                      要允许对另一个类的静态成员进行非限定访问,您还可以进行静态导入:

                      import static my.package.GlobalConstants;
                      

                      现在,而不是 print(GlobalConstants.MY_PASSWORD);
                      您可以直接使用常量:print(MY_PASSWORD);

                      请参阅What does the "static" modifier after "import" mean? 来决定。

                      并考虑 Evan Lévesque 关于携带常量的接口的回答。

                      【讨论】:

                        【解决方案20】:
                        // 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
                        

                        【讨论】:

                        • 这个答案添加了什么其他答案没有?我在这个答案中看不到任何“新”价值。
                        【解决方案21】:

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

                        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 关键字使我们不必一次又一次地为相同的变量指定数据类型。直接写变量就好了。

                        【讨论】:

                        • Java中没有全局变量;它们也不称为实例变量;将它们定义为static 并不“使它们完全可用”。第一段是废话。示例是不好的做法。
                        【解决方案22】:

                        一般来说,Java 没有任何全局变量。除了局部变量,所有变量都在程序中定义的任何类的范围内。 我们可以让静态变量拥有全局变量的作用域。

                        【讨论】:

                          【解决方案23】:

                          没有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
                          */
                          

                          【讨论】:

                            【解决方案24】:

                            面向对象编程是在理解变量的范围与封装这些变量的类对象密切相关的基础上构建的。

                            创建“全局变量”的问题在于它不是 Java 的行业标准。它不是行业标准,因为它允许多个类异步操作数据,如果您正在运行多线程应用程序,这在线程安全方面会变得更加复杂和危险。有various other reasons为什么使用全局变量无效,但如果你想避免这种情况,我建议你诉诸Aspect-Oriented Programming

                            面向方面的编程解决了这个问题,方法是让父类通过称为“advices”的东西来负责范围,这会在不实际修改代码的情况下向代码添加额外的行为。它为横切关注点或全局变量使用提供了解决方案。

                            Spring 是一个利用 AOP 的 Java 框架,虽然它传统上用于 Web 应用程序,但核心应用程序可以在整个 Java 框架(包括 8.0)中普遍使用。这可能是您想要进一步探索的方向。

                            【讨论】:

                              【解决方案25】:

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

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

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

                              Tools.a;
                              Tools.b;
                              

                              Yoy 是对的……尤其是在 J2ME 中…… 您可以通过放入 MidLet 构造函数来避免 NullPointerException (proggy 初始化)这行代码:

                              new Tools();
                              

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

                              就是这样!

                              【讨论】:

                              • 嗯...抱歉,但这增加了什么现有答案尚未涵盖的内容?
                              • 也许你是对的..但是这个答案解释了内存分配之类的事情。
                              • java中没有静态顶级类
                              猜你喜欢
                              • 1970-01-01
                              • 1970-01-01
                              • 2016-04-06
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2017-11-12
                              • 2017-02-17
                              • 1970-01-01
                              相关资源
                              最近更新 更多