Java是面向对象编程的,我们操作都是一个个对象,每个对象通过new生成,A a = new A(); 类A被new出来之后就在堆上分配了一定的空间。而在栈上会保存一个句柄引用a,引用a指向的就是这个对象的堆数据区域,通过这个句柄a就能对该引用指向的对象进行操作。在一个对象内部,需要进行内部调用的时候,java提供了一个this关键字来表示当前对象或者是“本对象”。
关键字this的使用场景
1.构造方法
构造方法是一个类的对象在通过new关键字创建时自动调用的,在程序中不能向调用其他方法一样通过方法名(也就是类名)来调用。但如果一个类有多个构造方法,可以在一个构造方法中通过this(a…)来调用其他的构造方法。
class A {
A() {
this(1);
}
A(int a){
this();
}
A(int a, int b) {
this(1, 2);
}
}
但是要注意一些问题:
1. 在通过this关键字调用构造器是,不能重复调用多个。如以下调用回出现错误提示。
public Test() {
}
public Test(int a) {
this(a, a);
}
public Test(int a , int b) {
this();
//this(1); 提示 call to this() must be first statement in Constructor body;
}
- 不能通过this关键字直接或者间接的调用该构造方法本身,因为这样会进行进行递归调用,进入死循环。代码如下:
public Test() {
}
public Test(int a) {
this(a, a); //编辑器会提示 Recursive Constructor invocation 构造器递归调用
}
public Test(int a , int b) {
this(a);
}
Test(int a)里面调用了this(a,a)也就是调用了Test(int a, int b),而Test(int a, int b)里面又调用了Test(int a).形成了递归调用。
2.调用本类中的变量和方法
可以调用本类中任何修饰符修饰的成员变量和方法。
3.在继承中的this的使用
先给出父类代码:
public class Parent {
public String str;
public Parent(){
this(1);
System.out.println("Parent()");
}
public Parent(int a) {
this.str = "Parent";
System.out.println("Parent(int a)");
this.show();
}
public void show() {
System.out.println(this.str);
}
}
再给出子类代码:
public class Child extends Parent {
public String str;
public Child(){
System.out.println("Child()");
}
public Child(int a) {
str = "Child";
System.out.println("Child(int a)");
}
public void show() {
System.out.println(str);
super.show();
}
}
运行代码:
Child child = new Child();
运行结果:
I/System.out: Parent(int a)
I/System.out: null
I/System.out: Parent
I/System.out: Parent()
I/System.out: Child()
分析:
new Child()的时候先调用Child无参数构造方法
->因为Child有父类就会默认调用到父类Parent的无参构造方法Parent()
->因为在Parent的无参构造方法中调用了this(1),这样就调用到了Parent(int a)
->所以先打印输出了“Parent(int a)”
-> 在Parent(int a)中接下来调用了this.show(); 虽然使用了this关键字,但是因为show方法被重写了,所以调用的还是子类child 的show()方法
-> 子类的str没有赋值 ,所以打印出null
-> 接下来调用super.show 输出父类中的show方法打印出str “Parent”
->接下来输出无参数的Parent构造方法的打印 “Parent()”
-> 再输出Child无参数构造方法中的打印 “Child()”
其中有两个值得注意的地方:
1. 在下面的代码中this.str 赋值的是Parent中的变量,不会影响到Child的str变量
2. this.show() 在从子类对象覆盖了show方法后,经过子类创建对象,this调用到的还是子类中的方法。
综上可以知道,实际代码中this关键字隐去之后,代码的调用逻辑还是相同的,在Parent(int a)中调用的show,还是会是子类对象中的重写过的show().
public Parent(int a) {
this.str = "Parent";
System.out.println("Parent(int a)");
this.show();
}
4.super和this的异同
不同:
1.this表示的是当前对象的引用,super并不是父类对象的引用。在代码中Object o = super;是错误的,Object o = this;则是允许的。
2.super关键字的作用在于当子类中覆盖了父类的某个成员变量,或者重写了父类的某个成员方法时还能够访问到父类的成员变量和成员方法。
相同:
1.如果子类中没有重写父类的成员变量和成员方法,则子类会继承父类的所有非private的成员变量和成员方法。这时在子类中无论通过this来访问成员和通过super来访问成员,结果都是一样的。
2.都是进行访问的句柄关键字。