【问题标题】:What exactly does "static" mean when declaring "global" variables in Java?在 Java 中声明“全局”变量时,“静态”究竟是什么意思?
【发布时间】:2011-03-25 20:28:11
【问题描述】:

我已经多次遇到这个问题,但我从来没有费心去了解它为什么会发生,也没有去了解“静态”的真正含义。我刚刚应用了 Eclipse 建议的更改并继续前进。

public class Member {

 // Global Variables
 int iNumVertices;
 int iNumEdges;

 public static void main(String[] args) {

  // do stuff

  iNumVertices = 0; // Cannot make a static reference to the non-static field iNumVertices

  // do more stuff

 } // main end 
}

所以 eclipse 告诉我做static int iNumVertices; 我不知道为什么。那么究竟什么是“静态”,它是如何使用的,使用“静态”的目的是什么,为什么会给我这个问题呢?

【问题讨论】:

  • 那些不是全局变量。他们甚至不公开。即使它们是公开的,它们也不会是全局变量。即使它们是公共的和静态的,它们也不会是全局变量。 Java没有全局的概念。 Everything 要么在本地声明,要么在类或接口中声明。
  • @Mark... 对不起?我不知道这些事实。感谢您的澄清。那么你会如何对它们进行分类呢?
  • @Hristo:我认为“成员变量”是正确的术语。
  • 将 C/C++ 作为一个单独的问题来处理可能是个好主意。
  • @deus-ex...谢谢。我将作为一个单独的问题重新发布。

标签: java class static instance-variables static-variables


【解决方案1】:

这是你的例子:

public class Member {

    // Global Variables
    int iNumVertices;
    int iNumEdges;

    public static void main(String[] args) {

        // do stuff

        iNumVertices = 0; // Cannot make a static reference to the non-static field iNumVertices

    }
}

方法main 是与类关联的静态方法。它不与Member 的实例关联,因此它无法访问与Member 的实例关联的变量。解决此问题的方法是 使这些字段成为静态的。相反,您需要使用 new 关键字创建 Member 的实例。

这是修改后的版本:

public class Member {
    // Fields
    private int iNumVertices;
    private int iNumEdges;

    public Member(){
        // init the class
    }

    public static void main(String[] args) {
        Member member = new Member();
        member.iNumVertices = 0;
        // do more stuff
    }
}

发现自己在创建全局静态数据表明您应该仔细考虑如何设计某些东西。这不是总是错的,但它应该告诉你想想你在做什么。

【讨论】:

  • 哦……我明白了。这很有意义。为什么决定将 2 个全局变量设为私有?是不是因为它们属于 Member 类,只能被 Member 对象访问?
  • 最好将不需要从外部访问的所有内容设为私有,即使在只有一个类的小型测试项目中也是如此。
  • @Hristo 我相信通常每个实例变量(也称为字段、属性和其他一些名称)都应该是私有的。您希望尽可能少地公开班级的内部工作。这可以帮助您使您的班级更具可预测性,因为您不会让其他人修改班级的状态。 6 个月后,当您修复代码中的错误时,如果您将它们保密,您将不必担心其他 5 个文件会更改您的变量。
  • .. 感谢您的回复。这是有道理的,将它们保密似乎是一种很好的做法。幸运的是,这不是一个长期项目……它是我正在研究的一个谜题的短期解决方案,所以它不会大规模进行。但我会在未来的项目中记住这一点:)
【解决方案2】:

static 变量是类的所有对象共享的变量。在您创建的每个 Member 对象的示例中,您将获得具有自己的 iNumVertices 值的对象。当您将 static 与变量一起使用时,只有一个变量在 Member 的每个对象之间共享。 static 方法的工作方式相同 - 它们在所有对象之间共享。

由于静态变量/方法对所有对象都是通用的,因此不需要创建类的对象来访问这些变量/方法。

iNumVertices 这样的非静态变量属于一个类的对象。不创建对象就无法访问它们。因此,当您从静态上下文(此处为 main 方法)访问非静态变量时,java 将不知道您正在尝试访问哪个对象的 iNumVertices。因此出现错误。

要么将 iNumVertices 设为静态,要么通过创建 Member 对象来引用它

Member m = new Member();
m.iNumVertices = 0;

