参考笔记:java类变量(static变量)_java 类变量-CSDN博客
目录

1.static关键字
- 使用范围:在 Java 类中,可用 static 修饰属性、方法、代码块、内部类
- 被修饰后的成员具备以下特点:
- 随着类的加载而加载,优先于对象实例而创建
- 修饰的成员,被所有对象实例所共享
- 访问权限允许时,可不创建对象,直接被类调用
2.静态变量/类变量
回顾一下变量的分类,静态变量也称为类变量
当编写一个类时,只是在描述其对象实例的属性和行为,而并没有产生实质上的对象,只有通过 new 关键字才会创建对象,这时系统才会分配内存空间给对象,类中的成员才可以供对象调用
有时候希望无论是否产生了对象或无论产生了多少对象的情况下,某些特定的数据在内存空间里只有一份,是所有对象实例共享的,因此引出了 static 静态变量
2.1 设计思想
应用场景:有一群小孩在玩堆雪人,不时有新的小孩加入,请问如何知道现在共有多少人在玩?
传统实现方法
静态变量引入
在 Child 类中设计一个用 static 关键字修饰的 count 属性,所有 Child 对象实例共享一个 count 属性
public class Test{
public static void main(String[] args){
Child child1 = new Child("小马", 22);
Child.count++;//小孩数量++
Child child2 = new Child("蔡徐坤", 22);
Child.count++;//小孩数量++
System.out.println(Child.count);
}
}
class Child{
public static int count = 0;//静态变量,用于记录有多少个小孩在玩游戏
public String name;
public int age;
public Child(String name, int age){
this.name = name;
this.age = age;
}
}
2.2 内存图分析
这里静态变量的存放区域说的最多的一个版本就是 JDK 8 之前在方法区,JDK8 之后存放在堆里。但无论存放在哪,都是所有对象实例共享一个变量,记住这点就行了
2.3 语法格式、访问方式
语法格式
(1)[访问修饰符] static 数据类型 变量名;【推荐】
(2)static [访问修饰符] 数据类型 变量名;
访问方式
(1)类名.静态变量名【推荐】
(2)对象实例名.静态变量名
2.4 静态变量细节
(1)静态变量的访问修饰符的访问权限和普通变量是一样的,依然要遵守;默认值规则和实例变量也是一样的
(2)当需要让某个类的所有对象实例都共享一个变量时,就可以考虑使用静态变量。比如:定义学生类,统计所有学生共交多少钱
(3)静态变量与实例变量的区别:静态变量是该类的所有对象实例共享的,而实例变量是每个对象实例独享的
(4)静态变量优先于对象实例而存在,类变量是在类加载的时候就生成的 ,因此无需创建对象来使用
(5)静态变量的 get/set 方法也是静态的
(6)当局部变量与静态变量重名时,可以使用 "类名.静态变量" 进行区分
3.静态方法/类方法
static 修饰成员方法时,该方法称为静态方法
静态方法的好处:不创建对象实例也可以调用某个方法(即当作工具来使用),非常方便
3.1 语法格式、访问方式
语法格式
(1)
[修饰符1] class 类{
[修饰符2] static 返回值类型 方法名(形参列表){
方法体
}
}【推荐】
(2)
[修饰符1] class 类{
static [修饰符2] 返回值类型 方法名(形参列表){
方法体
}
}
访问方式
(1)类名.静态方法名【推荐】
(2)对象实例名.静态方法名
案例
public class Test{
public static void main(String[] args){
Person.test();
Person person = new Person();
person.test();
}
}
class Person{
public static void test(){
System.out.println("static test");
}
}
3.2 静态方法细节
(1)静态方法优先于对象实例而存在,所以静态方法内部不允许有 this、super 关键字
(2)静态方法在本类的任意方法、代码块、构造器中都可以直接被调用
(3)静态方法的访问修饰符的访问权限和普通方法是一样的,依然要遵守
(4)静态方法内部只能访问静态变量、其他静态方法,不能访问类的非 static 的结构;普通方法既可以访问普通变量/方法,也可以静态变量/方法
(5)静态方法可以被子类继承,但不能被子类重写
如果子类定义了与父类同名、同参数、同返回类型的静态方法,此时父类的静态方法是被 "隐藏"(而非重写)
(6)静态方法的调用都只看编译类型
public class Test {
public static void main(String[] args) {
A a = new A();
a.run();//A run
A.run();//A run
B obj = new A();
obj.run();//B run
B.run();//B run
}
}
class B{
public static int a = 1;
public static void run(){
System.out.println("B run");
}
}
class A extends B{
public static void run(){
System.out.println("A run");
}
}
(7) 调用静态方法时,可以通过类名或对象引用调用,即使对象引用为 null ,还是能正常访问静态方法,不会抛出 NullPointerException(空指针异常)
public class Test {
public static void main(String[] args) {
Demo test = null;
test.hello();
}
}
class Demo{
public static void hello(){
System.out.println("hello!");
}
}
/*输出结果
hello
*/
4. main方法
public static void main(String[] args){
}
4.1 深入理解main方法
(1)Java 虚拟机需要调用类的 main()方法,所以该方法的访问权限必须是 public
(2) Java 虚拟机在执行 main() 方法时不必创建对象实例,可以直接 类名.main() 调用,所以main 方法必须用 static 修饰
(3) main 方法接收一个 String 类型的数组参数,该数组可以保存执行 Java 程序时所传递的参数
验证方法一
第1步:编写 Test.java,用于输出所传递的参数
public class Test {
public static void main(String[] args) {
for (int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
}
}
第2步:打开终端命令行,进入 Test.java 文件所在目录
第3步:执行 Javac Test.java,编译成 Test.class 文件
第4步:执行 Java Test 小马 蔡徐坤,执行 Java 程序的同时并传入参数
验证成功
验证方法二
(4)在 main() 方法中,可以直接调用 main() 方法所在类的静态成员。但由于 main() 方法是静态的,所以不能直接通过 "类名.成员名" 访问该类中的非静态成员,必须先创建该类的一个对象实例后,再通过 "对象名.成员名" 访问类中的非静态成员
public class Test {
public static int count = 0;//静态变量
public int age = 18;
public static void sayHello(){
System.out.println("Hello World!");
}
public void run(){
System.out.println("run");
}
public static void main(String[] args) {
Test.sayHello();//直接调用静态方法
sayHello();//直接调用静态方法
System.out.println(Test.count);//直接调用静态变量
System.out.println(count);//直接调用静态变量
System.out.println(new Test().age);//创建对象实例后再调用非静态变量
new Test().run();//创建对象实例后再调用非静态方法
}
}
/*输出结果
Hello World!
Hello World!
0
0
18
run
*/
4.2 补充
main 方法的形参名称 args 可以修改为其他名称,但不能修改参数类型
public class Test {
public static void main(String[] anything) {
for(int i = 0;i<anything.length;i++){
System.out.println(anything[i]);
}
}
}