static关键字如何在Java中工作?
我正在从头开始阅读Java教程 ,我对字段或变量上的static
关键字有疑问。 正如Java
在这里所说:
Class Variables (Static Fields)
类变量是使用static修饰符声明的任何字段; 这告诉编译器这个变量只有一个副本存在,无论该类被实例化多少次。 定义特定种类的自行车的齿轮数量的区域可以标记为静态,因为从概念上讲,相同数量的齿轮将适用于所有情况。
有了这个,我想如果你有一个对象(在这种情况下,是一个类Bicycle
一个实例)和它内部的一个字段,那么它是static
,如果你正在为bicycle1
或者bicycle2
,它的静止字段将具有相同的价值。 我错了还是我理解得很好?
我的意思是,如果我有:
Bicycle bicycle1 = new Bicycle(); Bicycle bicycle2 = new Bicycle();
在class级Bicycle
我有一个static
字段,如:
class Bicycle{ static int gears; //Methods to set and get gears }
在bicycle1
我将齿轮的值设置为7:
bicycle1.setGears(7);
那么如果我试着在bicycle2
获得齿轮的值,我应该得到与我在bicycle1
设置的相同的值,对吗?
System.out.println(bicycle2.getGears()); //7
好吧,这就是我怀疑的地方,因为正如Java
在上面提到的引用中所说:
这告诉编译器存在这个变量的正好一个副本
这个副本存放在哪里? 对象如何访问该副本? 什么时候创建这个副本?
这个副本存放在哪里?
副本(静态变量)存储在Permanent Geneneration部分中,但如果使用Java8,则永久生成部分不再存在。 静态变量以及静态方法是reflection数据的一部分 – 类相关数据而非实例相关。
对象如何访问该副本?
您创建的每个类(对象)实例都具有对该类的引用。
什么时候创建这个副本?
它是在加载类时在运行时创建的:这是在首次引用类时由JVM的类加载器完成的。
静态变量属于类,而不属于类的实例。 所以,你的直觉是正确的,无论你创造了多少个对象,你只有一个副本。
您可以使用类的名称访问静态变量,如下例所示:
class Static { static int staticField; } public class UseStatic { public static void main(String[] args) { System.out.println(Static.staticField); } }
静态字段对于创建某种类常量很有用。
最后,要轻松初始化特定类的静态字段,可以使用静态初始化块 。
资料来源 :关于java的大学课程, java官方文档
有了这个,我想如果你有一个对象(在这种情况下,是一个类Bicycle的一个实例)和它内部的一个字段,那么它是静态的,如果你正在为自行车1或者自行车2加油,它的静止字段将具有相同的价值。 我错了还是我理解得很好?
当您第一次在Java中实例化一个类时,JVM会创建两件事 :
-
一个实例。 对于您创建的每个实例,将一组非静态字段分配到堆上。 这些实例字段与所有其他实例分开(并用于表示其对象的状态)。
-
一个Class对象。 Java中的每个类都有一个且只有一个Class对象……无论创建多少个实例。 例如,类
String
的Class对象是Class
(它表示为String.class
的文字)。 您可以将类的静态字段视为属于Class对象。 Class对象的生命周期独立于类实例的生命周期; 只要JVM进程正在运行,就存在类对象(因此,它们的静态字段也存在很长时间)。
由于类只有一个Class对象,并且由于类的所有实例共享同一个Class对象,因此类的静态字段由所有存在的类实例共享。
通常,将static
关键字视为“独立于任何实例”是有用的:
- 静态字段属于Class对象,而不属于任何实例
- 静态方法通过Class对象调用,不能直接访问任何实例
- 静态成员类实例不依赖于任何其他实例
java中的静态变量存储在类中,您不需要创建它的实例来访问它们。
class Bicycle{ public static int gears = 7; //Methods to set and get gears }
您可以像这样访问静态方法
Bicycle.gears;
因此,在java上只声明了一个Bicycle类,当你实例化一个类时,它会创建一个自行车实例并声明所有静态属性。
这个副本存放在哪里?
静态变量存储在一些静态存储器中(我相信permgen),你不应该为此烦恼。
什么时候创建这个副本?
它们是在第一次访问类(由类加载器加载)时创建的,并且从不删除(除非卸载类)
对象如何访问该副本?
实例引用了它的类,类对所有变量都有敬意。 如何在内存中放置C结构是特定于实现的细节。
由于静态变量绑定到类而不是实例,因此您甚至不需要实例化类来访问它们。 MyClass.myStaticVar
。