343

我写了这个测试代码:

class MyProgram
{
    int count = 0;
    public static void main(String[] args)
    {
        System.out.println(count);
    }
}

但它给出了以下错误:

Main.java:6: error: non-static variable count cannot be referenced from a static context
        System.out.println(count);
                           ^

如何让我的方法识别我的类变量?

4

15 回答 15

357

您必须了解类和该类的实例之间的区别。如果您在街上看到一辆汽车,即使您看不到是哪种型号或类型,您也会立即知道这是一辆汽车。这是因为您将看到的内容与“汽车”类进行比较。该类包含与所有汽车相似的内容。把它想象成一个模板或一个想法。

同时,您看到的汽车是“汽车”类的一个实例,因为它具有您期望的所有属性:有人在驾驶它,它有一个引擎、车轮。

所以类说“所有汽车都有颜色”,实例说“这辆特定的汽车是红色的”。

在 OO 世界中,您定义了类,而在类内部,您定义了一个 type 的字段Color。当类被实例化时(当你创建一个特定的实例时),内存是为颜色保留的,你可以给这个特定的实例一个颜色。由于这些属性是特定的,因此它们是非静态的。

静态字段和方法与所有实例共享。它们用于特定于类而不是特定实例的值。对于方法,这通常是全局辅助方法(如Integer.parseInt())。对于字段,它通常是常量(如汽车类型,即您有一个不经常更改的有限集合)。

要解决您的问题,您需要实例化您的类的一个实例(创建一个对象),以便运行时可以为该实例保留内存(否则,不同的实例会相互覆盖,这是您不想要的)。

在您的情况下,请尝试将此代码作为起点:

public static void main (String[] args)
{
    try
    {
        MyProgram7 obj = new MyProgram7 ();
        obj.run (args);
    }
    catch (Exception e)
    {
        e.printStackTrace ();
    }
}

// instance variables here

public void run (String[] args) throws Exception
{
    // put your code here
}

main()方法创建它包含的类的实例(听起来很奇怪,但由于main()是用类而不是实例创建的,它可以这样做),然后调用实例方法(run())。

于 2010-04-01T10:10:38.590 回答
107

静态字段和方法连接到类本身而不是它的实例。如果您有一个类A、一个“普通”(通常称为实例)方法b和一个静态方法c,并且您创建了一个a类的实例,那么对和A的调用都是有效的。方法不知道连接了哪个实例,因此它不能使用非静态字段。A.c()a.b()c()

您的解决方案是使您的字段静态或非静态方法。你的主要可能看起来像这样:

class Programm {

    public static void main(String[] args) {
        Programm programm = new Programm();
        programm.start();
    }

    public void start() {
        // can now access non-static fields
    }
}
于 2010-04-01T10:14:51.480 回答
72

static关键字修改类中方法或变量的生命周期。在static加载类时创建方法或变量。未声明为的方法或变量static仅在将类实例化为对象时(例如通过使用new运算符)创建。

从广义上讲,一个类的生命周期是:

  1. 编写类的源代码,创建一个模板或模式或标记,然后可用于
  2. 使用该类使用运算符创建一个对象,以new将该类的实例作为实际对象,然后在完成该对象时
  3. 在垃圾收集期间销毁对象以回收它所持有的资源,例如内存。

为了有一个应用程序的初始入口点,Java 采用了 Java 程序必须有一个类,该类包含一个具有商定名称或特殊名称的方法。这种特殊的方法被称为main()。由于无论包含主方法的类是否已实例化,该main()方法都必须存在,因此必须使用修饰符声明该方法,static以便一旦加载该类,该main()方法就可用。

结果是当你通过命令行启动你的Java应用程序时java helloworld会发生一系列动作。首先启动并初始化一个 Java 虚拟机。接下来,将包含已编译 Java 代码的 helloworld.class 文件加载到 Java 虚拟机中。helloworld然后 Java 虚拟机在被调用的类中寻找一个方法main(String [] args)static即使该类实际上没有被实例化为对象,该方法也必须存在。Java 虚拟机不会通过从类创建对象来创建类的实例。main()它只是加载类并在方法处开始执行。

因此,您需要将类的实例创建为对象,然后您可以访问尚未使用static修饰符声明的类的方法和变量。一旦您的 Java 程序开始使用该main()函数,您就可以使用任何具有修饰符的变量或方法,static因为它们作为正在加载的类的一部分存在。

main()但是,在方法之外的那些没有修饰符的类的变量和方法在类static的实例被创建为方法内的对象之前不能使用main()。创建对象后,您可以使用对象的变量和方法。尝试使用没有static修饰符的类的变量和方法而不经过类的对象会在编译时被 Java 编译器捕获并标记为错误。

