目录
[static 修饰成员变量](#static 修饰成员变量)
[static 修饰成员方法](#static 修饰成员方法)
[static 成员变量初始化](#static 成员变量初始化)
static 是 静态 的意思,可以用来修饰成员变量 、成员方法
我们通过一个例子来看:
java
public class Student {
private int id;
private String name;
private int age;
public Student() {
}
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
}
我们使用上述学生类实例化对象
java
public static void main(String[] args) {
Student s1 = new Student(1, "张三", 18);
Student s2 = new Student(2, "李四", 19);
Student s3 = new Student(3, "王五", 19);
}
每个对象都有自己特有的 id、姓名 和 年龄 信息,这些信息是对不同学生进行描述的
上述 id、姓名 以及 年龄 是在 Student 类中定义的成员变量 ,每个对象都会包含一份,使用这些信息来描述具体的学生
而现在需要添加一个 classRoom 来描述学生的班级(假设所有学生的班级都是相同的)
而 classRoom 对于所有学生都是相同的,因此,没有必要每个学生对象中都存储一份,可以将其提取出来,让所有学生共享
在 Java 中,被 static 修饰的成员称为静态成员 ,也可以称为类成员 ,不属于某个具体的对象,而是所有对象所共享的
static 修饰成员变量
static 修饰的成员变量 ,称为静态成员变量
静态成员变量最大的特性:不属于某个具体的对象,是所有对象所共享的
静态成员变量可以直接通过 类名访问
java
public class Student {
private int id;
private String name;
private int age;
private static String classRoom = "一班";
public Student() {}
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public static void main(String[] args) {
System.out.println(Student.classRoom);
}
}
也可以通过对象访问
java
public class Student {
private int id;
private String name;
private int age;
private static String classRoom = "一班";
public Student() {}
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public static void main(String[] args) {
Student s1 = new Student(1, "张三", 18);
Student s2 = new Student(2, "李四", 19);
Student s3 = new Student(3, "王五", 19);
System.out.println(s1.classRoom);
System.out.println(s2.classRoom);
System.out.println(s3.classRoom);
}
}
classRoom 是对象所共享的,因此获取到的 classRoom 是相同的
若进行调试,也可以看到,静态成员变量并没有存储到某个具体的对象中
静态成员变量是所有对象共享 的,是类的属性 ,因此,在 JVM 进行类加载 时就会为其开辟空间进行存储(存储在方法区 中),它的生命周期伴随类的一生(随类的加载而创建,随类的卸载而销毁)
总结一下静态成员变量的特性:
(1)不属于某个具体的对象,是类的属性,是所有对象共享的,不存储在某个对象的空间中
(2)可以通过对象访问,也可以通过类名访问,但一般更推荐使用类名访问
(3)存储在方法区中,其生命周期伴随类的一生
static 修饰成员方法
一般类中的数据成员都设置为 private,成员方法设置为 public,上述我们直接在 Student 类中进行访问,那 Student 类中的 classRoom 属性如何在类外进行访问呢?
在 Java 中,被 static 修饰的成员方法是类的方法 ,不是某个对象所特有的,因此,静态成员一般是通过静态方法来访问的
java
public class Student {
private int id;
private String name;
private int age;
private static String classRoom = "一班";
public Student() {}
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public static String getClassRoom() {
return classRoom;
}
}
可以直接通过类名调用
java
public class Test {
public static void main(String[] args) {
System.out.println(Student.getClassRoom());
}
}
也可以通过对象调用
java
public class Test {
public static void main(String[] args) {
Student student = new Student();
System.out.println(student.getClassRoom());
}
}
更推荐使用类名 调用的方式
不能在静态方法中访问任何非静态成员变量
静态方法中也不能调用任何非静态方法
为什么在静态方法中不能访问任何非静态成员,也不能调用任何非静态方法?
(1)静态方法 与 非静态成员变量和方法 的作用域不同
静态方法 属于类本身的,是类方法 ,而不是特定对象的方法,这也就意味着 静态方法可以在不创建实例的情况下被调用
而非静态成员变量 和 非静态成员方法是与创建的对象相关联的,每个对象都有自己的副本,这些变量和方法只能通过对象实例来访问
(2)静态方法中没有 this 引用
静态方法中不具有隐含的 this 引用,这是因为它无法知道自己在哪个对象上下文中被调用
而非静态成员变量和方法依赖于 this 来引用当前对象的状态
因此,在静态方法中调用时无法传递 this 引用,没有对象的上下文可引用,导致编译器无法识别哪些非静态成员应该被访问
(3)作用不同
静态方法通常用于执行与类相关的操作
而非静态成员变量和方法用于表示对象的状态的行为
将静态方法和非静态成员变量和方法区分开,有利于保持代码的清晰性和可维护性
在构造方法中可以访问和使用静态成员变量,也可以调用静态成员方法
java
public class Student {
private int id;
private String name;
private int age;
private static String classRoom = "一班";
public Student() {
System.out.println(getClassRoom());
classRoom = "二班";
System.out.println(getClassRoom());
}
public static String getClassRoom() {
return classRoom;
}
}
静态方法无法重写,不能用来实现多态
java
public class Person {
public static void method() {
System.out.println("Person method...");
}
}
子类中也可以存在 method 方法,但是不会构成重写
java
public class Student extends Person{
private int id;
public static void method() {
System.out.println("Student method...");
}
}
访问 method 方法:
java
public class Test {
public static void main(String[] args) {
Person person = new Student();
person.method();
}
}
运行结果:
可以看到 person 调用的是父类静态方法,而不是子类的静态方法
为什么呢?
(1)静态方法是在编译时期进行绑定 的,而不是在运行时,这也就意味着当调用一个静态方法时,编译器会根据 引用类型确定要调用的方法,而不是类的实际类型
(2)静态方法是属于类的方法,而不是实例的,因此,它们不能被子类重写 。重写是基于实例的方法,需要通过对象来调用
(3)重写涉及到多态性 ,在实例方法中,它们可以根据对象的实际类型来确定调用哪个方法,而静态方法不具备这种特性
总结一下静态成员方法的特性:
(1)不属于某个具体的对象,是类方法
(2)可以通过对象调用,也可以通过类名调用,更推荐使用类名调用
(3)不能在静态成员方法中访问任何非静态成员变量
(4)静态成员方法中不能调用任何非静态成员方法
(5)可以在构造方法中使用静态成员变量,也可以调用静态成员方法,但是不推荐
(6)静态方法无法重写,不能用来实现多态
static 成员变量初始化
虽然静态成员变量可以在构造方法中初始化,但是一般不会将其放在构造方法中初始化,构造方法中初始化的是对象相关的实例属性
静态成员变量一般通过两种方式进行初始化:
就地初始化
静态代码块初始化
就地初始化
就地初始化:在定义时直接给出初始值
private static String classRoom = "一班";
静态代码块初始化
静态代码块 :使用static定义的代码块
private static String classRoom;
static {
classRoom = "一班";
}