final_static关键字的使用

final、static关键字的使用说明,主要是对使用static修饰的变量和方法的分析。static也可修饰类(内部类),被修饰的类叫静态内部类,这里不做说明。

Author: Msuenb

Date: 2023-02-10


final 关键字

final的含义是最终的、不可更改的。它可以修饰变量、方法和类,各有其意义。

final 修饰变量

final修饰某个变量(成员变量或局部变量),表示它的值不能被修改,称为常量。

注意:

  • 常量名建议使用大写字母,如:final double PI = 3.14
  • final修饰的成员变量,没有set方法,并且必须初始化(显示赋值、构造器中赋值、代码块中赋值),不能使用默认值。
class FinalVar {
    final String name = "Tom";	 // 显示赋值
    final int age;
    final double height;  
    final double weight;  

    {
        age = 18;		// 代码块中赋值
    }

    public FinalVar() {
        height = 179.5;	// 构造器中赋值
    }
    
    public FinalVar(double weight) {
        this.weight = weight;	// 构造器中赋值
    }

    public void setName(String name) {
        //this.name = name;     // 不可修改
    }
}

通常成员常量都是用public static final修饰

final 修饰方法

final修饰某个方法,表示这个方法不能被重写。

class Father {
    public final void method() {
        System.out.println("father");
    }
}

class Son extends Father {
    public final void method() {    // final 方法不可重写
        System.out.println("son");
    }
}

final 修饰符类

final修饰某个类,表示这个类不能被继承。

final class Father2 { }

class Son2 extends Father2 {}   // Father2 不能被继承

static 关键字

在类中声明的示例变量,其值是每个对象独立的。有时需要与当前对象无关的成员变量、成员方法,此时就可以将这些成员声明为静态的(static)。

静态变量

static关键字修饰的成员变量就是静态变量,也叫类变量。

【修饰符】 class 类{
  【其他修饰符】 static 数据类型  静态变量名;
}

静态变量的特点:

  • 静态变量的默认值规则和实例变量一样。父类的静态变量也可以被子类继承。
  • 静态变量的值存储在方法区,为所有对象共享。
  • 静态变量在本类任意位置都可以使用。权限修饰符允许的话,可以通过类名.静态变量名对象名.静态变量名(不推荐) 调用。
  • 静态变量的get/set方法也是静态的。

静态变量使用演示:

public class StaticVarTest {
    public static void main(String[] args) {
        StaticVar staticVar = new StaticVar();  // 对象1
        StaticVar staticVar2 = new StaticVar(); // 对象2 

        System.out.println(StaticVar.name); // null 可以通过 类名.静态变量 访问
        System.out.println(staticVar.name); // null 通过 对象名.静态变量 访问 不推荐
        System.out.println(staticVar2.name);// null

        StaticVar.name = "Tom";     // 修改 name 的值
        System.out.println(StaticVar.name);     // Tom
        System.out.println(staticVar.name);     // Tom
        System.out.println(staticVar2.name);    // Tom  多个对象共享

        StaticVar.setAge(18);       // 只能通过 set/get 方法访问 age
        System.out.println(StaticVar.getAge()); // 18
    }
}
class StaticVar {
    public static String name;  // 可以通过 类名.静态变量 访问
    private static int age;     // 只能通过提供的get/set访问

    public static String getName() {
        return name;
    }

    public static void setName(String name) {
        StaticVar.name = name;
    }

    public static int getAge() {
        return age;
    }

    public static void setAge(int age) {
        StaticVar.age = age;
    }
}

静态变量内存分析:

public class Main {
    public static void main(String[] args) {
        Student s1 = new Student();
        Student s2 = new Student();

        System.out.println(s1.job); // 学生
        System.out.println(s2.job); // 学生
        s1.job = "student";		// s1 和 s2 共享 job
        System.out.println(s1.job); // student
        System.out.println(s2.job); // student
    }
}

class Student {
    String name;
    int age;
    static String job = "学生";
}

静态变量、实例变量和局部变量:

  • 静态变量:存储在方法区,有默认值,所有对象共享,生命周期和类相同,还可以有权限修饰符、final等其他修饰符
  • 实例变量:存储在堆中,有默认值,每一个对象独立,生命周期每一个对象也独立,还可以有权限修饰符、final等其他修饰符
  • 局部变量:存储在栈中,没有默认值,每一次方法调用都是独立的,有作用域,只能有final修饰,没有其他修饰符

静态方法

static关键字修饰的成员方法就是静态方法。当方法没有访问到任何非静态成员时可以用static修饰。

【修饰符】 class 类{
  【其他修饰符】 static 返回值类型 方法名(形参列表){
        方法体
    }
}

静态方法的特点:

  • 静态方法在本类的任意方法、代码块、构造器中都可以直接被调用。
  • 权限修饰符允许的话,可以通过类名.静态方法名对象名.静态方法名(不推荐) 调用。
  • 静态方法可以被子类继承,但不能被子类重写
  • 静态方法的调用都只看编译时类型。
  • 静态方法只能访问静态成员 ,不能访问非静态成员。

静态方法使用演示:

public class StaticMethodTest {
    public static void main(String[] args) {
        Son son = new Son();
        Son.fun();
        // son.fun();  // 不推荐
        son.fun2();
    }
}

class Father {
    public static String a = "父类的静态变量";

    public static void method() {
        System.out.println("父类的静态方法");
    }
}

class Son extends Father {
    public String b = "子类的非静态变量";

    {
        fun1();   // 代码块中调用静态方法
        System.out.println("代码块中调用静态方法");
    }

    public Son() {
        fun1();  // 构造器中调用静态方法
        System.out.println("构造器中调用静态方法");
    }

    //@Override //尝试重写静态方法,加上@Override编译报错,去掉Override不报错,但是也不是重写
    //public static void method(){
    //    System.out.println("Son.fun");
    //}

    public static void fun() {
        System.out.println("子类的静态方法");
        // System.out.println(s);  // 静态方法中不能访问非静态变量
        // fun2();      // 静态方法中不能调用非静态方法
        System.out.println(a);  // 继承父类的静态变量
        method();   // 继承父类的静态方法
    }

    public static void fun1() { }

    public void fun2() {
        System.out.println("子类的非静态方法");
        fun1();      // 非静态方法可以访问静态成员
        System.out.println("非静态方法可以访问静态成员");
    }
}

静态导入

如果大量使用另一个类的静态成员,可以使用静态导入,简化代码。(了解)

import static 包.类名.静态成员名;
import static 包.类名.*;

演示:

import static java.lang.Math.*;

public class StaticImportTest {
    public static void main(String[] args) {
        //使用Math类的静态成员
        System.out.println(Math.PI);
        System.out.println(Math.sqrt(9));
        System.out.println(Math.random());
    }
}

静态和非静态的区别

  • 本类中的访问限制区别

    静态的类变量和静态的方法可以在本类任意位置直接访问。

    非静态的实例变量和非静态的方法只能在本类的非静态的方法、构造器等非静态成员中直接访问。

    • 静态直接访问静态,可以
    • 非静态直接访问非静态,可以
    • 非静态直接访问静态,可以
    • 静态直接访问非静态,不可以
  • 在其他类的访问方式区别

    静态的类变量和静态的方法可以通过类名.的方式直接访问;也可以通过对象.(不推荐)的方式访问。

    非静态的实例变量和非静态的方法只能通过对象.方式访问。

posted @ 2023-02-12 19:17  msuenb  阅读(11)  评论(0编辑  收藏  举报