不能从静态上下文中引用非静态变量

Non-static variable cannot be referenced from a static context

提问人:Greg 提问时间:4/1/2010 最后编辑:Bernhard BarkerGreg 更新时间:1/27/2022 访问量:1001530

问:

我写了这个测试代码:

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

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

java 变量 编译器错误 非静态

评论

4赞 Erick G. Hagstrom 9/16/2015
尽可能避免使用静电。你可以写一个完整的程序,全是静态的,就像在 .但这不会是一个非常好的选择。尝试按照它应该使用的方式使用 Java,作为一种面向对象的语言。C
1赞 Hari Reddy 6/28/2022
可能对初学者有帮助 - 可能想检查参数(可能存在不匹配)

答:

13赞 Nick Moore 4/1/2010 #1

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

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 {
  ...
381赞 Aaron Digulla 4/1/2010 #2

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

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

因此,该类说“所有汽车都有一种颜色”,而实例说“这辆特定的汽车是红色的”。

在 OO 世界中,您定义类,在类中,定义 .当类实例化时(创建特定实例时),会为颜色保留内存,您可以为此特定实例指定颜色。由于这些属性是特定的,因此它们是非静态的。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()

评论

5赞 Supahupe 1/9/2018
我现在正在向我们的新同事解释这一点 - 感谢您的精彩解释。这应该是接受者的答案。
2赞 muthuh 9/14/2021
特斯拉汽车呢?
0赞 Aaron Digulla 9/19/2021
@muthuh 这是一个设计问题:您应该创建一个类型,还是更确切地说,应该添加一个字段/属性(或或)?后者通常更灵活,您必须编写更少的代码,但如果您需要每种类型的汽车的特定行为,扩展通常更容易。TeslaCarmodelmaketype
3赞 user2656801 2/1/2022
这太烦人了。如果你刚开始使用 java 并尝试制作一个 java 文件,它要求你使主类成为静态的,如果你删除静态的,那么 java 将不会运行。如果保持静态,则会运行上述错误。然后,当程序中没有一个变量处理上述错误时,你在谷歌上搜索帮助,你会得到十几个人解释 java 内部的细节,而不是解决问题。
4赞 Petar Minchev 4/1/2010 #3

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

122赞 Mnementh 4/1/2010 #4

静态字段和方法连接到类本身,而不是连接到其实例。如果你有一个类、一个“普通”(通常称为实例)方法和一个静态方法,并且你创建了一个类的实例,那么对 and 的调用是有效的。方法不知道连接了哪个实例,因此它不能使用非静态字段。AbcaAA.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
    }
}
4赞 Everyone 4/1/2010 #5
  • 第一件事是要知道类的实例和类本身之间的区别。类对某些属性以及这些属性上下文中的整体行为进行建模。实例将为这些属性定义特定值。

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

  • 作为上述结果的推论

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

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

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

HTH型

13赞 Suseendran.P 7/18/2011 #6

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

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

给你的建议是:你误解了变量和静态函数的作用域。对此有清晰的认识。

12赞 Ajay Bhojak 7/24/2013 #7

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

6赞 Sainath Patwary karnate 9/24/2013 #8

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

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

评论

0赞 XMAN 11/27/2018
非常扎实的例子,我用它作为模板,将复杂的 src 文件修改为适当的结构。
76赞 Richard Chambers 1/16/2015 #9

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

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

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

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

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

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

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

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

评论

1赞 9/29/2021
感谢您的精彩解释。
1赞 Newaz Sharif Amit 9/3/2015 #10

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()。所以发生了编译时错误。

评论

0赞 plamut 9/3/2015
可能在你设法完成之前不小心提交了你的答案?请编辑它并添加缺失的内容,谢谢!
1赞 Sujay U N 6/7/2017 #11

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

|*|静态的:静态项可以用类名调用 如果你在代码中观察到,有些函数是直接用类名
调用的,比如

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);
        }
    }
}
2赞 Lakindu Akash 5/26/2018 #12

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

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

0赞 Vikas Dhiman 8/18/2021 #13

在这个程序中,你想使用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);
    }
}
1赞 hakki 9/26/2021 #14

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

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

因此,如果要使用 in ,变量必须声明为int count = 0;static void main()countstatic

static int count = 0;
-1赞 KaranKulshrestha 1/27/2022 #15

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

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

Without Instance making

无需创建类实例

enter image description here

我的模型类文件

enter image description here

只需创建实例,然后使用类非静态方法或变量,即可轻松出错