三妹开学了,学的计算机软件编程。她学校离我家很近,坐公交车也就 10 站路的距离, 每逢周末她都会来找我,让我辅导她学习 Java。作为一名拥有十余年编程经验的程序员,再加上父母给我们的这份血缘关系,我觉得义不容辞。
“二哥,今天我们要学习的内容是‘static 关键字’,对吧?”看来三妹已经提前预习了我上次留给她的作业。
“是的,三妹。Java 中的 static 关键字主要用于内存管理。 ”我面带着朴实无华的微笑回答着她,“我们可以将 static 关键字和变量、方法、代码块、内部类一起使用。”
----正儿八经的分割线,正文开始------------
01、什么是静态变量
如果在声明变量的时候使用了 static 关键字,那么这个变量就被称为静态变量。静态变量只在类加载的时候获取一次内存空间,这使得静态变量很节省内存空间。
考虑这样一个 Student 类:
/** * @author 微信搜「沉默王二」,回复关键字 PDF */ public class Student { String name; int age; String school = "郑州大学"; }
假设郑州大学录取了一万名新生,那么在创建一万个 Student 对象的时候,所有的字段(name、age 和 school)都会获取到一块内存。学生的姓名和年纪不尽相同,但都属于郑州大学,如果每创建一个对象,school 这个字段都要占用一块内存的话,就很浪费,对吧?因此,最好将 school 这个字段设置为 static,这样就只会占用一块内存,而不是一万块。
/** * @author 微信搜「沉默王二」,回复关键字 PDF */ public class Student { String name; int age; static String school = "郑州大学"; public Student(String name, int age) { this.name = name; this.age = age; } public static void main(String[] args) { Student s1 = new Student("沉默王二", 18); Student s2 = new Student("沉默王三", 16); } }
s1 和 s2 两个变量存放在栈区(stack),“沉默王二”+18 这个对象和“沉默王三”+16 这个对象存放在堆区(heap),school 这个静态变量存放在静态区,内存关系图如下所示。
再来看另外一个例子,我们创建一个实例变量 count,并且在构造函数中自增。因为实例变量会在创建对象的时候获取内存,因此每一个对象都会有一个 count 的副本, count 的值并不会随着对象的增多而递增。
/** * @author 微信搜「沉默王二」,回复关键字 PDF */ public class Counter { int count = 0; Counter() { count++; System.out.println(count); } public static void main(String args[]) { Counter c1 = new Counter(); Counter c2 = new Counter(); Counter c3 = new Counter(); } }
想一下,count 的值会是几呢?来看一下程序的输出结果。
1
1
1
每创建一个 Counter 对象,count 的值就从 0 自增到 1。那如果 count 是静态的呢?
/** * @author 微信搜「沉默王二」,回复关键字 PDF */ public class StaticCounter { static int count = 0; StaticCounter() { count++; System.out.println(count); } public static void main(String args[]) { StaticCounter c1 = new StaticCounter(); StaticCounter c2 = new StaticCounter(); StaticCounter c3 = new StaticCounter(); } }
这次输出结果又是多少呢?来看一下。
1
2
3
由于静态变量只会获取一次内存空间,所以任何对象对它的修改都会得到保留。