15.Java this 关键字/static关键字/静态初始化块/final关键字

创建对象的过程

  1. 分配对象空间,并将对象成员初始化为 0 或 空
  2. 执行属性值的显式初始化
  3. 执行构造方法
  4. 返回对象的地址给相关的变量。

this 关键字

注意点

  1. this 关键字用于区分局部变量和成员变量。(就近原则:优先获取最近的)
  2. 通过 this 可以直接指代成员变量(属性)。
  3. 通过 this 可以去调用类中普通的成员方法。
  4. 通过 this 可以去调用构造器。使用 this 关键字在一个构造器中去调用另一个重载的构造方法,可以避免相同的初始化代码。但只能在构造方法中用,且必须位于构造方法代码的第一行,否则报错。
  5. this 不能用于 static 方法中
  6. 在程序产生二义性之处,应用 this 来指明当前对象;
  7. 普通方法中,this 总是指向调用该方法的对象。
  8. 构造方法中,this 总是指向正要初始化的对象。

代码示例:上方注意点中提到的代码

public class TestThis1 {
    int a,b,c;
    // 定义构造方法
    TestThis1(int a,int b){
        this.a = a;
        this.b = b;
    }
    // 构造方法的重载
    TestThis1(int a,int b,int c){
        // 调用本类中(上方)两个参数的构造方法。在一个构造器中调用另一个构造器。
        this(a,b);
        this.c = c;
    }
    // 定义普通方法
    void sing(){
        System.out.println("小明同学,小明同学");
    }
    // 定义普通方法
    void eat() {
        // 调用本类中的 sing() 方法
        this.sing();
        System.out.println("小明同学,小明同学,你妈妈给你送来了你最喜欢的旺仔牛奶。");
    }

    public static void main(String[] args) {
        // 创建类对象,调用类方法(如果自定义了构造方法,则系统就不会自动添加无参构造方法,创建对象时就需要指定是哪个构造方法)
        TestThis1 hi = new TestThis1(2,3);
        hi.eat();
    }
}

代码示例:this 代表 “当前对象”

public class User {
    // 定义类的成员变量(类属性)
    int id;     // id
    String name;// 账户名
    String pwd; // 密码
    // 定义空构造方法
    public User(){
    }
    // 构造方法重载
    public User(int id,String name){
        // 测试调用方法时的 实参 到底是赋值给了谁
        System.out.println(id);    // 打印结果为 119
        System.out.println(name);  // 打印结果为 阿jun
        System.out.println(pwd);   // 打印结果为 null
        System.out.println("正在初始化已经创建好的对象(当前对象):" + this);
        // 利用 this 关键字将成员变量赋值给 User 构造方法的局部变量
        this.id = id;    // 不写 this,无法区分局部变量 id 和 成员变量 id
        this.name = name;
    }
    // 定义普通方法
    public void login(){
        // 这里的 this.name 等同于方法里调用成员变量(属性) name 
        System.out.println(this.name + ",要登录!");   // 不写 this 效果一样
    }
    // 定义 main 方法
    public static void main(String[] args) {
        // 调用方法时,成员变量属性 id 和 name 都已经被分别赋值为 id=119 和 name="阿jun"
        // 调用方法时定义的实参是直接赋值给了外部对应的成员变量(也叫对应类属性)
        User u3 = new User(119,"阿jun");
        // 此时打印的是 User 类中 u3 对象的内存地址
        System.out.println("打印的是 User 类中 u3 对象的内存地址:" + u3);
        u3.login();
    }
}

static 关键字

简述

在类中,用 static 修饰的变量称之为静态变量,也称为类变量。
类变量的声明周期和类相同,在整个应用程序执行期间都有效。
如下特点:

  1. 类表里是该类的公用变量,属于类,被该类的所有实例共享,在类被载入时被显式初始化。
  2. 对于该类的所有对象来说,static 成员变量只有一份,被该类的所有对象共享。
  3. 一般用 “类名.属性/方法” 来调用。(也可以通过对象引用或类名(不需要实例化)访问静态成员。)
  4. 在 static 方法中,不可直接访问非 static 的成员。

核心要点:

  • static 修饰的成员变量和方法,从属于类。
  • 普通变量和方法从属于对象。

代码示例:测试 static 关键字的用法

