我从头开始阅读Java tutorials,我对字段或变量上的static
关键字有疑问。正如Java
所说here:
Class Variables (Static Fields)
类变量是使用static修饰符声明的任何字段;这告诉编译器这个变量只有一个副本存在,无论该类被实例化多少次。定义特定类型自行车齿轮数的字段可以标记为静态,因为从概念上讲,相同数量的齿轮将适用于所有实例。
有了这个,我想如果你有一个对象(在这种情况下,是一个类Bicycle
的一个实例)并且它内部的一个字段是static
那么,如果你是refearing到bicycle1
或bicycle2
,其静态将具有相同值的字段。我错了还是我理解得很好?
我的意思是,如果我有:
Bicycle bicycle1 = new Bicycle();
Bicycle bicycle2 = new Bicycle();
在课程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
在我上面的引文中说:
这告诉编译器存在这个变量的正好一个副本
此副本存储在何处?对象如何访问该副本?该副本何时创建?
答案 0 :(得分:9)
此副本存储在何处?
副本(静态变量)存储在“永久生成”部分中,但如果使用Java8,则“永久生成”部分不再存在。 静态变量和静态方法是反射数据的一部分,反射数据是与类相关的数据,而不是与实例相关的。
对象如何访问该副本?
您创建的每个类(对象)实例都引用了该类。
何时创建此副本?
它是在加载类时在运行时创建的:这是在首次引用类时由JVM的类加载器完成的。
静态变量属于该类,而不属于该类的实例。 你的直觉是正确的 - 无论你创建多少个对象,你只有一个副本。
您可以使用类的名称访问静态变量,如下例所示:
class Static {
static int staticField;
}
public class UseStatic {
public static void main(String[] args) {
System.out.println(Static.staticField);
}
}
静态字段对于创建某种类常量非常有用。
最后,要轻松初始化特定类的静态字段,您可以使用Static Initialization Blocks。
来源:关于java的大学课程,java official documentation
答案 1 :(得分:3)
有了这个,我想如果你有一个对象(在这种情况下,一个 自行车类的实例)和它内部的一个字段 静止然后,独立于你是否正在自行车1或 bicycle2,其静态将具有相同值的字段。我 错了还是我理解得很好?
首次在Java中实例化类时,JVM会创建两件事:
一个实例。将一组非静态字段分配到堆上,用于您创建的每个实例。这些实例字段与所有其他实例分开(并用于表示其对象的状态)。
一个Class对象。 Java中的每个类都有一个且只有一个Class对象......无论创建多少个实例。例如,类String
的Class对象是Class<String>
(表示为文字String.class
)。您可以将类的静态字段视为属于Class对象。 Class对象的生命周期独立于类实例的生命周期;只要JVM进程正在运行,就会存在类对象(因此,它们的静态字段也存在很长时间)。
由于类只有一个Class对象,并且由于类的所有实例共享同一个Class对象,因此类的静态字段由所有存在的类实例共享。
通常,将static
关键字视为“独立于任何实例”意义非常有用:
答案 2 :(得分:1)
java中的静态变量存储在类中,您不需要创建它的实例来访问它们。
class Bicycle{
public static int gears = 7;
//Methods to set and get gears
}
您可以像这样访问静态方法
Bicycle.gears;
所以,只有一个在java上声明的Bicycle类,当你实例化一个类时,它会创建一个自行车实例并声明所有静态属性。
答案 3 :(得分:0)
此副本存储在何处?
静态变量存储在一些静态存储器中(我相信permgen),你不应该为此烦恼。
何时创建此副本?
它们是在第一次访问类时创建的(由类加载器加载)并且永远不会删除(除非卸载类)
对象如何访问该副本?
Instance引用了它的类,而class对它的所有变量都有敬意。如何在内存中放置C结构是特定于实现的细节。
由于静态变量绑定到类而不是实例,因此您甚至不需要实例化类来访问它们。 MyClass.myStaticVar
没问题。