Static
Java编程思想:一旦将什么东西设为static,数据或方法就不会同那个类的任何对象实例联系到一起。
特点:随着类的加载而加载,随着类的销毁而销毁。
作用:可以修饰成员变量,代码块,方法,内部类以及导包操作。
1. 修饰成员变量
如果用static来修饰类成员变量,那么这个变量将会被该类所有实例对象所共享,我们从内存角度来解释一下,根据类加载机制,我们可以知道,静态成员变量是在类初始化的时候被初始化,被放在Jvm所开辟内存的方法区(堆)中,所有实例对象对这一变量的引用均指向这一内存地址,所以说是共享的。
/**
* @PackageName com.a.squirrel.staticdesc
* @Author: squirrel
* @Date: 2018/6/21 09:54
* @Description: static关键字解析辅助类
*/
public class StaticDescription {
private String name; // 常规变量 类实例化时初始化
public static String tmpTwo;// 静态变量 类初始化时初始化
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
/**
* @PackageName com.a.squirrel.staticdesc
* @Author: squirrel
* @Date: 2018/6/21 10:06
* @Description: 测试
*/
public class TestStaticDescription {
public static void main(String[] args) {
// 创建两个实例对象
final StaticDescription sd1 = new StaticDescription();
final StaticDescription sd2 = new StaticDescription();
// 对象sd1对变量tmpTwo 进行修改
sd1.tmpTwo = new String("i have changed by sd1");
System.out.println("sd1.tmpTwo:"+sd1.tmpTwo);
System.out.println("sd2.tmpTwo:"+sd2.tmpTwo);
// 查看结果
System.out.println(sd1.tmpTwo==sd2.tmpTwo);
sd1.setName(new String("hello"));
sd2.setName(new String("hello"));
System.out.println(sd1.getName()==sd2.getName());
}
}
看一下输出结果:
由上图打印结果可以看出静态变量是被实例对象sd1和sd2共享
2.修饰代码块
如果用static来修饰代码块,那么这段代码将会在类初始化的时候先于main方法执行,并且只会执行一次!
/**
* @PackageName com.a.squirrel.staticdesc
* @Author: squirrel
* @Date: 2018/6/21 10:06
* @Description: static关键字解析辅助类
*/
public class TestStaticDescription {
static {
System.out.println("i am static code block");// 静态代码块
}
public static void main(String[] args) {
System.out.println("i am main method");
}
}
3. 修饰方法
static修饰的方法叫做静态方法,一般常见于工具类,最大的好处就是方便调用,不需要实例化对象。
4. 静态内部类
/**
* @PackageName com.a.squirrel.staticdesc
* @Author: squirrel
* @Date: 2018/6/21 10:06
* @Description: static关键字解析辅助类
*/
public class TestStaticDescription {
static {
System.out.println("i am static code block");// 外部类静态代码块
}
public TestStaticDescription() {
System.out.println("i am constructor");// 外部类构造器
}
public static void main(String[] args) {
System.out.println("i am main method");
System.out.println(InnerClass.tmp);// 调用内部类静态属性
}
private static class InnerClass{
private static int tmp = 0;// 静态内部类属性
static {
System.out.println("i am inner class code block");// 内部类静态代码块
}
public static void main(String[] args) {
System.out.println("i am inner class main method");
}
}
}
看一下结果:
对比上下两个图,我们可以知道,静态内部类在使用的时候才会被初始化。
静态内部类使用场景一般是当外部类需要使用内部类,而内部类无需外部类资源,并且内部类可以单独创建的时候会考虑采用静态内部类的设计。
静态内部类和非静态内部类的区别:
- 静态内部类可以有静态成员(方法,属性),非静态内部类则不能
- 静态内部类只能够访问外部类的静态成员,非静态内部类则可以访问外部类的所有成员(方法,属性)
- 实例化一个静态内部类,不依赖于外部类的实例,直接实例化内部类对象,实例化一个非静态内部类,需要先实例化外部类,然后才能实例化
5. 静态导包
将类的方法直接导入到当前类中,从而直接使用方法名即可调用类方法,这里不做过多说明。
注:个人总结,若有不对之处,欢迎批评指正,嘿嘿!