this&super
一、 this
this
关键字表示调用的是当前类的成员变量或者成员方法- 一般情况下,可以省略
this
关键字直接调用成员变量以及成员方法 - 但当方法的形参与成员变量同名时,如果要在方法内使用成员变量,必须添加this关键字指明使用的是当前类的成员变量
- 一般情况下,可以省略
- 使用
this
访问成员变量和方法时,如果在当前类中未找到,会从父类(甚至顺着继承关系继续从父类的父类)中查找(子类会继承父类中所有可以被继承的成员变量和方法) this
关键字只能在非static
方法中使用(static
属性修饰的变量或方法在当前类的对象实例化前就已经存在了)- 通过
this()
或者this(参数)
调用当前类的其他构造方法时:- 不能递归调用
- 只能在构造方法首行出现
二、 super
super
关键字表示调用的是父类的成员变量或者成员方法- 一般情况下,可以省略
super
关键字直接调用父类的成员变量以及成员方法 - 如果子类没有重写父类的方法,只要权限修饰符允许,在子类中完全可以直接调用父
类的方法; - 但当子类的成员变量与父类的成员变量同名、方法的形参与父类成员变量同名或者子类的方法重写了父类的方法时,如果要在子类中使用父类的成员变量或者方法,必须添加super关键字指明调用的是父类中的成员变量或者方法(否则默认调用的是当前类自己的成员变量或者方法)
- 一般情况下,可以省略
- 使用
super
访问父类的成员变量和方法时,如果在直接父类中未找到,会顺着继承关系继续从父类的父类中查找,直至找到(如果一直到Object类都找不到则抛出异常) super
关键字只能在非static
方法中使用- 通过
super()
或者super(参数)
调用父类的构造方法时:- 不能递归调用
- 只能在构造方法首行出现(因此在构造方法中,不可能同时显式调用父类构造方法和当前类的其他构造方法,因为这二者都要求在构造方法的首行出现)
三、 总结
-
子类构造方法
- 子类的任何一个构造方法,必须引用且只能引用一个其他构造方法(当前类中其他重载的构造方法或者父类的构造方法)
- 若子类构造方法的首行既没有通过
this
关键字显式调用当前类的其他构造方法,也没有通过super
关键字显式调用父类的构造方法,则子类此构造方法默认隐式调用super()
,即调用父类中无参的构造方法 - 如果子类构造方法中既未显式调用父类或当前类的构造方法,且父类中又没有空参的构造方法,则编译出错
-
调用成员方法时
-
方法前面没有
super
和this
,先从当前类找,如果没有从直接父类找,再没有顺着继承关系继续往上找 -
方法前面有
super
,从当前类的直接父类找,如果没有继续往上找 -
方法前面有
this
,先从当前类找匹配方法,如果没有再从直接父类找,再没有继续往上找
-
-
调用成员变量时
- 变量前面没有
super
和this
, 在构造方法、代码块、成员方法中时,先看是否是当前块中声明的局部变量,如果不是局部变量再去找当前类中的成员变量;如果从当前类中没有找到,再找直接父类中的成员变量,如果直接父类中没有找到再继续往上找 - 变量前面有
super
,从当前类的直接父类找,如果没有继续往上找 - 变量前面有
this
, 先从当前类找匹配的成员变量,如果没有再从直接父类找,再没有继续往上找
- 变量前面没有
四、 笔/面试题
-
问:下列代码的执行结果
public class Main { public static void main(String[] args) { User user = new User(); } } class Person { public Person() { System.out.println("this is person class"); } } class User extends Person { }
答:当子类构造方法不显式调用当前类的其他构造方法以及父类构造方法时,会隐式调用父类的无参构造方法。因此当实例化
User
类时,会隐式的调用父类中的无参构造方法,因此输出结果为this is person class
-
问:下列语句的执行结果
class Person { public int age; public Person() { System.out.println("this is person class"); } } class User extends Person { public User() { } public User(int age) { this(); super(); } }
答:
super()
和this()
不能同时出现在一个构造方法中,因此上述代码在编译期间便会报错。