无法从静态上下文引用非静态变量

问题

我写了这个测试代码:

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

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


#1 热门回答(213 赞)

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

与此同时,你看到的汽车是"汽车"级别的一个实例,因为它具有你期望的所有属性:有人驾驶它,它有发动机,车轮。

因此课程上说"所有车都有颜色",实例说"这辆特定的车是红色的"。

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

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


#2 热门回答(55 赞)

静态字段和方法连接到类本身而不是其实例。如果你有classA,'normal'方法b和静态方法c,并且你创建了类A的instancea,则对A.c()a.b()的调用有效。 Methodc()不知道连接了哪个实例,因此不能使用非静态字段。

你的解决方案是让你的字段静态或你的方法是非静态的。那么你的主要看起来像这样:

class Programm {
  public static void main(String[] args){
    Programm programm = new Programm();
    programm.start();
  }
  public void start(){
    // can now access non-static fields
  }
}

#3 热门回答(27 赞)

static关键字修改类中方法或变量的生命周期。在加载类时创建Astatic方法或变量。未声明为asstatic的方法或变量仅在将类实例化为对象时创建,例如使用newoperator。

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

  • 写入类的源代码,创建模板或模式或图章,然后可以使用
  • 使用new运算符创建一个对象,使用该类将类的实例作为实际对象,然后在完成对象时
  • 在垃圾收集期间销毁回收它所拥有的资源的对象,例如内存。

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

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

因此,你需要创建类的实例作为对象,然后你可以访问尚未使用staticmodifier声明的类的方法和变量。一旦你的Java程序以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
    }
}