秦疆的Java课程笔记:73 面向对象 static关键字详解

发布时间 2023-12-18 16:13:10作者: Acolyte_9527
  • 先看变量
public class Student {  
    private static int age;   //静态变量  
    private double score;   //非静态变量  
    public static void main(String[] args) {  
        System.out.println(Student.age);  
        System.out.println(Student.score);   //报错“无法从static上下文引用非static字段”  
        Student s1 = new Student();  
        System.out.println(s1.age);   //IDEA提示,“通过实例引用访问static成员OOP.demo.Student.age。可改成:System.out.println(age); 
        System.out.println(s1.score);  
    }  
}
  • 推荐使用类名访问静态变量,比如这里就是用Student.age访问静态变量age

  • 但在静态方法中使用类名访问非静态变量就会出错,比如这里main方法是静态的,访问非静态变量score就报错了。

  • 我的看法:如果分析内存的话,类静态成员是在和类一起加载的,这时非静态变量应该是尚未加载,所以无法调用。而通过Student s1 = new Student();语句实例化对象之后,非静态变量才完成加载,这时才可以调用。

  • 将类型实例化之后,通过对象调用对象属性就没有任何限制,比如这里的s1.ages1.score

  • s1.age那个提示,实际是在说走了弯路,因为静态成员可以直接调用,没必要再通过对象调用。当然这里只是作为示例。

  • 再看看方法

public class Student {  
    public void run() {}   //非静态方法  
    public static  void go() {}   //静态方法  
    public static void main(String[] args) {  
        go();  
        run();   //报错,无法从static上下文引用非static方法  
        Student s2 = new Student();  
        s2.run();  
        s2.go();  //IDEA提示:通过实例访问static成员  
    }  
}
  • 报错和提示的原因都是和上面一样的。

  • 代码块和静态代码块

public class Demo {  
    //代码块(匿名代码块)
    //程序在运行时并不能主动调用这些匿名代码块
    //在构造器之前执行  
    {
    }  
    //加上static关键词,就是静态代码块了  
    //类加载时,就会执行且只执行一次。  
    static {  
    }  
}
  • 演示如下:
public class Person {  
    //匿名代码块  
    {  
        System.out.println("匿名代码块");  
    }  
    //静态代码块  
    static {  
        System.out.println("静态代码块");  
    }  
    //构造方法
    public Person() {  
        System.out.println("构造方法");  
    }  
    //主程序方法
    public static void main(String[] args) {  
        Person person1 = new Person();
        System.out.println("***********");  
		Person person2 = new Person();  
    }  
}
====运行结果如下====
静态代码块
匿名代码块
构造方法
***********
匿名代码块
构造方法
  • 静态代码块和类一起加载,所以最早执行。

  • 第二个时匿名代码块,会在构造方法之前执行。

  • 构造方法执行最晚,是在主程序中创建实例对象person时才执行的。

  • 之前说过,静态代码块仅在类加载时执行一次,和是否调用构造方法无关。

  • 但是匿名代码块似乎每次创建对象时,就会先执行匿名代码块,再执行构造方法。

  • 静态导入包

//import java.lang.Math;   一般导入的写法  
//import java.lang.Math.random;   若直接导入一个类会报错  
import static java.lang.Math.random;   //但是可以加关键词static导入,这就是静态导入包  
import static java.lang.Math.PI;   //查看源码可知,PI是一个由final修饰的double类型常量 
public class Test {  
    public static void main(String[] args) {  
        //一般情况下,调用Math类中的方法和变量  
        System.out.println(Math.random());  
        System.out.println(Math.PI);  
        //静态导入包后,调用Math类的方法和变量  
        System.out.println(random());   
        System.out.println(PI);  
    }  
}