非静态variables不能从静态上下文中引用
我已经写了这个testing代码:
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); ^
我如何让我的方法来识别我的类variables?
您必须了解该类和该类的一个实例之间的区别。 如果你在街上看到一辆汽车,即使你看不清哪一种车型,你马上就会知道这是一辆汽车。 这是因为你比较你所看到的类 “汽车”。 该类包含哪些类似于所有的汽车。 把它想成一个模板或一个想法。
同时,你所看到的汽车是“汽车”类的一个例子,因为它具有你期望的所有特性:有人驾驶它,它有一个引擎,车轮。
所以class级说“所有车都有颜色”,实例说“这辆车是红色的”。
在OO世界中,您定义了类并在类中定义了一个Color
types的字段。 当类被实例化时(当你创build一个特定的实例时),内存被保留为颜色,你可以给这个特定的实例一个颜色。 由于这些属性是特定的,它们是非静态的。
静态字段和方法与所有实例共享。 它们是针对类的特定值,而不是特定的实例。 对于方法来说,这通常是全局辅助方法(如Integer.parseInt()
)。 对于领域,它通常是常数(如汽车types,即你有一个有限的集合,不会经常改变)。
为了解决你的问题,你需要实例化一个实例(创build一个对象),这样运行时可以为实例保留内存(否则,不同的实例会覆盖你不想要的)。
在你的情况下,试试这个代码作为起始块:
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()
方法创build它包含的类的实例(听起来很奇怪,但是由于main()
是用类创build的,而不是用实例创build的,所以可以这样做),然后调用实例方法( run()
)。
静态字段和方法连接到类本身,而不是它的实例。 如果你有一个类A,一个'普通'方法b和一个静态方法c并且创build一个类的实例,那么对Ac()
和ab()
的调用是有效的。 方法c()
不知道,哪个实例是连接的,所以不能使用非静态字段。
你的解决scheme是,你使你的领域静态或使你的方法是非静态的。 那么你主要可以看起来像这样:
class Programm { public static void main(String[] args){ Programm programm = new Programm(); programm.start(); } public void start(){ // can now access non-static fields } }
static
关键字修改类中方法或variables的生命周期。 一个static
方法或variables是在加载类时创build的。 没有声明为static
的方法或variables只有在例如使用new
运算符将该类实例化为对象时才会创build。
从广义上来说,一个class级的生命周期是:
- 该类的源代码被写入创build可用于的模板或图案或印章
- 用
new
操作符创build一个对象,使用该类将该类的实例作为实际对象,然后用该对象完成 - 在垃圾回收期间销毁回收它所持有的资源(如内存)的对象。
为了有一个应用程序的初始入口点,Java采用了这样的约定:Java程序必须有一个类,该类包含一个带有约定或特殊名称的方法。 这个特殊的方法叫做main()
。 由于无论包含main方法的类是否已被实例化,方法都必须存在,因此必须使用static
修饰符声明main()
方法,以便一旦加载类, main()
方法就可用。
结果是,当你通过命令行(例如java helloworld
启动Java应用程序时,会发生一系列的操作。 首先启动并初始化Java虚拟机。 接下来将包含已编译的Java代码的helloworld.class文件加载到Java虚拟机中。 然后,Java虚拟机将在名为main(String [] args)
的helloworld
类中查找一个方法。 这个方法必须是static
所以即使这个类没有被实例化为一个对象也是存在的。 Java虚拟机不通过从类创build对象来创build类的实例。 它只是加载类,并开始在main()
方法执行。
所以你需要创build一个类的实例作为一个对象,然后你可以访问这个类的方法和variables,这些方法和variables还没有用static
修饰符声明。 一旦Java程序启动了main()
函数,您就可以使用任何具有static
修饰符的variables或方法,因为它们是被加载的类的一部分。
然而,在main()
方法之外,那些没有static
修饰符的类的variables和方法只能在main()
方法中创build一个类的实例之前使用。 创build对象后,可以使用对象的variables和方法。 Java编译器在编译时会捕获未经过类的对象而使用没有static
修饰符的类的variables和方法,并将其标记为错误。
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 } }
让我们先分析一下你的程序。在你的程序中,你的第一个方法是main()
,记住它是静态方法…然后你声明该方法的局部variables(compareCount,low,high等等)。 这个variables的范围只是声明的方法,不pipe它是一个静态方法还是非静态方法。 所以你不能在这个方法之外使用这些variables。 这是你所犯的基本错误。
然后我们来到下一点。 你告诉静态正在杀死你 (它可能会杀死你,但它只是给你的程序生命!!)首先,你必须了解基本的东西。 *静态方法只调用静态方法,只使用静态variables。 *静态variables或静态方法不依赖于该类的任何实例。 (即如果你改变任何状态的静态variables,它将反映在类的所有对象)*因此,你把它称为类variables或类方法。 还有更多关于“静态”关键字的内容。 我希望现在你明白了。 首先更改variables的范围并将其声明为静态(可以在静态方法中使用它)。
对你的build议是:你误解了variables和静态function的范围的想法。 得到清楚的想法。
非常基本的事情是静态variables或静态方法是在课堂上。 类级别的variables或方法在实例级别的方法或variables之前加载。显然,没有加载的东西不能被使用。 所以java编译器不会让在运行时处理的东西在编译时解决。 这就是为什么它给你错误非静态的东西不能从静态上下文中引用。 您只需要阅读“类级别范围”,“实例级别范围”和“本地范围”。
为了能够从静态方法访问它们,它们需要是静态成员variables,如下所示:
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 { ...
现在,您可以在方法中添加/使用实例
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(); } }
我会尽力向你解释静态的东西。 首先,静态variables不属于该类的任何特定实例。 他们被认同与class级的名字。 静态方法再次不属于任何特定的实例。 他们只能访问静态variables。 假设你调用MyClass.myMethod(),myMethod是一个静态方法。 如果你在方法内部使用非静态variables,地球上的地狱它会知道使用哪个variables? 这就是为什么你可以使用静态方法只有静态variables。 我再说一遍,他们不属于任何特定的情况。
-
首先要了解一个类的实例和类本身之间的区别。 一个类对某些属性进行build模,并在这些属性的上下文中对整个行为进行build模。 一个实例将为这些属性定义特定的值。
-
绑定到static关键字的任何东西都可以在类的上下文中使用,而不是在类的实例的上下文中使用
-
作为上述的必然结果
- 方法内的variables不能是静态的
- 静态字段和方法必须使用类名调用,例如MyProgram7.main(…)
-
静态字段/方法的生命周期等同于应用程序的生命周期
例如说,汽车有财产的颜色,并展示行为的“运动”。 这辆车的一个例子是一辆红色大众甲壳虫,时速25公里。
现在,车辆的静态属性将是道路上的车轮(4)的数量,并且这将适用于所有车辆。
HTH
对于所有初学者来说,解释静态关键字是有点不同的。
当你更多的使用类和对象的时候,你会清楚地知道它。
| * | 静态:可以使用类名称来调用静态项目
如果你在代码中观察,一些函数被直接调用类名称
NamCls.NamFnc(); System.out.println();
这是因为NamFnc和println将在它们之前使用关键字静态声明。
| * | 非静态:可以使用类variables调用非静态项目
如果它不是静态的,你需要一个类的variables,
在类variables和后面放点
然后调用函数。
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); } } }
它是ClassLoader负责加载类文件。让我们看看当我们写我们自己的类时会发生什么。
例1:
class StaticTest { static int a; int b; int c; }
现在我们可以看到类“StaticTest”有3个字段,但实际上不存在b,c成员variables。但是为什么? 好吧,看看。 这里的b,c是实例variables。因为实例variables在创build对象时获取内存。 所以在这里,B,C还没有得到任何记忆。 这就是为什么不存在b,c。 所以只有一个存在。 对于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(),所以编译时发生错误。