this关键字和super关键字
一:this关键字.
1.1.为什么要用this引用?
看this之前先看一个代码:
public class Student{
private String name;
private String gender;
private int age;
//a.形参名不小心与成员变量名相同,函数体到底给谁赋值?
public void setInfor(String name,String gender,int age){
name=name;
gender=gender;
age=age;
}
public void printInfor(){
System.out.println("name 是:"+name+",gender是:"+gender+",age是:"+age);
}
public static void main(String[] args){
Student s1=new Student();
Student s2=new Student();
/*
b.两个对象都在调用setInfor和printInfor方法,
但是两个方法中没有任何有关对象的说明,
setInfor和printInfor方法如何知道打印的是哪个对象的数据呢?
*/
s1.setInfor("wang","男",21);
s2.setInfor("zhang","女",20);
s1.printInfor();
s2.printInfor();
}
}
这个时候就需要使用this引用了.
1.2.什么是this关键字.
其实,java编译器给每个“成员方法“增加了一个隐藏的引用类型参数,该引用参数指向当前对象(成员方法运行时调用该成员方法的对象),在成员方法中所有成员变量的操作,都是通过该引用去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
public class Student{
private String name;
private String gender;
private int age;
public void setInfor(String name,String gender,int age){
/*
this.name指的就是Student类中的name成员变量方法.
this.name=name语句中第二个name则指的是形参name
实际上setInfor()方法实现的功能就是将name的值赋值给成员变量name.
*/
this.name=name;
this.gender=gender;
this.age=age;
}
public void printInfor(){
System.out.println("name 是:"+this.name+",gender是:"+this.gender+",age是:"+this.age);
}
}
this引用是编译器自动添加的,用户在实现代码时一般不需要显式给出.
注意:this引用的是调用成员方法的对象.
public static void main(String[] args) {
Student s = new Student();
s.setInfor("wang","男",21);
s.printDate();
}
1.3.this引用的特性.
a. this的类型:对应类类型引用,即哪个对象调用就是哪个对象的引用类型
b. this只能在"成员方法"中使用
c. 在"成员方法"中,this只能引用当前对象,不能再引用其他对象,具有final属性
d. this是“成员方法”第一个隐藏的参数,编译器会自动传递,在成员方法执行时,编译器会负责将调用成员方法
对象的引用传递给该成员方法,this负责来接收.
二.super关键字.
2.1super关键字的产生
在设计程序时,子类和父类中可能会存在相同名称的成员,如果在子类的方法中访问父类同名成员时,改如何操作?直接访问肯定是无法做到的,在此,Java提供了super关键字.
2.2 super关键字的使用.
2.2.1 调用成员方法和成员变量
创建父类.
public class Base(){
int a;
int b;
public void methodA(){
System.out.println("Base---methodA()");
}
public void methodB(){
System.out.println("Base---methodB()");
}
}
用子类进行继承
public class Derived extends Base{
int a;
char b;
//与父类中的methodA构成重载
public void methodA(int a){
System.out.println("Derived---methodA(int)");
}
//与父类中的methodB构成重写
public void methodB(){
System.out.println("Derived---methodB()");
}
public void methodC(){
//本类中的成员
a=100;
b=101;
//super关键字调用父类中的成员
super.a=200;
super.b=201;
methodA(100); //调用子类中的methodA()方法,有参数
methodA(); //从父类中继承的methodB()方法,无参数
methodB(); //默认调用子类中的methodB()方法,无参
//这里如果写methodB(),肯定会调用子类自己的方法.
super.methodB(); //用super.调用父类中的methodB()方法
}
public class void main(String[] args){
Derived d=new Derived ();
d.methodC();
/*
输出结果:
Derived---methodA(int)
Base---methodA()
Derived---methodB()
Base---methodB()
*/
}
}
在子类方法中或者子类对象访问成员时,优先访问自己的,自己没有时再到父类中找,如果父类中也没有则报错。
注意:只能在非静态的方法中使用.
//编译时会报错.
public static void error(){
super.a=300;
super.methodA();
}
2.2.2调用构造方法.
子类对象构造时,需要先调用父类的构造方法,然后执行子类的构造方法.(这句话其实不严谨),先看代码,后文中解释.
public class Base{
public Base(){
System.out.println("Base()");
}
}
子类继承父类.
public class Derived extends Base{
public Derived(){
// super();
/*
注意:子类构造方法中默认会调用基类的无参构造方法:super(),
用户没有写时,编译器会自动添加,而且super()必须是子类构造方法中第一条语句,
并且只能出现一次.
*/
System.out.println("Derived()");
}
}
测试类
public class Test {
public static void main(String[] args) {
Derived d = new Derived();
}
//运行结果
Base()
Derived()
}
从运行结果来看,确实是父类构造方法先于子类构造方法执行.
其实,创建对象的时候,先调用的是子类的构造方法,但是子类的构造方法中会用super()调用父类中的无参构造方法,并且永远处于第一行.所以运行结果会出现
先Base(),再Derived().
三 this和super的异同
3.1 相同点
a. 都是Java中的关键字
b. 只能在类的非静态方法中使用,用来访问非静态成员方法和字段
c. 在构造方法中调用时,必须是构造方法中的第一条语句,所以它两不能同时存在
3.2 不同点
a.this是当前对象的引用,当前对象即调用实例方法的对象,super相当于是父类对象的引用.
b.在非静态成员方法中,this用来访问本类的方法和属性,super用来访问父类继承下来的方法和属性.
c. this是非静态成员方法的一个隐藏参数,super不是隐藏的参数
d.成员方法中直接访问本类成员时,编译之后会将this还原,即本类非静态成员都是通过this来访问的;在子类中如果通过super访问父类成员,编译之后在字节码层面super实际是不存在的(通过字节码文件可以验证).
e.在构造方法中:this(…)用于调用本类构造方法,super(…)用于调用父类构造方法,两种调用不能同时在构造方法中出现.
f. 构造方法中一定会存在super(…)的调用,用户没有写编译器也会增加,但是this(…)用户不写则没有.