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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2559527/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 09:15:16  来源:igfitidea点击:

Non-static variable cannot be referenced from a static context

javavariablescompiler-errorsnon-static

提问by Greg

I've written this test code:

我写了这个测试代码:

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

But it gives the following error:

但它给出了以下错误:

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

How do I get my methods to recognize my class variables?

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

回答by Nick Moore

To be able to access them from your static methods they need to be static member variables, like this:

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

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 {
  ...

回答by Aaron Digulla

You must understand the difference between a class and an instance of that class. If you see a car on the street, you know immediately that it's a car even if you can't see which model or type. This is because you compare what you see with the class"car". The class contains which is similar to all cars. Think of it as a template or an idea.

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

At the same time, the car you see is an instance of the class "car" since it has all the properties which you expect: There is someone driving it, it has an engine, wheels.

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

So the class says "all cars have a color" and the instance says "this specific car is red".

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

In the OO world, you define the class and inside the class, you define a field of type Color. When the class is instantiated (when you create a specific instance), memory is reserved for the color and you can give this specific instance a color. Since these attributes are specific, they are non-static.

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

Static fields and methods are shared with all instances. They are for values which are specific to the class and not a specific instance. For methods, this usually are global helper methods (like Integer.parseInt()). For fields, it's usually constants (like car types, i.e. something where you have a limited set which doesn't change often).

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

To solve your problem, you need to instantiate an instance (create an object) of your class so the runtime can reserve memory for the instance (otherwise, different instances would overwrite each other which you don't want).

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

In your case, try this code as a starting block:

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

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
}

The new main()method creates an instance of the class it contains (sounds strange but since main()is created with the class instead of with the instance, it can do this) and then calls an instance method (run()).

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

回答by Petar Minchev

I will try to explain the static thing to you. First of all static variables do not belong to any particular instance of the class. They are recognized with the name of the class. Static methods again do not belong again to any particular instance. They can access only static variables. Imagine you call MyClass.myMethod() and myMethod is a static method. If you use non-static variables inside the method, how the hell on earth would it know which variables to use? That's why you can use from static methods only static variables. I repeat again they do NOT belong to any particular instance.

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

回答by Mnementh

Static fields and methods are connected to the class itself and not its instances. If you have a class A, a 'normal' method b, and a static method c, and you make an instance aof your class A, the calls to A.c()and a.b()are valid. Method c()has no idea which instance is connected, so it cannot use non-static fields.

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

The solution for you is that you either make your fields static or your methods non-static. You main could look like this then:

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

class Programm {

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

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

回答by Everyone

  • The first thing is to know the difference between an instance of a class, and the class itself. A class models certain properties, and the behaviour of the whole in the context of those properties. An instance will define specific values for those properties.

  • Anything bound to the static keyword is available in the context of the class rather than in the context of an instance of the class

  • As a corollary to the above

    1. variables within a method can not be static
    2. static fields, and methods must be invoked using the class-name e.g. MyProgram7.main(...)
  • The lifetime of a static field/method is equivalent to the lifetime of your application

  • 首先要知道类的实例和类本身之间的区别。类对某些属性以及在这些属性的上下文中的整体行为进行建模。一个实例将为这些属性定义特定的值。

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

