杰瑞科技汇

java super和this

this 关键字

this 关键字在 Java 中代表当前对象的引用,它可以在类的方法或构造器中使用,主要有以下几个用途:

java super和this-图1
(图片来源网络,侵删)

访问当前对象的成员变量(解决命名冲突)

当方法的形参与类的成员变量同名时,为了避免混淆,可以使用 this 来明确指定访问的是成员变量。

public class Person {
    private String name;
    // 构造器
    public Person(String name) {
        // 这里的 name 是形参,this.name 是成员变量
        // 将形参 name 的值赋给成员变量 name
        this.name = name; 
    }
    public void printName() {
        // 这里的 name 默认是成员变量
        System.out.println("Name: " + this.name); // 使用 this 更清晰,但也可以省略
    }
}

分析: 在构造器 public Person(String name) 中,name 是一个局部变量(形参),如果直接写 name = name;,赋值操作会自己给自己赋值,成员变量 name 的值不会被改变,使用 this.name 就明确表示我们要给当前对象的 name 成员变量赋值。

调用当前对象的成员方法

通常我们直接调用成员方法,printName();,但有时为了代码清晰,或者在某些特殊场景下,可以使用 this 来显式调用。

public class Person {
    public void sayHello() {
        System.out.println("Hello from Person!");
    }
    public void greet() {
        // 直接调用
        sayHello(); 
        // 使用 this 显式调用,效果相同
        this.sayHello(); 
    }
}

调用当前类的其他构造器(构造器重载)

在一个类的构造器中,可以使用 this(...) 来调用该类的其他构造器,这通常用于代码复用,避免在多个构造器中重复编写初始化代码。

java super和this-图2
(图片来源网络,侵删)

重要规则

  • this(...) 必须是构造器中的第一条语句
  • 不能在一个构造器中同时调用 this(...)super(...)
public class Student {
    private String name;
    private int age;
    // 构造器1:只提供名字
    public Student(String name) {
        // 调用构造器2,并传入默认年龄 18
        this(name, 18); 
        System.out.println("Constructor 1 (name only)");
    }
    // 构造器2:提供名字和年龄
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Constructor 2 (name and age)");
    }
    public void displayInfo() {
        System.out.println("Name: " + this.name + ", Age: " + this.age);
    }
}
public class Main {
    public static void main(String[] args) {
        Student s1 = new Student("Alice"); // 会调用构造器1
        s1.displayInfo(); // 输出: Name: Alice, Age: 18
        Student s2 = new Student("Bob", 25); // 会调用构造器2
        s2.displayInfo(); // 输出: Name: Bob, Age: 25
    }
}

执行流程分析

  1. 创建 s1 时,new Student("Alice") 调用了构造器1。
  2. 构造器1的第一条语句是 this("Alice", 18);,所以它立即停止执行,转而去调用构造器2。
  3. 构造器2执行完毕后,返回到构造器1,继续执行 System.out.println(...)
  4. s1 的最终状态是 name="Alice", age=18

super 关键字

super 关键字代表当前对象的父类对象的引用,它主要用于在子类中访问父类的成员(变量、方法、构造器)。

访问父类的成员变量(解决命名冲突)

当子类的成员变量与父类的成员变量同名时,可以使用 super 来访问父类的成员变量。

java super和this-图3
(图片来源网络,侵删)
class Animal {
    protected String name = "Animal";
}
class Dog extends Animal {
    private String name = "Dog";
    public void printNames() {
        System.out.println("Dog's name: " + this.name); // 访问子类的 name
        System.out.println("Animal's name: " + super.name); // 访问父类的 name
    }
}
public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog();
        myDog.printNames();
    }
}

输出:

Dog's name: Dog
Animal's name: Animal

调用父类的成员方法

当子类重写了父类的方法时,如果想在子类的方法中调用父类的原始版本,可以使用 super

class Vehicle {
    public void move() {
        System.out.println("Vehicle is moving.");
    }
}
class Car extends Vehicle {
    @Override
    public void move() {
        // 先调用父类的 move 方法
        super.move(); 
        // 再添加自己的行为
        System.out.println("Car is driving on the road.");
    }
}
public class Main {
    public static void main(String[] args) {
        Car myCar = new Car();
        myCar.move();
    }
}

输出:

Vehicle is moving.
Car is driving on the road.

调用父类的构造器

在创建子类对象时,JVM 会先隐式或显式地调用父类的构造器,来初始化父类继承下来的成员,使用 super(...) 可以显式地指定调用父类的哪个构造器。

重要规则

  • super(...) 必须是子类构造器中的第一条语句
  • 如果子类构造器中没有显式调用 super(...),编译器会自动添加一个 super(); 来调用父类的无参构造器。
  • 如果父类没有无参构造器,而子类也没有显式调用 super(...),则编译会出错。
class Father {
    public Father() {
        System.out.println("Father's no-arg constructor");
    }
    public Father(String message) {
        System.out.println("Father's arg constructor: " + message);
    }
}
class Son extends Father {
    // 子类构造器1:隐式调用父类的无参构造器
    public Son() {
        // 等价于 super(); (必须放在第一行)
        System.out.println("Son's no-arg constructor");
    }
    // 子类构造器2:显式调用父类的带参构造器
    public Son(String message) {
        super("Hello from Son"); // 显式调用,必须放在第一行
        System.out.println("Son's arg constructor");
    }
}
public class Main {
    public static void main(String[] args) {
        System.out.println("--- Creating Son object 1 ---");
        Son s1 = new Son();
        System.out.println();
        System.out.println("--- Creating Son object 2 ---");
        Son s2 = new Son("Custom Message");
    }
}

输出:

--- Creating Son object 1 ---
Father's no-arg constructor
Son's no-arg constructor
--- Creating Son object 2 ---
Father's arg constructor: Hello from Son
Son's arg constructor

thissuper 的核心区别与联系

特性 this super
含义 当前对象的引用 当前对象父类对象的引用
指向 指向本类的对象 指向父类的对象
使用场景 访问本类成员变量(解决重名)
访问本类成员方法
调用本类其他构造器
访问父类成员变量(解决重名)
调用父类成员方法
调用父类构造器
构造器调用 this(...) super(...)
位置限制 必须在构造器第一条语句 必须在构造器第一条语句
与继承关系 不依赖于继承,任何类都可以使用 只在继承关系中才有意义

总结与最佳实践

  1. 明确指向this 指向自己,super 指向父亲,记住这个核心区别,就不会用混。
  2. 构造器链:在继承体系中,对象的创建是一个自上而下的过程,父类先被初始化,然后才是子类。super 是这个链条的显式体现。
  3. 代码清晰:虽然有时 thissuper 可以省略(如访问成员变量),但在容易产生混淆的地方(如构造器、形参与成员变量同名时),显式写出它们可以让代码更清晰、更易于维护。
  4. 构造器规则:牢记 this(...)super(...) 都必须是构造器中的第一条语句,并且不能同时出现,这是 Java 语言硬性规定的语法。

理解 thissuper 是掌握 Java 面向对象编程,特别是继承机制的关键,它们是连接类与类、对象与对象之间关系的桥梁。

分享:
扫描分享到社交APP
上一篇
下一篇