import java.io.*;

class HelloWorld {
    int myInt;      // this is a class variable that is unique to each object
    static int myInt2;  // this is a class variable shared by all objects of this class

    static void main (String [] args) {
        // this is the main entry point for this Java application
        System.out.println ("Hello, World\n");
        myInt2 = 14;    // able to access the static int
        HelloWorld myWorld = new HelloWorld();
        myWorld.myInt = 32;   // able to access non-static through an object
    }
}
于 2015-01-16T15:37:22.630 回答
13

让我们首先分析您的程序。在您的程序中,您的第一个方法是main(),请记住它是静态方法...然后为该方法声明局部变量(compareCount、low、high 等)。这个变量的作用域只是声明的方法,不管它是静态方法还是非静态方法。因此,您不能在该方法之外使用这些变量。这是你犯的基本错误。

然后我们来到下一点。你告诉静态正在杀死你。(它可能会杀死你,但它只会给你的程序带来生命!!)首先你必须了解基本的东西。*静态方法只调用静态方法,只使用静态变量。*静态变量或静态方法不依赖于该类的任何实例。(即,如果您更改静态变量的任何状态,它将反映在类的所有对象中) *因此,您将其称为类变量或类方法。还有更多关于“静态”关键字的内容。我希望你现在明白了。首先更改变量的范围并将其声明为静态(以便能够在静态方法中使用它)。

给你的建议是:你误解了变量和静态功能范围的概念。清楚地了解这一点。

于 2011-07-18T09:10:05.990 回答
12

为了能够从您的静态方法访问它们,它们需要是静态成员变量,如下所示:

public class MyProgram7 {
  static Scanner scan = new Scanner(System.in);
  static int compareCount = 0;
  static int low = 0;
  static int high = 0;
  static int mid = 0;  
  static int key = 0;  
  static Scanner temp;  
  static int[]list;  
  static String menu, outputString;  
  static int option = 1;  
  static boolean found = false;

