## Java编程那些事儿67——this和super
陈跃峰
出自:[http://blog.csdn.net/mailbomb](http://blog.csdn.net/mailbomb)
### 8.8 this和super
下面再来介绍一下this和super关键字的使用。在程序中通过使用this和super关键字,可以实现对于类内部很多内容方便的引用,也有助于理解面向对象的实现原理,更方便的理解面向对象技术的内部实现。
#### 8.8.1 this关键字
this关键字代表自身,在程序中主要的使用用途有以下几个方面:
1. 使用this关键字引用成员变量
2. 使用this关键字在自身构造方法内部引用其它构造方法
3. 使用this关键字代表自身类的对象
4. 使用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关键字可以在子类中引用父类中的内容。主要的使用形式有以下几种:
1. 在子类的构造方法内部引用父类的构造方法
2. 在子类中调用父类中的成员方法
3. 在子类中调用父类中的成员变量
##### 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都是非静态的,所以这两个关键字都无法在静态方法内部进行使用。
- 前言
- (1)序言
- (2)程序设计是什么?
- (3)你适合学习程序设计吗?
- (4)如何学好程序设计?
- (5)程序设计介绍小结
- (6)计算机软件基本概念
- (7)进制的概念
- (8)计算机内部的数据表达
- (9)网络编程基础
- (10)Java语言简介
- (11)JDK的获得、安装和配置
- (12)第一个HelloWorld程序
- (13)Eclipse基本使用
- (14)Eclipse基础使用进阶
- (15)如何学好Java语法
- (16)代码框架、关键字和标识符
- (17)基本数据类型
- (18)变量和常量
- (19)数据类型转换
- (20)空白、语句结束和注释
- (21)算术运算符
- (22)比较运算符
- (23)逻辑运算符
- (24)赋值运算符
- (25)位运算符
- (26)移位运算符
- (27)其它运算符
- (28)运算符优先级
- (29)表达式
- (30)流程控制基础
- (31)if语句语法(1)
- (32)if语句语法(2)
- (33)if语句语法(3)
- (34)switch语句语法
- (35)while语句语法
- (36)do-while语句语法
- (37)for语句语法
- (38)break和continue语句
- (39)流程控制综合示例1
- (40)流程控制综合示例2
- (41)流程控制综合示例3
- (42)流程控制综合练习
- (43)数组概述
- (44)数组基础语法
- (45)数组使用示例1
- (46)数组使用示例2
- (47)数组使用示例3
- (48)多维数组基础
- (49)多维数组使用示例1
- (50)多维数组使用示例2
- (51)多维数组练习
- (52)方法声明
- (53)方法声明示例
- (54)方法调用
- (55)方法重载和参数传递
- (56)方法练习
- (57)面向对象基础
- (58)类(一)
- (59)类(二)
- (60)对象
- (61)面向对象设计方法和面向对象特性(一)
- (62)继承(二)
- (63)多态性
- (64)访问控制符、修饰符和其它关键字
- (65)static修饰符
- (66)final修饰符
- (67)this和super
- (68)抽象类和接口(一)
- (69)抽象类和接口(二)
- (70)抽象类和接口(三)
- (71)内部类简介
- (72)包的概念
- (73)JDK文档使用
- (74)java.lang包介绍1
- (75)String类使用
- (76)StringBuffer类和System类
- (77)包装类
- (78)时间和日期处理
- (79)Random随机处理
- (80)集合框架简述
- (81)异常处理概述
- (82)异常处理语法1
- (83)异常处理语法2
- (84)IO简介
- (85)IO类体系
- (86)文件操作之File类使用
- (87)文件操作之读取文件
- (88)文件操作之写文件
- (89)读取控制台输入
- (90)装饰流使用1
- (91)装饰流使用2
- (92)IO使用注意问题
- (93)多线程基础
- (94)多线程实现方式1
- (95)多线程实现方式2
- (96)多线程使用示例1
- (97)多线程使用示例2
- (98)多线程问题及处理1
- (99)多线程问题及处理2
- (100)多线程问题及处理3
- (101)网络编程概述
- (102)网络编程技术1
- (103)网络编程技术2
- (104)网络编程技术3
- (105)网络编程技术4
- (106)网络编程技术5
- (107)网络协议概念
- (108)网络编程示例1
- (109)网络编程示例2
- (110)网络编程小结