static是一个关键字,翻译为:静态的。
static
修饰的变量叫做静态变量- 静态变量在类加载时初始化,存储在堆中。
- 当所有对象的某个属性的值是相同的,建议将该属性定义为静态变量,来节省内存的开销。
static
修饰的方法叫做静态方法- 只要带有
static
关键字,就是类级别的,统一使用**“类名.”**调用。实际运行时和对象无关。
一、Java中的三种变量
public class Chinese {
int i; // 实例变量
static int j; // 静态变量
public static void main(String[] args){
int i; // 局部变量
}
}
二、实例变量和静态变量的JVM内存图解
- 定义
String country
为实例变量时的JVM内存图
- 定义
static String country
为静态变量时的内存图
- JDK8之后,静态变量存储在堆内存当中
- 在类加载时初始化(不用
new
),类加载在main
方法之前执行
三、静态变量的代码应用
- 当一个属性是对象级别的,这个属性通常定义为实例变量。(实例变量是一个对象一份,100个对象就有100个空间,对空间占用大)
- 当一个属性是类级别的,即所有对象都有这个属性且这个属性的值是一样的,建议定义为静态变量,在内存空间上只有一份(如:中国人类 -> 国籍属性则统一是中国,将该国籍变量定义为静态变量,就避免了一个同样的值,在每个对象中都要单独开辟空间,因而节省了内存,如下代码)
public class Chinese{
// 身份证号
String idCard;
// 姓名
String name;
// 国籍
static String country = "中国";
// 构造方法
public Chinese(String idCard, String name){
this.idCard = idCard;
this.name = name;
}
// 输出方法
public void display(){
System.out.println("身份证号:" + this.idCard + ",姓名:" + this.name)
}
}
public class ChineseTest{
public static void main(String[] args){
// 使用两个参数的构造方法创建和初始化对象
Chinese p1 = new Chinese("123456789", "张三");
Chinese p2 = new Chinese("123467890", "李四");
// 访问国籍(可以直接类调用)
System.out.println("国籍:" + Chinese.country);
}
}
四、*静态代码块
适用于类加载时执行的任务(如在类加载时记录日志)
- 语法格式
public class StaticTest{
// 静态代码块
static{
System.out.println("静态代码块1执行")
}
static{
System.out.println("静态代码块2执行")
}
public static void main(String[] args){
System.out.println("main方法执行")
}
}
- 静态代码块在类加载时执行,并且只执行一次
- 静态代码块可以编写多个,并且遵循自上而下的顺序依次执行
- 静态代码块内不能访问实例相关数据,可以访问在静态代码块前定义的静态变量。
**重要:**类加载时执行加载的静态变量和静态代码块有先后顺序的要求,在静态代码块内调用静态变量,需要静态变量在静态代码块前定义。实例变量和实例方法没有前后定义的要求。