对this关键字和super关键字的总结
对java面向对象中的this和super关键字进行复习。
1、this关键字
this
是一个关键字,翻译为:这个。this
是一个引用,this变量中保存了内存地址指向自身
,this存储在JVM内存java对象内部。
每创建100个java对象,每一个对象都有this
,也就说有100个不同的this
。this
可以实现出现在“实例方法中”当中,this指向当前正在执行这个动作的对象
1.1、this关键字的用法
- 通过
this.属性
来表示当前类的实例变量 - 通过
this.(参数列表)
来表示调用当前类的成员方法 - 通过
this(参数列表)
表示通过当前的构造方法去调用另一个本类的构造方法
1.2、this代码实现分析
1 |
|
1 |
|
1.3、this调用顺序
见下面的super调用顺序总结。
2、super关键字
2.1、super关键字的用法
在Java中,super关键字有三种用法,分别是:
- 通过super.属性来访问父类中的成员变量
1 |
|
- 通过super.(参数列表)来访问父类中的成员方法
1 |
|
- 通过super(参数列表)来访问父类中的构造方法创建对象。
1 |
|
注意:子类无法通过super关键字访问父类中private修饰的属性和方法,因为private修饰的属性和方法只能在当前类的内部进行访问在子类的构造器中通过super关键字调用父类的构造器时,super关键字必须出现在构造器的第一行且仅能出现一次
2.2、super调用的顺序
在正常情况下(不使用this或者super关键字):当我们再子类中调用某方法时,如果子类存在需要该方法时,直接调用即可。如果子类中不存在该方法,则向上寻找父类,如果父类中存在该方法,则调用父类中的方法若父类中不存在该方法,那么向上寻找父类的父类,直到找到Object类
注意:如果直到Object类依然没有找到该方法,那么会提示方法不存在
;但如果向上找到了这个方法但没有权限访问(例如该方法被private修饰),则会产生错误
。
1 |
|
在上述代码中,子类中的func1()
方法在调用func2()
方法时,会先在子类中查找是否存在func2()方法,未找到时会在其父类中查找func2()
方法。
如果我们使用this关键字进行调用,func2()
将改为 this.func2()
; 此时语义未发生改变,依然会先在子类中查找,没有找到时会在其父类中查找。
当我们使用super关键字,改为 super.func2()
这时语义就发生了变化,上面提到过,super.方法名()
调用的是父类中的方法。所以这条语句就不会检测当前类中是否存在func2()
方法,只会从父类开始向上进行检测。
如果我们有重复的方法该怎么进行调用(就近原则),当子类要访问上级类的某个成员,而子类的多个上级类都有该成员时,我们对super关键字的使用采用就近原则,也就是访问super关键字向上找到的第一个成员。(this和super同样遵守就近原则)
3、this和super的异同
3.1、相同点
- 二者都能出现在实例方法或者构造方法中(不能出现在静态方法中);
- 二者的语法都是
this.
,this()
,super.
,super()
; - 大部分情况下可以省略,但是在区分局部变量或者实例变量的时候不可省略;
- 只能出现在构造方法的第一行(二者不能共同出现)。
3.2、不同点
区别点 | this | super |
访问属性 | 访问本类中的属性,如果本类没有属性则从父类中继续查找 | 访问父类中的属性 |
调用方法 | 访问本类中的方法,如果本类没有此方法则从父类继续查找 | 直接访问父类中的方法 |
调用构造器 | 调用本类构造器,必须放在构造器首行 | 调用父类构造器,必须放在子类构造器的首行 |
特殊 | 表示当前对象 | 子类访问父类对象 |
4、默认存在的super
当一个构造方法第一行既没有this()又没有super()的话,默认会有一个super();表示通过当前子类构造方法调用父类的无参数构造方法。所以必须保证父类的无参数构造方法是存在的。无论怎样折腾,父类的构造方法是一定会执行的(100%)。
5、二者不共存(构造函数冲突)
如果想用super继承父类构造的方法,但是没有放在第一行的话,那么在super之前的语句,肯定是为了满足自己想要完成某些行为的语句,但是又用了super继承父类的构造方法。那么以前所做的修改就都回到以前了,就是说又成了父类的构造方法了。
this和super不能同时出现在一个构造函数里面,因为this必然会调用其它的构造函数,其它的构造函数必然也会有super语句的存在,所以在同一个构造函数里面有相同的语句,就失去了语句的意义,编译器也不会通过。
6、为什么静态方法中不能使用this和super方法
静态方法是存储在静态区内的,静态区会随着类加载器一起加载到内存当中,这时候,只是加载到内存当中,但是并没有真正的去运行,此时也就没有产生实例化的对象。
然而this是表示当前对象的,super表示父类对象的,两个关键字和对象是关联起来的。这时候,连实例化的对象都没有产生,所以this和super也就不存在。
以下是理解:
首先,static叫静态方法,也叫类方法,它先于任何的对象出现。在程序最开始启动(JVM初始化)的时候,就会为static方法分配一块内存空间,成为静态区,属于这个类。而非static方法,必须在类实例化的时候,才会给分配内存空间,在实例化对象的时候JVM在堆区分配一个具体的对象,this指针指向这个对象。也就是说,this指针是指向堆区中的类的对象,而static域不属于this指向的范围所在,所以不能调用。
同时,在static修饰的方法中,不能使用super(),道理其实与上面差不多。
super代表子类对父类满参构造函数的初始化,也是需要产生对象才可以使用但是考虑到虚拟机加载顺序为先加载类,当被实例化才产生对象。所以如果并存则表示类和对象同时加载,显然是不合逻辑的。