一、this
1.指代当前类的对象
每个对象都会持有自己的一个this,是一个引用类型变量,存放是对象自身在内存中的地址值。或者说,this是一个指向对象自身的指针。
(1)在构造方法里用this
class Date {
int year;
int month;
int day;
//构造方法
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public void print() {
}
}
目的:区分方法传过来的参数year 和 对象的成员变量this.year。
(2)成员方法的形参中,默认第一个参数是this
此this的作用是:指出在哪个对象上调用此方法。其也称为方法的隐式参数,存放于虚拟机栈的局部变量表。
(3)把对象自身作为参数传递给别的方法
public class Test {
public void m1(){
m2(this); //把this传给另一个方法
}
public void m2(Test t){
System.out.println(t);
}
}
(4)调用成员方法或成员变量,隐式加this
public class IdCard {
//成员变量
private String city;
//用this访问本对象的成员变量(this可去掉)
public void print() {
System.out.println(this.city);
}
//用this访问本对象的成员方法(this可去掉)
public void print1() {
this.print();
}
}
(5)类名.this
和上面一样,都是指代当前类的对象,但一般应用在含有内部类的场景上。因为只用this,读者无法区分外部类和内部类(编译器可以区分, 不用类名.this也不会报错),所以采用类名.this区分。
根据用法分两种情况讨论:
- 一般的使用情况,是内部类直接访问外部类的成员变量或方法,成员变量或方法不重名。即使不加“类名.this”区分,读者也不会觉得有歧义性;
class Outer {
String name;
class Inner {
void printInner() {
System.out.println(name);
//读者自然想到name是外部类的name, 但实际上name等同于Outer.this.name
}
}
}
2.内部类和外部类的成员变量或方法重名,读者理解起来稍有歧义性,用“类名.this”区分更好。
class Outer {
String name; //外部类和内部类都有name成员变量
void printOuter() {
System.out.println(Outer.this.name);//Outer.this.name也等同于this.name, this可被自动识别是Outer对象; 甚至连this也可去掉,直接用name;
}
class Inner {
String name;//外部类和内部类都有name成员变量
void printInner() {
System.out.println(Inner.this.name);//Inner.this.name也等同于this.name, this可被自动识别是Inner对象; 甚至连this也可去掉,直接用name;
}
}
}
注:本小节的例子用的是普通内部类,用匿名内部类同理!
2.指代本类构造方法
适用场景:构造方法调用另一个构造方法。
(1)有参构造方法调用无参构造方法时,用this();
注意:this()要写在方法第一行,不然报错。
public class Test {
//构造方法1
Test() {
System.out.println("hello");
}
//构造方法2
Test(int count) {
this();
System.out.println(count);
}
}
(2)无参构造方法调用有参构造方法,用this(参数);
注意:this(参数)要写在方法第一行,不然报错。
public class Test {
//构造方法1
Test() {
this(10);
System.out.println("hello");
}
//构造方法2
Test(int count) {
System.out.println(count);
}
}
二、super
1.指代父类的对象
class Father {
String color;
public void printColor() {
}
}
class Son extends Father {
String color;
public void printColor() {
System.out.println(this.color); //使用当前类的对象的成员变量
System.out.println(super.color); //使用父类的对象的成员变量
super.printColor(); //调用父类的对象的成员方法
}
}
2.指代父类的构造方法
适用场景:当前类的构造方法(显示/隐式)调用父类的构造方法。
class Father {
String color;
public Father(String color) {
this.color = color;
}
}
class Son extends Father {
String color;
public Son(String color) {
super(color); //显示调用父类的有参构造方法
this.color = color;
}
}
此处子类构造方法显示调用父类构造方法,把它改成显示调用父类的无参构造方法,再来品品里面的知识点:
public Son(String color) {
super(); /**此处显示调用父类的无参构造方法。
写不写super()都无所谓; 因为其调用是隐式的; 不管写不写super(), new对象时,JVM会先调用父类的构造方法,再调用子类构造方法。
但需要父类的无参构造方法不被去掉,不然会报错。
因为有个原则:如果父类已经有一个构造方法, 无参的构造方法会失效。
(则:要么,父类不写任何的构造方法,有个隐式的无参的构造方法;要么,父类只定义个无参的构造方法;要么父类同时定义无参构造方法和有参构造方法))。**/
this.color = color;
}