  • 作为上述的推论

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

E.g. Say, car has the property colour, and exhibits the behaviour 'motion'. An instance of the car would be a Red Volkswagen Beetle in motion at 25kmph.

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

Now a static property of the car would be the number of wheels (4) on the road, and this would apply to all cars.

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

HTH

HTH

回答by Suseendran.P

Let's analyze your program first.. In your program, your first method is main(), and keep it in mind it is the static method... Then you declare the local variable for that method (compareCount, low, high, etc..). The scope of this variable is only the declared method, regardless of it being a static or non static method. So you can't use those variables outside that method. This is the basic error u made.

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

Then we come to next point. You told static is killing you. (It may be killing you but it only gives life to your program!!) First you must understand the basic thing. *Static method calls only the static method and use only the static variable. *Static variable or static method are not dependent on any instance of that class. (i.e. If you change any state of the static variable it will reflect in all objects of the class) *Because of this you call it as a class variable or a class method. And a lot more is there about the "static" keyword. I hope now you get the idea. First change the scope of the variable and declare it as a static (to be able to use it in static methods).

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

And the advice for you is: you misunderstood the idea of the scope of the variables and static functionalities. Get clear idea about that.

给您的建议是:您误解了变量和静态功能范围的概念。对此有一个清晰的认识。

回答by Ajay Bhojak

The very basic thing is static variables or static methods are at class level. Class level variables or methods gets loaded prior to instance level methods or variables.And obviously the thing which is not loaded can not be used. So java compiler not letting the things to be handled at run time resolves at compile time. That's why it is giving you error non-static things can not be referred from static context. You just need to read about Class Level Scope, Instance Level Scope and Local Scope.

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

回答by Sainath Patwary karnate

Now you can add/use instances with in the method

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

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

回答by Richard Chambers

The statickeyword modifies the lifecycle of a method or variable within a class. A staticmethod or variable is created at the time a class is loaded. A method or variable that is not declared as staticis created only when the class is instantiated as an object for example by using the newoperator.

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

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

广义而言,类的生命周期是:

  1. the source code for the class is written creating a template or pattern or stamp which can then be used to
  2. create an object with the newoperator using the class to make an instance of the class as an actual object and then when done with the object
  3. destroy the object reclaiming the resources it is holding such as memory during garbage collection.
  1. 编写该类的源代码,创建一个模板、模式或图章,然后可用于
  2. new使用该类的运算符创建一个对象,将该类的实例作为实际对象,然后在完成该对象后
  3. 在垃圾回收期间销毁对象以回收其持有的资源,例如内存。

In order to have an initial entry point for an application, Java has adopted the convention that the Java program must have a class that contains a method with an agreed upon or special name. This special method is called main(). Since the method must exist whether the class containing the main method has been instantiated or not, the main()method must be declared with the staticmodifier so that as soon as the class is loaded, the main()method is available.

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

The result is that when you start your Java application by a command line such as java helloworlda series of actions happen. First of all a Java Virtual Machine is started up and initialized. Next the helloworld.class file containing the compiled Java code is loaded into the Java Virtual Machine. Then the Java Virtual Machine looks for a method in the helloworldclass that is called main(String [] args). this method must be staticso that it will exist even though the class has not actually been instantiated as an object. The Java Virtual Machine does not create an instance of the class by creating an object from the class. It just loads the class and starts execution at the main()method.

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

So you need to create an instance of your class as an object and then you can access the methods and variables of the class that have not been declared with the staticmodifier. Once your Java program has started with the main()function you can then use any variables or methods that have the modifier of staticsince they exist as part of the class being loaded.

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

However, those variables and methods of the class which are outside of the main()method which do not have the staticmodifier can not be used until an instance of the class has been created as an object within the main()method. After creating the object you can then use the variables and methods of the object. An attempt to use the variables and methods of the class which do not have the staticmodifier without going through an object of the class is caught by the Java compiler at compile time and flagged as an error.

然而,在类的实例被创建为方法内的对象之前,不能使用那些在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
    }
}

回答by Newaz Sharif Amit

It is ClassLoader responsible to load the class files.Let's see what happens when we write our own classes.

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

Example 1:

示例 1:

class StaticTest {

      static int a;
      int b;
      int c;
}

Now we can see that class "StaticTest" has 3 fields.But actually there is no existence of b,c member variable.But why ???. OK Lest's see. Here b,c are instance variable.Since instance variable gets the memory at the time of object creation. So here b,c are not getting any memory yet. That's why there is no existence of b,c. So There is only existence of a. For ClassLoader it has only one information about a. ClassLoader yet not recognize b,c because it's object not instantiated yet.

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

Let's see another example: Example 2:

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

class StaticTest {

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


      public static void main(String []cmd) {

             display();       
      }

}

Now if we try to compile this code compiler will give CE error. CE: non-static method display() cannot be referenced from a static context.

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

Now For ClassLoader it looks like:

现在对于 ClassLoader 它看起来像:

class StaticTest {

      public static void main(String []cmd) {

             display();       
      }

}

In Example 2 CE error is because we call non static method from a static context. So it is not possible for ClassLoader to recognize method display() at compile time.So compile time error is occurred.

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