【讨论】:

  • 因此,如果我希望一个变量特定于每个对象......如果我希望每个成员独立于另一个成员(例如,如果他们是不同的年龄),那么我不应该使用静态对吗?
  • 没错!这就是成员变量的确切用途。但是,您不能将它与变量的范围混淆 - 公共、私有等。
  • 等等...我认为范围是指变量存在的时间范围。你是说公共的、私有的等等……也定义了范围?
  • public,private 处理继承以及所有变量/方法都是可见的。 static 专门处理类对象内的变量共享。范围是在这两种情况下都使用的词,但含义完全不同。
  • 有趣...我以前没有遇到过这个。我一直在处理涉及变量/对象/等生命周期的范围......感谢您的解释。
【解决方案3】:
learn what "static" actually means

静态实际上意味着类变量对于该特定类的所有实例都是相同的,但是如果您想避免使用静态变量(这是一个好主意,因为静态变量保存在内存中)您可以传递变量value trough constructor 从而避免使用 static 修饰符,并达到相同的效果(即如果您在类实例化时传递相同的值)。

这是代码示例:

public class Car{

    private int speed;

    public Car(int speed){
        this.speed = speed;
    }

}

所以你可以在创建新实例时这样做:

Car car = new Car(100);

并且每次创建 Car 实例时它的速度都会为 100,从而避免静态声明 private static int speed = 100;

【讨论】:

  • 啊这很有趣......与其他答案略有不同的解决方案。介意发布一些代码来演示吗?
  • @Hristo 如果您希望您的示例工作,您需要创建将 iNumVertices 的值设置为 0 的函数(所谓的 setter 函数)。然后在 main 你应该实例化你的类Member member = new Member();,然后调用 setter 函数来改变你的类字段的值,member.setINumVertices(0);
【解决方案4】:

静态变量是类变量。该变量的单个副本可用于该类的所有实例,并且它们将共享该变量。静态成员也可以在不引用类的特定实例的情况下使用。

更多:

http://download.oracle.com/javase/tutorial/java/javaOO/classvars.html

【讨论】:

    【解决方案5】:

    静态变量不需要为了被实例化而被实例化,所以如果你试图从一个静态上下文中访问一个非静态变量,你就有可能试图访问一些没有被初始化/实例化的东西.

    【讨论】:

      【解决方案6】:

      静态方法只能访问静态变量。类中有两种变量。一个是静态变量(也是类变量),另一个是实例变量。内存中仅存在一份静态变量副本,但将为每个对象实例化实例变量。因此,对于静态变量,所有对象都访问同一个变量,并且一个对象所做的任何更改都将反映到其他对象。 这里的问题是为什么方法必须是静态的才能访问静态变量。当您将方法设为静态时,您无需实例化该类的对象即可访问该方法。因此,如果此方法能够访问实例变量,那么它应该更改哪个对象的变量?另一种方法是可能的,即非静态方法可以访问静态变量。

      【讨论】:

      • 因此,如果我希望一个变量特定于每个对象......如果我希望每个成员独立于另一个成员(例如,如果他们是不同的年龄),那么我不应该使用静态对吗?
      • @Hristo 正确。术语“实例”是指类的独特的、单独的实现。该类描述了每个实例的结构。静力学回避了这一点,并不是单个实例的真正一部分。它们不能对一个实例是唯一的 - 只有一个静态副本,而不是与每个实例关联的副本。
      • 感谢您的解释。这是有道理的。
      【解决方案7】:

      在静态方法中使用的每个类变量(在类体内部和方法体外部声明的变量)也需要声明为静态的。

      静态类变量和方法可以在该类之外访问,而无需该类的实例。

      【讨论】:

        【解决方案8】:

        静态变量对类的所有实例都是通用的。

        注意:如前所述,这些是类变量,即由所有实例共享。

        这些也可以称为类级变量。 通常,您将常量(定义常量还需要 final 关键字)和全局变量定义为静态。

        欲了解更多信息,请参阅: http://download.oracle.com/javase/tutorial/java/javaOO/classvars.html

        http://www.roseindia.net/java/beginners/staticvariable.shtml

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-03-12
          • 1970-01-01
          • 2019-06-07
          • 2015-04-11
          • 2014-10-29
          • 2016-01-27
          • 2014-12-05
          • 1970-01-01
          相关资源
          最近更新 更多