关于java:无法从静态上下文引用非静态变量

Non-static variable cannot be referenced from a static context

我写了这个测试代码:

1
2
3
4
5
6
7
8
class MyProgram
{
    int count = 0;
    public static void main(String[] args)
    {
        System.out.println(count);
    }
}

但它给出了以下错误:

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

如何获取识别类变量的方法?


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

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

所以这个类说"所有的汽车都有一个颜色",而实例说"这个特定的汽车是红色的"。

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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())。


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

解决方案是,要么使字段静态化,要么使方法非静态化。你主要可以这样看:

1
2
3
4
5
6
7
8
9
10
11
class Programm {

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

    public void start() {
        // can now access non-static fields
    }
}


关键词改变了一类中的一种方法或变量的生命周期。方法或变量随时间的推移而产生。一种方法或变量,它不是以static的形式声明的,只有当该类别被设置为一个对象,以new为例。

The lifecycle of a class,in broad terms,is:

  • 课堂源代码是写入或创建模板的。模式或堆栈,可用于
  • 运算符使用阶级创建一个阶级实例作为一个实际的对象,然后根据该对象创建一个实例。
  • Destroy the object reclaiming the resources is holding as memory during garbage collection.
  • 为便于执行,日本国际协力事业团通过了《公约》,日本国际协力事业团必须有一个类别,包含一种商定的方法或特别名称。这一特殊方法被称为main()。自从确定了主要方法或未确定方法的类别之后,就必须存在该方法,方法必须与EDOCX1,0一起声明,修改后,一旦该类别被装载,则可以使用EDOCX1,5。

    结果是当你开始使用你的爪哇时,一个指挥线,如EDOCX1&9。第一个是一个虚拟机的启动和初始化。下一个地狱世界.列有编译的爪哇码的文件被装入虚拟机。然后爪哇虚拟机寻找一种方法在helloworld类中被称为main(String [] args)。这一方法必须是static因此,即使这一类物质实际上并未作为一个物体存在。爪哇虚拟机不创建阶级的实例,创建阶级的对象。它只是在main()方法上装载了等级和开始执行。

    因此,你需要创建一个实例,作为一个对象,然后你可以访问没有以static声明的等级的方法和变量。一旦你的爪哇程序开始使用main()功能,你可以使用任何变量或方法,自从它们作为装载级的一部分存在以来。

    然而,这些变量和方法在main()之外的等级中,不具备EDOCX1〕〔0〕的方法,在等级的一个实例被创建为main()中的一个对象之前,修改不能被使用。在创建对象之后,你可以使用对象的变量和方法。一种试图使用不具备static的类别的变量和方法的尝试被Java编译器当作一个误差在编译时间和闪烁时进行了考验。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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
    "
    );
            myInt2 = 14;    // able to access the static int
            HelloWorld myWorld = new HelloWorld();
            myWorld.myInt = 32;   // able to access non-static through an object
        }
    }

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

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

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


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


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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 {
      ...


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    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();
      }
    }


    我会尽力向你解释静态的东西。首先,所有静态变量不属于类的任何特定实例。它们可以用类的名称识别。静态方法不再属于任何特定实例。它们只能访问静态变量。假设您调用myclass.mymethod(),而mymethod是一个静态方法。如果你在方法中使用非静态变量,那它怎么知道要使用哪些变量呢?这就是为什么只能从静态方法使用静态变量的原因。我再重复一遍,它们不属于任何特定的实例。


    • 第一件事是知道类的实例和类本身之间的区别。类为某些属性建模,并在这些属性的上下文中为整个属性的行为建模。实例将为这些属性定义特定的值。

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

    • 作为以上的推论

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

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

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

    高温高压


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

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


    对于所有初学者来说,解释静态关键字有点困难。当您更多地使用类和对象时,您将清楚地了解它。

    |*|静态:静态项可以用类名调用如果您在代码中观察到,则直接使用类名称调用某些函数,例如

    1
    2
    3
    NamCls.NamFnc();

    System.out.println();

    这是因为NAMFNC和println将使用前面的关键字static声明。

    |*|非静态:可以使用类变量调用非静态项如果不是静态的,则需要类的变量,在类变量后加上点,然后然后调用函数。

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

    下面的代码解释得很清楚

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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);
        }
    }

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    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);
            }
        }
    }


    这是典型的负荷,它有责任装载等级文件。让我们看看当我们写自己的班级时发生了什么。

    Example 1:

    ZZU1

    现在我们可以看到"Statictest"类别有3个字段,但实际中没有B,C成员变量,但为什么呢?Now we can see that class"statictest"has 3 fields.But actually there is no existence of B,C member variable.什么?好吧,你看这里是B,C是instance variable.Since instance variable gets the memory at the time of object creation.所以这里没有记忆。这就是为什么没有B的存在,C,所以只有A的存在。对于分类装载,只有一个关于A.Classloader Yet不承认B,c因为它的对象没有设置Yet。

    Let's see another example:Example 2:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class StaticTest {

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


          public static void main(String []cmd) {

                 display();      
          }

    }

    现在,如果我们试图编译这个编译器的代码,就会造成这个错误。CE:non-static method display()cannot be referenced from a static context.

    现在看起来像是

    1
    2
    3
    4
    5
    6
    7
    8
    class StaticTest {

          public static void main(String []cmd) {

                 display();      
          }

    }

    以2为例,这个错误是因为我们从静态上下文中称为非静态方法。因此,分类负载在编译时不可能识别方法显示()所以编译时出现误差。