Java编程那些事儿——this和super
8.8 this和super
下面介绍一下this和super关键字的使用。在程序中通过使用this和super关键字,可以实现对于类内部很多内容方便的引用,也有助于理解面向对象的实现原理,更方便的理解面向对象技术的内部实现。
8.8.1 this关键字
this关键字代表自身,在程序中主要的使用用途有以下几个方面:
l 使用this关键字引用成员变量
l 使用this关键字在自身构造方法内部引用其它构造方法
l 使用this关键字代表自身类的对象
l 使用this关键字引用成员方法
8.8.1.1引用成员变量
在一个类的方法或构造方法内部,可以使用“this.成员变量名”这样的格式来引用成员变量名,有些时候可以省略,有些时候不能省略。首先看一下下面的代码:
/**
*使用this引用成员变量
*/
public class ReferenceVariable {
private int a;
public ReferenceVariable(int a){
this.a = a;
}
public int getA(){
return a;
}
public void setA(int a){
this.a = a;
}
}
在该代码的构造方法和setA方法内部,都是用this.a引用类的成员变量。因为无论在构造方法还是setA方法内部,都包含2个变量名为a的变量,一个是参数a,另外一个是成员变量a。按照Java语言的变量作用范围规定,参数a的作用范围为构造方法或方法内部,成员变量a的作用范围是类的内部,这样在构造方法和setA方法内部就存在了变量a的冲突,Java语言规定当变量作用范围重叠时,作用域小的变量覆盖作用域大的变量。所以在构造方法和setA方法内部,参数a起作用。
这样需要访问成员变量a则必须使用this进行引用。当然,如果变量名不发生重叠,则this可以省略。
但是为了增强代码的可读性,一般将参数的名称和成员变量的名称保持一致,所以this的使用频率在规范的代码内部应该很多。
8.8.1.2引用构造方法
在一个类的构造方法内部,也可以使用this关键字引用其它的构造方法,这样可以降低代码的重复,也可以使所有的构造方法保持统一,这样方便以后的代码修改和维护,也方便代码的阅读。
下面是一个简单的示例:
/**
*使用this关键字引用构造方法
*/
public class ReferenceConstructor {
int a;
public ReferenceConstructor(){
this(0);
}
public ReferenceConstructor(int a){
this.a = a;
}
}
这里在不带参数的构造方法内部,使用this调用了另外一个构造方法,其中0是根据需要传递的参数的值,当一个类内部的构造方法比较多时,可以只书写一个构造方法的内部功能代码,然后其它的构造方法都通过调用该构造方法实现,这样既保证了所有的构造是统一的,也降低了代码的重复。
在实际使用时,需要注意的是,在构造方法内部使用this关键字调用其它的构造方法时,调用的代码只能出现在构造方法内部的第一行可执行代码。这样,在构造方法内部使用this关键字调用构造方法最多会出现一次。
8.8.1.3代表自身对象
在一个类的内部,也可以使用this代表自身类的对象,或者换句话说,每个类内部都有一个隐含的成员变量,该成员变量的类型是该类的类型,该成员变量的名称是this,实际使用this代表自身类的对象的示例代码如下:
/**
*使用this代表自身类的对象
*/
public class ReferenceObject {
ReferenceObject instance;
public ReferenceObject(){
instance = this;
}
public void test(){
System.out.println(this);
}
}
在构造方法内部,将对象this的值赋值给instance,在test方法内部,输出对象this的内容,这里的this都代表自身类型的对象。
8.8.1.4引用成员方法
在一个类的内部,成员方法之间的互相调用时也可以使用“this.方法名(参数)”来进行引用,只是所有这样的引用中this都可以省略,所以这里就不详细介绍了。
8.8.2 super关键字
super关键字的中文意思是超级的,使用super关键字可以在子类中引用父类中的内容。主要的使用形式有以下几种:
l 在子类的构造方法内部引用父类的构造方法
l 在子类中调用父类中的成员方法
l 在子类中调用父类中的成员变量
8.8.2.1引用父类构造方法
在构造子类对象时,必须调用父类的构造方法。而为了方便代码的编写,在子类的构造方法内部会自动调用父类中默认的构造方法。但是如果父类中没有默认的构造方法时,则必须手动进行调用。
使用super可以在子类的构造方法内部调用父类的构造方法。可以在子类的构造方法内部根据需要调用父类中的构造方法。
使用super关键字调用父类构造方法的示例代码如下:
//文件名:SuperClass.java
public class SuperClass {
public SuperClass(){}
public SuperClass(int a){}
}
//文件名:SubClass.java
public class SubClass extends SuperClass {
public SubClass(){
super(); //可省略
}
public SubClass(int a){
super(a);
}
public SubClass(String s){
super(); //可省略
}
}
在该示例代码中,SubClass继承SuperClass类,在SubClass类的构造方法内部可以使用super关键字调用父类SubClass的构造方法,具体调用哪个构造方法没有限制,可以在子类内部根据需要进行调用,只是根据调用的构造方法不同传入适当的参数即可。
由于SubClass类的父类SuperClass内部有默认的构造方法,所以SubClass的构造方法内部super()的代码可以省略。
和使用this关键字调用构造方法一样,super调用构造方法的代码只能出现在子类构造方法中的第一行可执行代码。这样super调用构造方法的代码在子类的构造方法内部则最多出现一句,且不能和this调用构造方法的代码一起使用。
8.8.2.2引用父类成员方法
在子类中继承了父类中的成员方法,一般可以直接通过方法名使用,但是如果在子类中覆盖了父类的成员方法以后,如果需要在子类内部调用父类中被覆盖的成员方法时则不能直接调用了,这样就又需要使用super关键字了。
示例代码如下:
//文件名:SuperClass2.java
public class SuperClass2 {
public void test(){}
public void print(int a){
System.out.println("SuperClass2: " + a);
}
}
//文件名:SubClass2
public class SubClass2 extends SuperClass2 {
public void print(int a){
super.print(a);
System.out.println("SubClass2");
}
public void t(){
super.test(); //super可省略
super.print(0); //不可省略
}
}
8.8.2.3引用父类成员变量
在子类中如果引用父类的成员变量,也可以使用“super.成员变量”来引用,只是一般成员变量的覆盖是没有意义的,所以这个时候都可以直接使用成员变量名进行引用,所以这里的super都可以省略。
8.8.3注意的问题
最后,在实际使用this和super时,除了上面介绍到的需要注意的问题以外,还需要特别注意的是,this和super都是非静态的,所以这两个关键字都无法在静态方法内部进行使用。