在Java编程中,this
和super
是两个非常关键的关键字,它们各自有独特的作用和用途。理解这两个关键字对于掌握Java面向对象编程非常重要。
this关键字
this
关键字用于引用当前对象。它可以用于以下场景:
- 解决成员变量与局部变量名冲突:当局部变量与成员变量同名时,可以通过
this
关键字来区分。 - 在构造器中调用另一个构造器:一个构造器内部可以通过
this()
调用另一个构造器(必须是第一条语句)。 - 返回当前对象的引用:在一些情况下,
this
可以用于返回当前对象的引用。 - 在继承关系的条件下,如果子类没有和父类一样的非私有属性和方法(访问修饰是默认、
protected
或public
的),子类可以通过this调用父类的属性和方法。其实在继承关系下,父类的非私有的属性和方法在子类中都可以直接调用,非继承关系但在同一个包的条件下,其他类也可以通过创建对象(你想访问的对象)调用他的非私有成员(属性和方法)
示例:
public class Example {
private int number;
// 构造器1
public Example() {
this(0); // 调用构造器2
}
// 构造器2
public Example(int number) {
this.number = number; // 解决局部变量与成员变量名冲突
}
public Example getInstance() {
return this; // 返回当前对象的引用
}
public void printNumber() {
System.out.println(this.number);
}
public static void main(String[] args) {
Example example = new Example(5);
example.printNumber(); // 输出5
}
}
super关键字
super
关键字用于引用当前对象的直接父类(超类)。它可以用于以下场景:
- 访问父类的成员(字段和方法):当子类隐藏(重写)了父类的成员时,可以通过
super
来访问父类的成员。 - 调用父类的构造器:在子类的构造器中,
super()
用于调用父类的构造器(必须是第一条语句,如果父类没有无参构造器,则必须显式调用)。 - 在继承关系的条件下,如果子类没有和父类一样的非私有属性和方法(访问修饰是默认、
protected
或public
的),子类可以通过super调用父类的属性或方法。其实在继承关系下,父类的非私有的属性和方法在子类中都可以直接调用。
示例:
class Parent {
private String name = "Parent";
public Parent() {
System.out.println("Parent constructor called");
}
public void printName() {
System.out.println(name);
}
}
public class Child extends Parent {
private String name = "Child";
// 调用父类的构造器
public Child() {
super(); // 必须是第一条语句
System.out.println("Child constructor called");
}
// 隐藏父类的方法
@Override
public void printName() {
super.printName(); // 调用父类的方法
System.out.println(this.name);
}
public static void main(String[] args) {
Child child = new Child();
child.printName();
// 输出:
// Parent constructor called
// Child constructor called
// Parent
// Child
}
}
解释:为什么会输出 Parent constructor called 和 Child constructor called 两条语句?
因为在创建Child对象时调用了子类Child的无参构造方法,而子类的无参构造方法又调用父类Parent的无参构造方法,不理解的小伙伴可以看看另一期刊:
面向对象的三大特征-CSDN博客
例题1:问Father类和Son类中通过this和super都可以调用哪些属性和方法?
public class Grand {
String name="爷爷";
private int age = 88;
public void method(){}
}
class Father extends Grand{
String id ="01";
private double score;
public void work(){
//方法体内this可以访问哪些成员?
// super可以访问哪些成员?
}
}
class Son extends Father{
String name="儿子";
public void study(){}
private void show(){
//方法体内this可以访问哪些成员?
// super可以访问哪些成员?
}
}
答案:
- Father类this调用的成员:
//调用Grand类
this.name; //调用Grand类的name
this.method(); //调用Grand类方法
//下面都是调用本类的成员
this.id;
this.score=100.0;
this.work();
- Father类super 调用的成员:
//调用父类Grand的非私有成员
super.name;
super.method();
解释: 在继承关系的条件下,子类Father没有和父类Grand一样的非私有属性(name),所以可以用this.name调用父类的属性,即使你不使用this或super
,只要父类的属性不是private
的,子类也可以直接访问它,因为子类继承了父类的默认、protected
和public
成员。
- Son类this调用的成员:
this.name; //注意:因为子类有和父类Grand一样的属性name,所以调用的是自己的name属性
this.id; //调用父类Father的属性id
this.method(); //调用父类Grand非私有method方法
this.work();//调用父类Father非私有work方法
this.show();//递归调用
this.study();//调用本类的方法
- Son类super调用的成员:
//调用父类Grand的非私有成员
super.name;
super.method();
//调用父类Father的非私有成员
super.id;
super.work();
解释:super关键字是从父类开始查找成员,例如先查找Son的父类Father的成员,如果没有Father类没有name属性,那么就往上继续查找Grand类的name属性,如果有则返回,没有则报错!
例题2: 下面代码的输出结果是什么?
public class Father {
String name ="Rose";
Father(){
System.out.println("调用Father()无参构造方法。。");
}
Father(String name){
this.name=name;
}
}
class Son extends Father{
String name="Jack";
Son(){
super();
System.out.println("调用Son()无参构造方法。。");
}
Son(String name){
super(name);
}
public void test(){
System.out.println(super.name);
System.out.println(this.name);
}
public static void main(String[] args) {
new Son().test();//匿名对象:仅使用一次,用完后废弃
new Son("john").test();
}
}
答案:
调用Father()无参构造方法。。
调用Son()无参构造方法。。
Rose
Jack
john
Jack
解释:
- new Son()创建对象时调用子类无参构造器,但在调用子类无参构造器之前会默认父类的无参构造器 ,所以第一句输出:调用Father()无参构造方法。。
- 在test方法中输出父类和子类name属性
- new Son("john")调用子类的有参构造器,方法体中写了super(name);调用父类的有参构造器(如果不写 super(name);会默认调用父类的无参构造器),然后将John 传给了父类属性,此时Father类的name是John
- 在test方法中输出父类和子类name属性(即John和Jack)
区别总结
- 作用对象:
this
引用当前对象,super
引用当前对象的直接父类。 - 用途:
this
主要用于解决成员变量与局部变量名冲突、调用另一个构造器、返回当前对象的引用;super
主要用于访问父类的成员(字段和方法)、调用父类的构造器。 - 使用场景:
this
通常用于当前类内部,super
通常用于子类内部访问父类。 - 在继承关系的条件下,如果子类没有和父类一样的非私有属性和方法(访问修饰是默认、
protected
或public
的),子类可以通过this或super调用父类的属性和方法。其实在继承关系下,父类的非私有的属性和方法在子类中都可以直接调用