  public static void main (String[]args) throws IOException {
  ...
于 2010-04-01T10:08:59.627 回答
12

最基本的事情是静态变量或静态方法处于类级别。类级别的变量或方法在实例级别的方法或变量之前被加载。显然没有加载的东西不能使用。所以java编译器不让在运行时处理的事情在编译时解决。这就是为什么它给你错误非静态事物不能从静态上下文中引用的原因。您只需要阅读有关类级别范围、实例级别范围和本地范围的信息。

于 2013-07-24T13:26:20.067 回答
7

现在您可以在方法中添加/使用实例

public class Myprogram7 {

  Scanner scan;
  int compareCount = 0;
  int low = 0;
  int high = 0;
  int mid = 0;  
  int key = 0;  
  Scanner temp;  
  int[]list;  
  String menu, outputString;  
  int option = 1;  
  boolean found = false;  

  private void readLine() {

  }

  private void findkey() {

  }

  private void printCount() {

  }
  public static void main(String[] args){

    Myprogram7 myprg=new Myprogram7();
    myprg.readLine();
    myprg.findkey();
    myprg.printCount();
  }
}
于 2013-09-24T10:03:30.657 回答
4

我将尝试向您解释静态的东西。首先,静态变量不属于该类的任何特定实例。它们通过类的名称来识别。静态方法再次不属于任何特定实例。他们只能访问静态变量。想象一下,您调用 MyClass.myMethod() 并且 myMethod 是一个静态方法。如果你在方法中使用非静态变量,它到底怎么知道要使用哪些变量?这就是为什么您只能从静态方法中使用静态变量的原因。我再重复一遍,它们不属于任何特定实例。

于 2010-04-01T10:13:10.330 回答
4
  • 首先要知道类的实例和类本身之间的区别。类对某些属性以及在这些属性的上下文中的整体行为进行建模。实例将为这些属性定义特定值。

  • 任何绑定到 static 关键字的东西都在类的上下文中可用,而不是在类的实例的上下文中

  • 作为上述的推论

    1. 方法中的变量不能是静态的
    2. 静态字段和方法必须使用类名调用,例如 MyProgram7.main(...)
  • 静态字段/方法的生命周期等同于应用程序的生命周期

例如,汽车具有属性颜色,并表现出“运动”行为。这辆车的一个例子是一辆时速 25 公里的红色大众甲壳虫。

现在汽车的静态属性将是道路上的车轮数 (4),这将适用于所有汽车。

高温高压

于 2010-04-01T11:55:11.103 回答
2

在调用实例方法或实例变量之前它需要一个对象(Instance)。当从静态方法调用实例变量时,编译器不知道该变量属于哪个对象。因为静态方法没有对象(总是只有一个副本)。当您从实例方法调用实例变量或实例方法时,它引用该this对象。这意味着该变量属于创建的任何对象,并且每个对象都有自己的实例方法和变量的副本。

静态变量被标记为static并且实例变量没有特定的关键字。

于 2018-05-25T19:45:43.737 回答
1

ClassLoader 负责加载类文件。让我们看看当我们编写自己的类时会发生什么。

示例 1:

class StaticTest {

      static int a;
      int b;
      int c;
}

现在我们可以看到“StaticTest”类有3个字段。但实际上不存在b,c成员变量。但是为什么???。好吧,让我们拭目以待。这里 b,c 是实例变量。因为实例变量在对象创建时获取内存。所以这里 b,c 还没有得到任何记忆。这就是为什么不存在 b,c。所以只存在a。对于 ClassLoader,它只有一个关于 a 的信息。ClassLoader 尚未识别 b,c 因为它的对象尚未实例化。

让我们看另一个示例:示例 2:

class StaticTest {

      public void display() {
          System.out.println("Static Test");
      }


      public static void main(String []cmd) {

             display();       
      }

}

现在如果我们尝试编译这段代码,编译器会给出 CE 错误。CE:不能从静态上下文引用非静态方法 display()。

现在对于 ClassLoader,它看起来像:

class StaticTest {

      public static void main(String []cmd) {

             display();       
      }

}

在示例 2 中,CE 错误是因为我们从静态上下文中调用非静态方法。所以ClassLoader在编译时无法识别方法display(),所以出现编译时错误。

于 2015-09-03T12:21:00.273 回答
1

这是为所有初学者解释静态关键字的一点差异。
当您更多地使用类和对象时,您会清楚地了解它。

|*| 静态:静态项目可以用类名调用
如果你在代码中观察,一些函数直接用类名调用,如

NamCls.NamFnc();

System.out.println();

这是因为 NamFnc 和 println 将在它们之前使用关键字 static 声明。

|*| 非静态:非静态项目可以用类变量调用
如果它不是静态的,你需要一个类的变量,
在类变量后面加上点,
然后调用函数。

NamCls NamObjVar = new NamCls();
NamObjVar.NamFnc();


下面的代码巧妙地解释了你

|*| 类中的静态和非静态函数:

public class NamCls
{
    public static void main(String[] args)
    {
        PlsPrnFnc("Tst Txt");

        NamCls NamObjVar = new NamCls();
        NamObjVar.PrnFnc("Tst Txt");
    }

    static void PlsPrnFnc(String SrgPsgVal)
    {
        System.out.println(SrgPsgVal);
    }

    void PrnFnc(String SrgPsgVal)
    {
        System.out.println(SrgPsgVal);
    }
}


|*| 类中的静态和非静态类:

public class NamCls
{
    public static void main(String[] args)
    {
        NamTicCls NamTicVaj = new NamTicCls();
        NamTicVaj.PrnFnc("Tst Txt");

        NamCls NamObjVar = new NamCls();
        NamNicCls NamNicVar = NamObjVar.new NamNicCls();
        NamNicVar.PrnFnc("Tst Txt");
    }

    static class NamTicCls
    {
        void PrnFnc(String SrgPsgVal)
        {
            System.out.println(SrgPsgVal);
        }
    }

    class NamNicCls
    {
        void PrnFnc(String SrgPsgVal)
        {
            System.out.println(SrgPsgVal);
        }
    }
}
于 2017-06-06T22:31:44.237 回答
1

在 Java 编程语言中,关键字static表示特定成员属于类型本身,而不是属于该类型的实例。

这意味着只static创建该成员的一个实例,该实例在该类的所有实例之间共享。

所以如果你想使用你的int count = 0;in static void main()count变量必须声明为static

static int count = 0;
于 2021-09-26T14:54:54.450 回答
0

在这个程序中你想使用 count,所以将 count 方法声明为静态

class MyProgram<br>
{
    int count = 0;
    public static void main(String[] args)
    {
        System.out.println(count);
    }
}

听说您可以将此方法声明为公共私有和受保护的。如果您使用这种方法,您可以创建一个安全的应用程序。

class MyProgram
{
    static int count = 0;
    public static void main(String[] args)
    {
        System.out.println(count);
    }
}
于 2021-08-17T18:28:02.393 回答
-1

这是因为您不创建模型类的实例,每次使用非静态方法或变量时都必须创建实例。

您可以轻松解决此问题,请参见下图

没有实例制作

没有创建类的实例

在此处输入图像描述

我的模型类文件

在此处输入图像描述

通过创建实例然后使用类非静态方法或变量很容易出错

于 2022-01-27T09:33:10.533 回答