// 测试 static 关键字的用法
public class User2 {
    int id;
    String name;
    String pwd;
    static String company = "公众号:阿jun修炼手册"; // 定义静态变量
    // 定义构造方法
    public User2(int id,String name){
        this.id = id;
        this.name = name;
    }
    // 定义普通方法
    public void login(){
        // 普通方法中调用静态方法
        printCompany();
        // 普通方法中调用静态变量
        System.out.println("登录名:" + company);
        // 普通方法中调用普通属性
        System.out.println("登录名:" + id);
    }
    // 定义静态方法
    public static void printCompany(){
        System.out.println(company);
        // 下方代码会编译出错,静态方法中无法去使用非静态的方法/变量/常量,因为两者在方法区中的位置不同
        // System.out.println(id);
    }
    public static void main(String[] args) {
        // 定义类对象
        User2 u = new User2(110, "120");
        // 通过类名去调用方法,打印 company 静态变量
        User2.printCompany();
        // 静态变量重新赋值,通过类名去调用 company 静态变量
        User2.company = "阿jun 都2021年了还没对象";
        // 通过类名去调用方法,打印 company 静态变量
        User2.printCompany();
        // 对象调用静态方法
        u.printCompany();
        // 对象调用普通方法
        u.login();
    }
}

内存分析图

注意点

  1. 类加载完以后,类里面的相关信息(代码、静态变量/常量)会加载到 方法区 中
  2. 普通的方法/变量/常量 从属于类对象
  3. 静态的方法/变量/常量 从属于类。
  4. 静态方法中无法去使用非静态的方法/变量/常量。因为两者在内存的堆中的位置不同
  5. 在普通方法中调用静态的方法/属性,没有问题
  6. this 用于普通方法中,属于类,不属于对象,this 代表的是当前的对象,所以不能在静态方法里使用
  7. 静态方法/变量/常量 类似于汽车的图纸,非静态方法/变量/常量属类似于汽车成品。图纸中不能找到汽车,汽车中能去找图纸(有汽车,肯定就有图纸,有图纸不一定有汽车)

静态初始化块

简述

构造方法用于对象的初始化。静态初始化块,用于类的初始化操作。
在静态初始化块中不能直接访问非 static 成员。

语法格式

static {
    …………
}

使用要点

  1. 静态块用 static 来修饰,不给定名字。
  2. 静态块在类初始化的时候开始执行。
  3. 类初始化过程中,不能去调用非静态的方法/变量,因为初始化过程中没有对象。
  4. 初始化类的过程,相当于是在描绘汽车图纸的过程。
  5. 程序在加载类的过程中,就会去将静态块的代码内容去执行。
  6. 类加载完成以后,才能构造对象。

代码示例:测试静态初始化块的使用

// 测试 静态初始化块
public class User3 {
    int id;
    String name;
    String pwd;
    static String company;  // 定义静态成员变量
    // 静态初始化块
    static {
        System.out.println("开始进行类的静态初始化块,company 此时的值为:" + company);
        System.out.println("静态初始化块会在类加载的时候被调用执行。");
        System.out.println("静态初始化块可以去调用静态的方法/变量,但不能调用非静态的方法/变量(如:id、name)");
        // 调用静态成员变量并赋值
        company = "公众号-阿jun修炼手册";
        // 调用静态方法
        printCompany();
    }
    // 定义静态方法
    public static void printCompany(){
        // 静态方法中调用静态变量
        System.out.println("被赋值以后的 company 值为:" + company);
    }
    public static void main(String[] args) {
        User3 u = null;  // 这里并没有创建对象,啥也没做
    }
}

注意点

静态初始化执行顺序(学继承以后再看,先了解)

  1. 上溯到 Object 类,先执行 Object 的静态初始化块,再向下执行子类的静态初始化块,知道我们的类静态初始化块为止。
  2. 构造方法执行顺序与上方所述一致。

final关键字

作用

  1. 修饰变量

被 final 修饰的变量不可改变。一旦赋了初值,就不能被重新赋值

final int MAX_SPEED = 120;
  1. 修饰方法

该方法不可被子类重写,但是可以被重载。

 public final void study(){}
  1. 修饰符

修饰的类不能被继承。比如:Math、String 等。

final class A{}
posted @ 2021-11-06 14:09  阿jun  阅读(93)  评论(0)    收藏  举报