静态:
static :用于修饰成员的静态关键字
static是什么?
成员修饰符。
有什么特点:
1.被静态修饰的成员,可以直接被类名所调用。
2.静态成员优先于对象存在。//因为静态成员是伴随着类加载进内存的,而创建对象这一操作是在类加载进内存之后存在的
3.静态成员随着类的加载而加载,随着类的消失而消失。静态成员生命周期很长
静态方法:
什么时候方法需要静态修饰呢?
该方法没有访问过对象中的属性,就需要用静态修饰
静态变量:
static String country = "CN";
静态变量以及静态方法在内存中实际上是存储在一个叫方法区的内存区域中的。
注意事项:
1.静态方法只能访问静态成员,不能访问非静态成员,这就是静态方法的局限性。
2.静态的方法中不能出现this或者super关键字。
3.主方法是静态的。
static 怎么用?
直接用于修饰成员。
什么时候用?
成员变量:如果数据在所有对象中都是一样的,直接静态修饰。
成员方法:如果方法中没有访问过对象中的属性数据,那么该方法就定义成静态的。
例子一枚:
class Person
{
private String name;
private int age;
static String country = "CN";
Person(String name,int age){
this.name = name;
this.age = age;
}
public void show(){
System.out.println("name="+name+",age="+age);
}
public static void sleep(){
System.out.println("呼呼");
}
}
class StaticDemo
{
public static void main(String args[]){
Person p = new Person("Lisi",21);
p.show();
Person.sleep();
}
}
简单的分析一下上面代码运行时的内存图解:
1.javac 对源文件进行编译,产生两个字节码文件Person.class StaticDemo.class
2.java 调用虚拟机运行程序。
一:
虚拟机一运行先找到含有main方法的类(StaticDemo类),于是StaticDemo类加载进了内存的方法区中,该类中的StaticDemo(){}构造方法也随着StaticDemo类进入了方法区中,并且与StaticDemo类处于同一片区域;而StaticDemo类中的public static void main(){}方法由于是静态成员,所以main(){}方法进入了方法区的静态代码区(Static Code),至此,StaticDemo类中的所有成员都已加载进内存。
二:
紧接着,main(){}方法压栈(进栈)
开始执行main方法中的语句:Person p = new Person("Lisi",21);
先执行等式右边的语句:
要new一个Person对象,此时Person类才加载进内存(注意:这个时候Person类才进内存哦)
与StaticDemo类的进内存方式同理,Person类在内存的方法区中开辟一片属于Person的空间,Person类中的成员name,age,Person(name,age){},show(){}也进入了该区域,而被static修饰的country变量,被static修饰的sleep(){}方法则进入了方法区中的静态代码区(Static Code)区,至此,Person类中的所有成员都已加载进内存。
三:
然后要new Person对象,所以需要Person类的构造方法,Person(String name,int age){}构造方法压栈,虚拟机调用该方法在堆内存中创建了一个Person对象,并为其分配了地址0x98,默认初始化name = null,age = 0;再显示初始化this.name = "Lisi" ,this.age = 21,此时对象已经创建完毕(等式右边的语句结束)Person(String name,int age){}构造方法弹栈(出栈)。
四:
再执行等式左边的语句:创建一个Person类型的变量p,将Person对象的地址赋值给p(注意:p并不是对象哦,他只是Person对象的一个引用,换句话说p变量中存储的只是Person对象的地址,真正的Person对象是存储在堆内存中的)
第一句话解释完毕...
------------------------------------------分割线-----------------------------------------------
下面解释第二句:p.show();
p携带着Person对象的地址就找到了其所属的Person类(注意:是在方法区中找到的),然后p就调用了show()方法,show()方法压栈,开始执行show()方法中的语句,show()方法中含有this(注意:一般方法都会携带this,那啥是不一般的方法呢?请继续往后看...)this就找到了存在于堆内存中的Person对象的name和age值,于是乎,Lisi和21就打印到了屏幕上,于是show()方法中的语句执行完毕,show()方法弹栈。
第二句话解释完毕...
------------------------------------------分割线-----------------------------------------------
下面解释最后一句:Person.sleep();
凡是进行类名.方法名()调用,都到方法区的静态区中去找,找到sleep()后,sleep()压栈,执行static sleep()方法中(这个sleep方法就不一般,静态嘛)的语句,在屏幕上打印“呼呼”,sleep()方法内的语句执行完毕sleep()方法弹栈。
第三句话解释完毕...
到目前为止,main()方法中的语句全部执行完毕,main()方法弹栈,程序结束。
静态变量以及静态方法在内存中实际上是存储在一个叫方法区的内存区域中的。