• 【Java】this、super关键字,代码块介绍


    文章目录

    一. this引用

    1. this引用的介绍

    • this引用是成员方法的参数之一,不需要用户传递实现,由编译器自动完成,也就是说,这个参数用户是看不到的,但用户可使用这个参数。
    • this引用指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。 只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
    • this 引用的是调用成员方法的对象。

    2. this引用的特性

    1. this的类型:对应类 类型引用,即哪个对象调用就是哪个对象的引用类型
    2. this只能在"成员方法"中使用
    3. 在"成员方法"中,this只能引用当前对象,不能再引用其他对象
    4. this是“成员方法”第一个隐藏的参数,编译器会自动传递,在成员方法执行时, 编译器会负责将调用成员方法对象的引用传递给该成员方法,this负责来接收

    1. 用户也可以将由编译器实现的形参this手动给出,但实参中不能有其对应的对象的引用,否则会报错

    3. this引用所解决的问题

    看下面给出的代码, 当方法形参名与成员变量名相同 ;但我们没有手动通过this引用去调用成员变量;

    看执行结果可以发现此时并没有完成对于成员变量的赋值,因为在方法中遵循局部变量优先的原则,就不会去访问成员变量,只是形参自己给自己赋值而已

    1. public class Date {
    2. public int year;
    3. public int month;
    4. public int day;
    5. public void setDay(int year, int month, int day){
    6. year = year;
    7. month = month;
    8. day = day;
    9. }
    10. public void printDate(){
    11. System.out.println(year + "/" + month + "/" + day);
    12. }
    13. public static void main(String[] args) {
    14. // 构造三个日期类型的对象 d1 d2 d3
    15. Date d1 = new Date();
    16. Date d2 = new Date();
    17. Date d3 = new Date();
    18. // 对d1,d2,d3的日期设置
    19. d1.setDay(2022,8,15);
    20. d2.setDay(2022,8,16);
    21. d3.setDay(2022,8,17);
    22. // 打印日期中的内容
    23. d1.printDate();
    24. d2.printDate();
    25. d3.printDate();
    26. }
    27. }

    执行结果:

    要解决这里的问题只需要通过this去访问成员变量即可,此时就可以区分形参和成员变量了

    1. public void setDay(int year, int month, int day){
    2. this.year = year;
    3. this.month = month;
    4. this.day = day;
    5. }

    执行结果:

    4. this的三种用法

    • this.成员变量
    • this.成员方法
    • this( );访问构造方法(在构造方法博客中介绍)

    二. super关键字

    1. super关键字的介绍

    由于设计不好,或者因场景需要,子类和父类中可能会存在相同名称的成员,如果要在子类方法中访问父类同名成 员时,该如何操作?

    直接访问是无法做到的,因为局部优先的的原则,会直接访问子类的成员。

    Java提供了 super关键字,该关键字主要作用:在子类方法中访问父类的成员。

    【注意事项】

    1. super只能在非静态方法中使用
    2. super可以用来在子类方法中,访问父类的成员变量和方法。
    1. public class Base {
    2. int a;
    3. int b;
    4. public void methodA(){
    5. System.out.println("Base中的methodA()");
    6. }
    7. public void methodB(){
    8. System.out.println("Base中的methodB()");
    9. }
    10. }
    11. class Derived extends Base{
    12. int a; // 与父类中成员变量同名且类型相同
    13. char b; // 与父类中成员变量同名但类型不同
    14. // 与父类中methodA()构成重载
    15. public void methodA(int a) {
    16. System.out.println("Derived中的method()方法");
    17. }
    18. // 与基类中methodB()构成重写
    19. public void methodB(){
    20. System.out.println("Derived中的methodB()方法");
    21. }
    22. public void methodC(){
    23. // 对于同名的成员变量,直接访问时,访问的都是子类的
    24. a = 100; // 等价于: this.a = 100;
    25. b = 101; // 等价于: this.b = 101;
    26. // 注意:this是当前对象的引用
    27. // 访问父类的成员变量时,需要借助super关键字
    28. // super是获取到子类对象中从基类继承下来的部分
    29. super.a = 200;
    30. super.b = 201;
    31. // 父类和子类中构成重载的方法,直接可以通过参数列表区分清访问父类还是子类方法
    32. methodA(); // 没有传参,访问父类中的methodA()
    33. methodA(20); // 传递int参数,访问子类中的methodA(int)
    34. // 如果在子类中要访问重写的基类方法,则需要借助super关键字
    35. methodB(); // 直接访问,则永远访问到的都是子类中的methodA(),基类的无法访问到
    36. super.methodB(); //访问基类的methodB()
    37. }
    38. }

    2. super的三种用法

    • super.子类中从父类继承的成员变量
    • super.子类中从父类继承的成员方法
    • super( );调用父类的构造方法(在构造方法博客中介绍)

    三. super和this的比较

    1. 相同点

    1. 都是Java中的关键字
    2. 只能在类的非静态方法中使用,用来访问非静态成员方法和字段
    3. 在构造方法中调用时,必须是构造方法中的第一条语句,并且不能同时存在

    2. 不同点

    1. this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是子类对象中从父类继承下来部分成员的引用(注意不是父类的引用,子类继承父类并没有创建父类对象)
    2. 在非静态成员方法中,this用来访问本类的方法和属性,子类对象中如果没有重名现象的发生,this也可以访问到父类继承下来的方法和属性;但super只能用来用来访问父类继承下来的方法和属性

    1. 在构造方法中:this(…)用于调用本类构造方法,super(…)用于调用父类构造方法,两种调用不能同时在构造方法中出现
    2. 子类构造方法中一定会存在super(…)的调用 ,用户没有写编译器也会自动给出;但是要在子类构造方法中调用子类其他构造方法,需要用户手动添加this(…)

    四. 代码块概念以及分类

    使用 { } 定义的一段代码称为代码块。

    根据代码块定义的位置以及关键字,又可分为以下四种:

    • 普通代码块
    • 构造代码块
    • 静态代码块
    • 同步代码块

    1. 普通代码块

    普通代码块:定义在方法中的代码块, 其内的变量只在代码块中有效,这种用法较少见。

    1. public class Main{
    2. public static void main(String[] args) {
    3. {
    4. //直接使用{ }定义,普通方法块
    5. int x = 10 ;
    6. System.out.println("x1 = " +x);
    7. }
    8. int x = 100 ;
    9. System.out.println("x2 = " +x);
    10. }
    11. }

    2. 构造代码块

    定义在类中的代码块(不加修饰符)。

    也叫: 实例代码块 。构造代码块一般用于初始化实例成员变量。

    1. public class Student{
    2. //实例成员变量
    3. private String name;
    4. private String gender;
    5. private int age;
        //实例代码块
    
    1. {
    2. this.name = "xinxin";
    3. this.age = 21;
    4. this.gander = "nan";
    5. System.out.println("I am instance init()!");
    6. }
    7. public void show(){
    8. System.out.println("name: "+name+" age: "+age+" gender: "+gender);
    9. }
    10. }
    11. public class Main {
    12. public static void main(String[] args) {
    13. Student stu = new Student();
    14. stu.show();
    15. }
    16. }

    3. 静态代码块

    使用static定义的代码块称为静态代码块。一般用于初始化静态成员变量。

    1. public class Student{
    2. private String name;
    3. private int age;
    4. private static String classRoom;
        
        //实例代码块
     
    
    1. {
    2. this.name = "xin";
    3. this.age = 21;
    4. System.out.println("I am instance init()!");
    5. }
        // 静态代码块
    
    1. static {
    2. classRoom = "rj2104";
    3. System.out.println("I am static init()!");
    4. }
    5. public static void main(String[] args) {
    6. Student s1 = new Student();
    7. Student s2 = new Student();
    8. }
    9. }

    4. 注意事项

    • 静态代码块不管生成多少个对象,其只会执行一次
    • 静态成员变量是类的属性,因此是在JVM加载类时开辟空间并初始化的
    • 如果一个类中包含多个静态代码块,在编译代码时,编译器会按照定义的先后次序依次执行(合并)
    • 实例代码块只有在创建对象时才会执行
  • 相关阅读:
    Linux中bind9的view(视图解析)配置示例与注意事项
    flutter多渠道打包运行
    【TypeScript】中的函数详解
    使用Jaeger进行分布式跟踪:学习如何在服务网格中使用Jaeger来监控和分析请求的跟踪信息
    JAVAWeb学习1:HTML超文本标记语言
    【java】实现自定义注解校验——方法二
    JDS-12时间继电器
    《SQLite系列》SQLite数据库常用命令大全
    SpringBean生命周期
    全球手机一哥再度回归国内市场,国产手机品牌怕了么?
  • 原文地址:https://blog.csdn.net/guanshengg/article/details/126359266