【Java SE】静态变量、静态方法、main方法

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

目录

1.static关键字

2.静态变量/类变量

2.1 设计思想

2.2 内存图分析

2.3 语法格式、访问方式

2.4 静态变量细节

3.静态方法/类方法

3.1 语法格式、访问方式

3.2 静态方法细节

扫描二维码关注公众号,回复: 17572152 查看本文章

4. main方法

4.1 深入理解main方法

4.2 补充


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]);
        }
    }
}