Java static关键字详解
Java static关键字平时用的实在太多了,网上对它的介绍也是非常多的,这里希望通过自己的理解对它进行详细的阐述总结,以加深对该关键字的理解。
static翻译为“静态”,用到static的地方一般都是和类相关的,而不是和对象相关的。在Java中该关键字大体用在5处:静态变量、静态方法、静态代码块、静态内部类、静态导入。
先定个调:被static修饰的变量或者方法可以直接通过类名去访问,而不需要依赖对象去访问,类加载完成后就可以去访问了。
下面将对这几个特性进行详细解释。
静态变量
普通的变量(未用static修饰的)是实例变量,这种变量每个对象都会维护一份,对象创建的时候在堆上分配(对象实例数据中)并初始化,只能通过对象引用拿到该值(getter方法)。
由static修饰的变量称为类变量,这种变量在类加载的时候初始化,并在方法区为该变量分配内存(注意这里只是在方法区的类元数据中为该变量分配了空间,这个空间保存的是对象的引用,而具体的对象分配在堆上),全局只有一个该变量副本,所有对象共享该变量,这样可以节省内存。虽然可以通过对象引用到该变量,但是不推荐这样做,推荐通过类名引用该变量。
静态方法
static修饰的方法(静态方法)和未被static修饰的方法(实例方法)区别在于:
- static方法可以通过类名来调用,当然也可以通过对象来调用(不推荐)。普通方法只能通过对象来调用,因为普通方法是和对象相关的,static方法不依赖对象。
- static方法不可以访问非static的变量,也不能访问this和super,因为static方法不依赖对象,既然没有对象那就谈不上this了。
- static方法不可以访问非static的方法,但是非static方法可以访问static方法。
静态代码块
静态代码块在类加载的时候执行,如果存在多个静态代码块,按顺序执行,每个静态代码块仅会执行一次。例如对于如下示例:
public class Test {
static {
System.out.println("hello static area");
}
}
当虚拟机加载了该类时,将会打印出hello static area
。
静态内部类
普通的类是不允许被声明为static的,但是内部类可以声明为static的。静态内部类定义在类内部、方法外。静态内部类只是定义在一个类的内部,其他的和正常的类没有区别。创建静态类的对象时不需要先创建外部类的对象。关于静态内部类有以下几点需要注意:
静态内部类不能访问外部类的非静态变量,这点不难理解,任何类不能通过类名来访问类的非静态变量,内部静态类也是如此。例如对于以下示例
public class Outer { private Integer x; public static class Inner { public void print() { //此处会报错,因为x是外部类Outer的实例变量,当调用Inner的print方法时,是不需要创建外部类的 //对象的,对象都不存在,肯定访问不了类Outer的实例变量 System.out.println(x); } } }
在
Outer
内部需要Inner
对象直接实例化即可,在Outer外部通过如下方式创建Inner对象Outer.Inner inner = new Outer.Inner()
静态导入
Java 1.5开始支持静态导入,可以直接把其它类的静态变量导入到当前类中,当前类可以直接使用该静态变量而不需要去引用原有的类名。关键字为import static
例如
import static Common.X
看例子:
public class Common {
public static Integer X = 100;
}
import xxx.xxx.Common;
public class Test {
public void test() {
//此处引用Common的静态变量时需要引用Common
int x = Common.X;
}
}
import static xxx.xxx.Common.X;
public class Test {
public void test() {
//静态导入Common的静态变量X后,此处可以直接引用
int x = X;
}
}