static静态修饰符
- static修饰三个内容:成员变量,方法,代码块
- 被static修饰的成员变量被称为静态成员,也称为类成员,不用static修饰的成员称为实例成员。
下面是一个学生类,我写了一个普通成员变量和一个静态成员变量 :
public class Student {
String name;//成员变量
static String sex;//静态成员变量
public static void main(String[] args) {
}
}
接着我早测试类中对上面两个变量进行调用,出现一个很有意思的事情
public class Text01 {
public static void main(String[] args) {
Student stu1=new Student();
stu1.name="张三";//调用成员变量,没什么问题。
stu1.sex="女";//调用静态成员变量,你会发现调不出来,现在是强行写上去
Student stu2=new Student();
stu2.name="李四";//调用成员变量,没什么问题
stu2.sex="男";//调用静态成员变量,你会发现调不出来,现在是强行写上去
// 打印成员变量,你发现没什么问题,打印很正常
System.out.println(stu1.name);
System.out.println(stu2.name);
// 打印静态成员变量,你会发现打印出来的值不太对。
System.out.println(stu1.sex);
System.out.println(stu2.sex);
}
}
大家看结果惊叹是这样的:
张三
李四
男 //程序直接忽视我们设置的性别开始胡来了!!
男
让我们用内存图看看到底发生了什么吧
*任何程序开始前经过加载都会先加载到方法区中,现在方法区其实是有当前两个类的。也就是我们的学生类和测试类。
接下来我们的程序该运行测试类中的main方法了,就会咋栈中给main方法开辟一块栈内存。
接着 Student stu1=new Student();,当new一个对象的时候,就会在堆内存给这个new的对象开辟一个堆内存。堆内存的地址假设为0x111,然后吧这个地址返回给stu1,Student这个类中有一个普通成员变量,初始化为null.
接着程序走 stu1.name=“张三”;此时就会根据stu1的地址找到堆内存相应的地址,再找到name这个属性,把它赋值为张三。
接下来该执行 stu1.sex=“女”;但是这是个静态的变量,是在学生类中被static修饰的静态成员。
- 静态成员变量保存在方法区中!!!而且在方法区中只有一份,因为只定义了这一个静态成员变量。
所以当执行这一步的时候。请看:
stu1是指向堆的地址,但是在这个地址中是找不到sex这个成员的,所以系统就会去找这个地址所在的类,就会找到学生类Student类。把对应的sex改成女
同理,我们程序继续往下走
Student stu2=new Student();
stu2.name="李四";//调用成员变量,没什么问题
stu2.sex="男";
如下图:
stu1.sex=“女”;和stu2.sex=“男”;修改的都是方法区的这一个sex静态成员,执行完后sex这个静态成员的最终的值是“男”。
所以程序执行完打印
// 打印成员变量,你发现没什么问题,打印很正常
System.out.println(stu1.name);
System.out.println(stu2.name);
// 打印静态成员变量,你会发现打印出来的值不太对。
System.out.println(stu1.sex);
System.out.println(stu2.sex);
结果才会是这样:
张三
李四
男
男