this
在 Java 语言中,this 用来指定当前实例的对象。this 有一个十分重要的作用就是用来区分对象的成员变量和方法的形参。示例如下:
class Example {
String string;
public Example (String string) {
this.string = string;
}
}
如果将上面的构造方法写成下面的样子将会出现一个 bug,就是通过有参构造方法创建对象之后,成员变量的值仍然是默认值。
class Example {
String string;
public Example (String string) {
string = string;
}
}
之所以出现这样的情况,是因为变量作用域的问题,在方法内部,局部变量能够覆盖成员变量,但是要注意,块级变量是不能覆盖方法级变量的哦。有关变量的作用域范围的知识可以参看笔者的另一篇博客Java中的变量和常量。
如果意外地将方法写成了下面的样子,在一般的编译器里是会出现警告的,一定要及时处理一下。
// 类中有成员变量 String string
void mathod(String string) {
string = string;
}
// warning:The assignment to variable string has no effect
// 警告:对变量 string 的赋值无效
有点跑偏,总结一下就是:使用 this 关键字可以访问到被覆盖的成员变量。
this 只能用在非静态代码块中,使用成员变量时会默认在前面加上 this,随后,哪个对象调用方法, this 就是哪个对象。但是当成员变量和局部变量同名时,不再默认添加 this 关键字,而是就近调用。
this() 调用的是构造方法。
super
super 指代当前对象的超类的对象,根据 this 的作用,可以大致推断出 super 的作用了,那就是可以访问父类中的成员变量和方法,即使父类的成员变量被覆盖或者方法被重写了。另外,super 可以用来调用父类的构造器。
- super.变量名 访问超类的变量
- super.方法名 访问超类的方法
- super() 调用超类的构造方法
Java 规定:
构造派生类对象之前必须构造超类。在派生类的构造方法中,如果不显式调用超类的构造方法,则默认使用 super() 调用超类的无参构造方法。如果显式调用,则不再使用默认调用。
class SuperClass {
// 为超类的构造方法添加一个参数, 目的就是使 JVM 不再提供默认的无参构造方法
public SuperClass(String string) {
// string 没有实际的意义, 就是单纯的表示一个参数
}
}
class SubClass extends SuperClass {
// 这是派生类的构造方法
public SubClass() {
// 理论上, 这里会默认地调用其超类的无参构造方法
// 但是超类中只提供了一个有参的构造方法, 致使程序错误
// Implicit super constructor SuperClass() is undefined. Must explicitly invoke another constructor
}
}
上面程序的错误是:
隐式超构造方法 SuperClass() 是未定义的。必须显式调用另一个构造方法
通过 super 调用父类的构造方法,只能是在子类的构造方法中才被允许。如果子类的构造方法中调用了父类的构造器,那么 super 语句必须写在子类构造方法体的最开始。否则会报错。
public class SubClass extends Base {
public SubClass() {
System.out.println("SubClass");
super();
}
}
// warning:Constructor call must be the first statement in a constructor
public class SubClass extends Base {
public void method() {
super();
System.out.println("this is a method");
}
}
// warning:Constructor call must be the first statement in a constructor
通过上面程序的两处警告,可以发现:构造方法只能在另一个构造方法中调用,而且只能放在第一行调用。