static 内存图
程序示例:
Javabean 类:
public class Student {
String name;
int age;
static String teacherName;
public void show() {
System.out.println(name + "..." + age + "..." + teacherName);
}
}
测试类:
public class staticDemo1 {
public static void main(String[] args) {
Student.teacherName = "xiaoming";
Student s1 = new Student(); // 第一个对象
s1.name = "zhangsan";
s1.age = 23;
s1.show();
Student s2 = new Student(); // 第二个对象
s2.show();
}
}
执行结果:
zhangsan...23...xiaoming
null...0...xiaoming
第一步, 先执行 main() 方法, main() 方法先进栈.
第二步, 执行语句 Student.teacherName = "xiaoming";
这样一来就用到了 Student 这个类, 所以要把这个类的字节码文件加载到方法区, 并创建了一个单独存放静态变量的空间, 可以将这个空间称为静态存储位置或静态区. 将字节码文件加载到方法区中后, 静态区就出现了.
JDK 8 之前, 静态区是在方法区里面的, 到了 JDK 8 之后, 就将其放到了堆空间中. 在静态区中就存放着这个类的所有的静态变量. 静态变量的默认初始化值和普通成员变量的规则相同.
此时在内存中尚无对象, 因为代码还没有执行到 new 关键字. 只有 new 关键字执行了, 在内存中才有对象. 因此静态变量是优先于对象而存在的, 是随着类的加载而加载的. 类一旦加载进了内存, 这个静态变量就会出现. 只要是用 static 修饰的, 不限于成员变量, 都随着类的加载而加载, 优先于对象出现在内存中.
第三步, 执行 Student s1 = new Student();
等号左边在 main() 方法中定义了一个变量 s1, 等号右边在堆内存开辟了一个空间, 这个空间存储了所有的非静态的成员变量. 这个空间的地址被赋值给了变量 s1. 如果想要通过 s1 去访问静态变量 teacherName, 就要去静态区去找对应的变量.
第四步, 执行 s1.name = "zhangsan"; 和 s1.age = 23;
第五步, 执行 s1.show();
此时, show() 方法被加载进栈. show() 方法的调用者是 s1. 执行完毕之后 show() 方法出栈.
第六步, 执行 Student s2 = new Student();
等号左边在 main() 方法中定义了一个变量 s2, 等号右边在堆内存又开辟了一个新的空间, 这个空间存储了所有的非静态的成员变量. 这个空间的地址被赋值给了变量 s2. 如果想要通过 s1 去访问静态变量 teacherName, 就要去静态区去找对应的变量.
第七步, 执行 s2.show();
此时, show() 方法被加载进栈. show() 方法的调用者是 s2. 执行完毕之后 show() 方法出栈.
静态区中的变量是对象共享的, 在内存中只有一份, 谁要用谁去拿. 非静态区的变量, 是每一个对象所独有的, 在每一个对象内单独存放.
另一个示例:
先执行 main 方法, main 方法进栈, 然后执行第一条语句 Student.teacherName = "阿玮老师";, 用到了 Student 类, 则将 Student 类的字节码文件 Student.class 加载到方法区中, 这里面有所有的成员变量和成员方法, 在 JDK 7 之前, 不管是静态的还是非静态的, 都在方法区中, 在 JDK 7 之后, 将静态的成员变量移动到了堆内存的静态区中.
静态成员变量的初始化规则没有改变, String 类型首先初始化为 null. 在第一条语句中这个静态变量又被赋值为了 "阿玮老师", 替换了初始值 null.
注意, 静态方法并不在静态区中, 还是在方法区中, 和非静态的成员变量和成员方法都在一起, 只有静态成员变量被移动到了静态区中.
然后开始执行第二行代码 Student.method();. 因此, method 方法进栈. method 方法是用类名 Student 来调用的, 因此会去静态区中寻找这个方法需要的东西, 此处 method 方法需要 name 和 teacherName. 然而, name 并不存在于静态区中, 因此调用失败.
静态方法不能调用非静态方法:
非静态的可以访问所有:

浙公网安备 33010602011771号