this & super
this关键字
1. 构造器(构造方法)
首先介绍类中的构造器
作用:
- 使用new关键字,本质是在调用构造器
- 用来初始化值
public class Box {
double width;
double height;
double depth;
// 实例化初始值
// 无参构造
public Box() {
}
// 有参构造:一旦定义了有参构造,无参就必须显式定义
public Box(double width, double height, double depth) {
this.width = width;
this.height = height;
this.depth = depth;
}
public Box(double width, double height) {
this.width = width;
this.height = height;
}
IDEA生成构造器快捷键:alt + insert
this在构造器中的作用:
隐藏实例变量
在Java中,不能在同一个作用域或在所包含的作用域内声明两个同名的局部变量,但局部变量(包括方法的形参)可以和类的实例变量重名。当局部变量和实例变量具有相同的名称时,局部变量会隐藏实例变量。
Box (double width, double height, double depth) {
this.width = width;
this.height = height;
this.depth = depth;
}
这篇文章介绍得很清楚:【Java】还不懂this关键字?一分钟彻底弄懂this关键字
2. 调用重载的构造函数
当使用重载的构造函数时,有时可以在一个构造函数中调用另一个构造函数。一般形式:
this(arg-list)
- 没有使用
this()
的类:
class MyClass {
int a;
int b;
// 单独初始化a和b
MyClass(int i, int j) {
a = i;
b = j;
}
// 将a和b初始化为同一个值
MyClass(int i) {
a = i;
b = i;
}
// 设置a和b的默认值
MyClass() {
a = 0;
b = 0;
}
}
- 使用
this()
改写MyClass类:
class MyClass {
int a;
int b;
// 单独初始化a和b
MyClass(int i, int j) {
a = i;
b = j;
}
// 将a和b初始化为同一个值
MyClass(int i) {
this(i, i); // 调用方法 MyClass(i, i)
}
// 设置a和b的默认值
MyClass() {
this(0); // 调用方法 MyClass(0)
}
}
通过this()
调用重载的构造函数的作用:
有助于阻止不必要的重复代码。许多情况下,减少重复代码可以降低加载类所需的时间。
但是,相比于包含所有内联初始化代码的构造函数,调用this()
的构造函数执行速度会更慢。
限制:
- 使用
this()
时不能使用当前类的任何实例变量; - 不能再同一个构造函数中同时使用
super()
和this()
,因为它们都必须是构造函数中的第一条语句。
super关键字
super在继承中的两种用法:
- 调用超类的构造函数
- 访问超类中被子类的某个成员隐藏的成员
1. 使用 super 调用超类的构造函数
一般形式:super(arg-list)
arg-list
是超类中构造函数需要的全部参数
class Box {
private double width;
private double height;
private double depth;
Box(Box ob) {
width = ob.width;
height = ob.height;
depth = ob.depth;
}
Box(double w, double h, double d) {
width = w;
height = h;
depth = d;
}
double volume() {
return width * height * depth;
}
}
class BoxWeight extends Box {
double weight;
BoxWeight(BoxWeight ob) {
// 调用Box类的Box(Box ob)构造函数
super(ob);
weight = ob.weight;
}
BoxWeight(double w, double h, double d, double m) {
// 调用Box类的Box(double w, double h, double d)构造函数
super(w, h, d);
weight = m;
}
}
public class DemoSuper {
public static void main(String[] args) {
BoxWeight mybox = new BoxWeight(10, 20, 15, 34.3);
double vol;
vol = mybox.volume();
System.out.println("体积为: " + vol);
System.out.println("质量为: " + mybox.weight);
// 所有不同传参的构造器均同理
}
}
Output:
体积为: 3000.0
质量为: 34.3
注:
- 为
super()
传递的是BoxWeight
类型的对象,而不是Box
类型的对象,这仍然会调用Box(Box ob)
构造函数。 super()
总是引用调用类的直接超类(即extends哪个类,就调用哪个类);即使在多层次继承中也如此。super()
必须是子类构造函数中执行的第一条语句。
2. 使用 super 访问超类中被子类的某个成员隐藏的成员
super.member
member
既可以是方法,也可以是实例变量
class A {
int i;
}
class B extends A {
int i; // 同名,隐藏了 A 中的 i
B(int a, int b) {
super.i = a; // A 中的 i
i = b; // B 中的 i
}
void show() {
System.out.println("super.i = " + super.i);
System.out.println("i = " + i);
}
}
public class UseSuper {
public static void main(String[] args) {
B subOb = new B(1, 2);
subOb.show();
}
}
Output:
super.i = 1
i = 2
this和super比较
- super
- super 调用父类的构造方法,必须在构造方法的第一个
- super 必须只能出现在子类的方法或者构造方法中
- super 和 this 不能同时调用构造方法,因为它们都必须是构造函数中的第一条语句
- this
- 代表对象不同:
this
:本身调用这个对象
super
:代表父类对象的引用 - 前提:
this
:没有继承也可以使用
super
:只能在继承条件下才能使用 - 构造方法:
this();
本类的构造
super();
父类的构造
- 代表对象不同: