static
介绍
我们希望无论是否产生多少对象,某些特定的数据在内存空间里只有一份
- static可以称作是静态或者全局
- 可以修饰的范围:成员变量和方法及代码块
- 独立于任何实例化对象,不依赖于对象可以直接用类进行访问
- 直接上案列:
(1)成员变量static
public class Person {
String name;
static int age;
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "zhangsan";
p1.age = 10;
Person p2 = new Person();
p2.name = "lisi";
p2.age = 12;
System.out.println(p1);
System.out.println(p2);
}
}
那么这里结果显而易见:p2的age赋值后影响了p1的age,对它有了干扰,给age属性加了static关键字之后,Person对象就不再拥有age属性了,age属性会统一交给Person类去管理,即多个Person对象只会对应一个age属性,一个对象如果对age属性做了改变,在这个类中的其他的对象都会受到影响,而且在jvm中它是和类(person)放在一起的,存放在静态存储区,既不在stack中也不在heap中,并且是在类加载前完成了赋值初始化操作,其实在实际中通常没这么用
所以由此我们能注意到他们的区别静态变量和非静态变量的区别:
-
静态变量被所有对象共享,在内存中只有一个副本,在类初次加载的时候才会初始化
-
非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响
那么我们实在是希望属性共享怎么办:
public class Person {
private static int count = 0;
int id;
String name;
int age;
public Person() {
id = ++count;
}
public String toString() {
return "Id:" + id + ", Name:" + name + ", Age:" + age;
}
public static void main(String[] args) {
Person p1 = new Person();
p1.name = "zhangsan";
p1.age = 10;
Person p2 = new Person();
p2.name = "lisi";
p2.age = 12;
System.out.println(p1);
System.out.println(p2);
}
/**Output
* Id:1, Name:zhangsan, Age:10
* Id:2, Name:lisi, Age:12
*/
}
这里我们设置了id来区别main中的对象实现了属性的这样一个共享,除此之外还记录了对象的数量
(2)成员方法的static
首先我们知道,相比于修饰成员属性,修饰成员方法对于数据的存储上面并没有多大的变化,只是有一个小优势防止多次new造成的内存开销,和书写繁琐
public class PrintHelper {
public static void print(Object o){
System.out.println(o);
}
}
但是他也有局限,使得它经常在帮助类中使用,一个静态修饰的static中不能使用非static修饰的成员变量和方法,这个其实很好理解,因为static修饰的方法是属于类的,如果去直接使用对象的成员变量,它会不知所措(不知该使用哪一个对象的属性)
总结
最后说明一下他们在jvm中的加载顺序:,当我们new一个对象时,static修饰的成员变量首先被初始化,随后是普通成员,最后调用Person类的构造方法完成初始化。也就是说,在创建对象时,static修饰的成员会首先被初始化(意思是创建对象之前完成),而且我们还可以看到,如果有多个static修饰的成员,那么会按照他们的先后位置进行初始化
static是java中非常重要的一个关键字,而且它的用法也很丰富,主要有四种用法:
- 用来修饰成员变量,将其变为类的成员,从而实现所有对象对于该成员的共享;
- 用来修饰成员方法,将其变为类方法,可以直接使用“类名.方法名”的方式调用,常用于工具类;
- 静态块用法,将多个类成员放在一起初始化,使得程序更加规整,其中理解对象的初始化过程非常关键;
- 静态导包用法,将类的方法直接导入到当前类中,从而直接使用“方法名”即可调用类方法,更加方便。
- 由于类只会加载一次,所以static成员也只加载一次,生命周期相同
- 存在方法区的静态域中
- 静态方法中只能有静态的属性和方法,非静态方法中既可以有静态也可以有非静态
- 静态方法中不能有this和super