一、static关键字的特点:
生命周期
一般变量随对象的创建而创建,随对象被回收被回收
静态方法和变量随着类的加载被创建,随着类的消失而消失
调用方式
成员变量通过对象名调用
静态变量通过类名(推荐)调用,并被所有对象共享
数据存储位置不同
成员变量存在堆内存的对象中
静态变量存在方法区钟
1. static修饰成员方法
static修饰的方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方法来说,是没有this的,因为它不依附于任何对象,既然都没有对象,就谈不上this了。并且由于这个特性,在静态方法中不能访问类的非静态成员变量和非静态成员方法,因为非静态成员方法/变量都必须依赖具体的对象才能够被调用。
但是要注意的是,虽然在静态方法中不能访问非静态成员方法和非静态成员变量,但是在非静态成员方法中是可以访问静态成员方法/变量的。例如:
在上面的代码中,由于print2方法是独立于对象存在的,可以直接用类名调用。
假如说可以在静态方法中访问非静态方法/变量的话,那么如果在main方法中有下面一条语句:
MyObject.print2();
此时对象都没有,str2根本就不存在,所以就会产生矛盾了。同样对于方法也是一样,由于你无法预知在print1方法中是否访问了非静态成员变量,所以也禁止在静态成员方法中访问非静态成员方法。
而对于非静态成员方法,它访问静态成员方法/变量显然是毫无限制的。
因此,如果说想在不创建对象的情况下调用某个方法,就可以将这个方法设置为static。我们最常见的static方法就是main方法,至于为什么main方法必须是static的,现在就很清楚了。因为程序在执行main方法的时候没有创建任何对象,因此只有通过类名来访问。
2. static修饰成员变量
static修饰的变量也称为静态变量,静态变量和非静态变量的区别是:静态变量被所有对象共享,在内存中只有一个副本,它当且仅当在类初次加载时会被初始化。而非静态变量是对象所拥有的,在创建对象的时候被初始化,存在多个副本,各个对象拥有的副本互不影响。
static成员变量的初始化顺序按照定义的顺序进行初始化。
3. static修饰代码块
static关键字还有一个比较重要的作用就是用来形成静态代码块以优化程序性能。static块可以置于类中的任何地方,类中可以有多个static块。在类初次被加载的时候,会按照static块的顺序来依次执行每个static块,并且只会执行一次。
static块可以优化程序性能,是因为它的特性:只会在类被初次加载的时候执行一次。如下:
class Person{
private Date birthDate;
public Person(Date birthDate) {
this.birthDate = birthDate;
}
boolean isBornBoomer() {
Date startDate = Date.valueOf("1946");
Date endDate = Date.valueOf("1964");
return birthDate.compareTo(startDate)>=0 && birthDate.compareTo(endDate) < 0;
}
}
isBornBoomer是用来判断一个人是否是1946-1964年出生的,而每次isBornBoomer被调用的时候,都会生成startDate和birthDate两个对象,造成了空间浪费,如果改成下面这样效率会更高:
class Person {
private Date birthDate;
private static Date startDate, endDate;
static {
startDate = Date.valueOf("1946");
endDate = Date.valueOf("1964");
}
public Person(Date birthDate) {
this.birthDate = birthDate;
}
boolean isBornBoomer() {
return birthDate.compareTo(startDate) >= 0 && birthDate.compareTo(endDate) < 0;
}
}
因此,很多时候会将一些只需要进行一次的初始化操作都放在static代码块中进行。
二、static关键字的误区
1. 与C/C++中的static不同,Java中的static关键字不会影响到变量的变量或者方法的作用域。在Java中能够影响到访问权限的只有private、public、protected这几个关键字。
示例如下:
提示错误,说明static关键字并不会改变变量和方法的访问权限。
2. 虽然对于静态方法来说没有this,但是我们在非静态方法中能够通过this访问静态方法成员变量。
如下:
public class Test {
static int value = 11;
public static void main(String[] args) {
new Test().printValue();
}
private void printValue() {
int value = 22;
System.out.println(this.value);
}
}
输出的结果是:11
这里的this表示的是当前对象,那么通过new Test()来调用printValue的话,当前对象就是通过new Test()生成的对象。而static变量是被对象所享有的,因此在printValue中的this.value的值毫无疑问是11。在printValue方法内部的value是局部变量,根本不可能与this关联,所以输出11。需要记住的是:静态成员变量虽然独立于对象,但是不代表不可以通过对象去访问,所有的静态方法和静态变量都可以通过对象访问(只要权限足够)。
3. 在C/C++中static关键字是可以作用于局部变量的,但是在Java中是不允许使用static修饰局部变量的。这是Java语法的规定。
————————————————
版权声明:本文为CSDN博主「LiuWang_1122」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yubujian_l/article/details/86498238