面向对象 Static
文章目录
- 面向对象 Static
- 1.什么是静态?
- 2.Static的作用
- 2.1 属性
- 2.1.1 实例属性
- 2.1.2 静态属性
- 2.2 方法
- 2.2.1 静态方法
- 2.3 代码块
- 2.3.1 局部代码块
- 2.3.2 动态代码块
- 2.3.3 静态代码块
- 2.4 静态导入
- 3.类加载
- 3.1 什么是类加载?
- 3.2 触发类加载的5种情况
- 3.3 类加载过程的5个阶段
- 4.面试题
1.什么是静态?
概念: 共享的, 共有的;
基本用法:
- 静态(static)可以修饰属性,称为静态属性(类属性)。
- 静态(static)可以修饰方法,称为静态方法(类方法)。
特点:
- 静态成员是类所有对象共享的成员,在全类中只有一份,不因创建多个对象而产生多份。
- 静态成员访问不必创建对象,可直接通过类名访问。
使用场景:
- 一般工具类中属性和方法都是静态的。比如:Arrays、Math
- 如果这个属性或方法只需要一份,使用静态修饰。比如:main方法
2.Static的作用
2.1 属性
2.1.1 实例属性
实例属性是每个对象各自持有的独立空间(多份),对象单方面修改,不会影响其他对象。
eg:
public class Test {public static void main(String[] args) {Student stu_1 = new Student();stu_1.name = "小明";Student stu_2 = new Student();stu_2.name = "小红";}
}public class Student {String name;
}
2.1.2 静态属性
静态属性是整个类共同持有的共享空间(一份),任何对象修改,都会影响其他对象。
eg:
public class Test {public static void main(String[] args) {System.out.println("使用类名访问静态属性");Student.count = 2000;System.out.println("学生数量为:"+Student.count);}
}public class Student {static int count;
}
eg:
练习:统计一个类的对象被创建过多少次?
//Student
public class Student {String name;int age;String gender;double score;//默认为0, 创建对象的次数public static int count;public Student() {Student.count++;}public Student(String name, int age, String gender, double score) {Student.count++;this.name = name;this.age = age;this.gender = gender;this.score = score;}
}
//Test
public class Test {public static void main(String[] args) {Student stu_1 = new Student();stu_1.name = "小明";stu_1.age = 18;stu_1.gender = "男";stu_1.score = 100;Student stu_2 = new Student();stu_2.name = "小红";stu_2.age = 18;stu_2.gender = "女";stu_2.score = 100;Student stu_3 = new Student("小绿", 20, "男", 98);System.out.println("使用类名访问静态属性");System.out.println("学生数量为:"+Student.count);}
}
2.2 方法
2.2.1 静态方法
被 static 修饰的方法, 称为静态方法;
public class Student {//默认为0, 创建对象的次数public static int count;public static void calcCount() {System.out.println("开始统计...");Student.count = 2000;System.out.println("统计结束...");//可在本类中,通过“静态方法名”访问method(); // Student.method();}public static void method() {// 方法体}
}public class Test {public static void main(String[] args) {System.out.println("使用类名访问静态方法");//可在其他类中,通过“类名.静态方法名”访问Student.calcCount();System.out.println("学生数量为:"+Student.count);}
}
- 可在本类中, 通过 “静态方法名” 访问;
- 可在其他类中, 通过 “类名.静态方法名” 访问;
特点:
- 静态方法允许直接访问静态属性和静态方法。
- 静态方法不能直接访问实例属性和实例方法,需要创建对象访问。
- 非静态方法中可以直接访问静态属性和静态方法。
- 静态方法中不允许使用this或是super关键字。
- 静态方法可以被继承,可以重载,不能被重写(重写只存在于实例方法之间)。
2.3 代码块
2.3.1 局部代码块
局部代码块:定义在方法内部的代码块。
eg:
public class TestBlock {public static void main(String[] args) {int num1 = 100;{int num2 = 200;System.out.println(num1);System.out.println(num2);}}
}
作用: 会缩小变量的使用范围,提前释放局部变量,节省内存。
2.3.2 动态代码块
动态代码块:定义在方法外,类内部的代码块。
执行时机:创建对象时,触发动态代码块的执行。作用:可为实例属性初始化。
代码编译后会将动态代码块中的内容添加到每个构造方法的首行;
eg:
//Student
public class Student {String name;public Student() {//System.out.println("动态代码块执行了");}public Student(String name) {//System.out.println("动态代码块执行了");this.name = name;}//动态代码块{System.out.println("动态代码块执行了");}
}
2.3.3 静态代码块
静态代码块:使用static修饰的动态代码块。
执行时机:类加载时,触发静态代码块的执行(仅一次)。
作用:可为静态属性初始化。
eg:
//Student
public class Student {String name;public Student() {}public Student(String name) {this.name = name;}//静态代码块static {System.out.println("静态代码块执行了");}
}
2.4 静态导入
eg:
package StageOne.day12.demo04;
import static java.lang.System.out;
/*** @author 胡昊龙* @version 1.0* @description: TODO* @date 2024/1/4 16:33*/
public class TestImportStatic {public static void main(String[] args) {out.println("静态导入");}
}
3.类加载
3.1 什么是类加载?
JVM首次使用某个类时,需通过CLASSPATH查找该类的.class文件。
将.class文件中对类的描述信息加载到内存中,进行保存。如:包名、类名、父类、属性、方法、构造方法…
3.2 触发类加载的5种情况
-
创建对象。
Student s=new Student();
-
创建子类对象。
class CollegeStudent extends Student {...}CollegeStudent stu = new CollegeStudent();
-
访问静态属性。
static int count; //静态属性System.out.println(Student.count);
-
调用静态方法。
public static void method() {...} // 静态方法Student.method();
-
主动加载:Class.forName(“全限定名”);//后面讲
3.3 类加载过程的5个阶段
类加载的五个阶段:
- 加载—>链接 (验证—>准备—>解析)—>初始—>使用—>卸载
准备:为类的静态属性分配空间,并赋值默认值(静态常量除外)
初始化:从上到下执行静态变量赋值,静态代码块
4.面试题
eg:
阅读下方代码, 请说明运行结果和具体的执行过程
public class TestStatic {public static void main(String[] args) {Demo.show();}
}
class Demo {static {Demo.count1++;Demo.count2++;}private static Demo demo = new Demo();public static int count1;public static int count2=0;public Demo() {Demo.count1++;Demo.count2++;}public static void show() {System.out.println("count1:"+count1);System.out.println("count2:"+count2);}
}
res:
count1:2
count2:0