学习内容:this和super
1.1 this
1.this是Java的一个关键字,是一个引用,保存当前对象的内存地址指向自身。
例:
// An highlighted block
public class thisTest {
public static void main(String[] args) {
Customer c1=new Customer("张三");
Customer c2=new Customer("李四");
c1.shopping();
c2.shopping();
}
}
class Customer{
String name;
public Customer(){}
public Customer(String name){
this.name=name;//这里的"this"指的是成员变量"name"
}
public void shopping(){
System.out.println(name+"正在购物!");//这个name前面有一个“this.”被省略了
}
}
这里的"this.name"指的是成员变量name,因为有参构造方法里面的局部变量名和Customer类的成员变量名一样也是name,为了方便区分就加上"this."。
如果局部变量名和成员变量名不一样,这里是"this."是可以省略的。反正就不能省略。
public Customer(String name){
this.name=name;//这里的"this"指的是成员变量"name"
}
这里创建了两个对象c1和c2,再分别用这两个对象去调用shopping()方法
Customer c1=new Customer("张三");
Customer c2=new Customer("李四");
c1.shopping();
c2.shopping();
shopping()方法输出的name前面是有一个"this.“的,只不过被省略了。当对象c1调用shopping()方法时,这里的"this"指的是c1对象的地址,也就是c1;当对象c2调用shopping()方法时,这里的"this"指的是c2对象的地址,也就是c2。无论是哪个对象去调用这个shopping()方法,“this"表示的都是调用这个方法的对象。
如果将这里的"this.“改为"c1.”(或者是"c2.”),那么当c2对象调用shopping()方法时,输出的是"c1.name”,就是c1对象的name了。
this在内存图中的存储结构是怎样的呢?(以上述代码为例)
2.2 this()
通过当前的构造方法去调用一个本类的构造方法,可以使用this(),格式如下
this(参数列表);
通过构造方法1去调用构造方法2,能做到代码复用;但前提是构造方法1和构造方法2必须在同一个类当中。
例:
public class thisTest01 {
public static void main(String[] args) {
Date d1=new Date();
d1.show();
Date d2=new Date(2001,9,25);
d2.show();
}
}
class Date{
private int year;
private int month;
private int day;
public Date() {
/*this.year=2001;
this.month = 12;
this.day = 5;*/
this(2001,12,5);//这一行代码等同于上面三行代码
}
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public void show(){
System.out.println(year+"年"+month+"月"+day+"日");
}
}
这里用无参构造方法和有参构造方法分别new了一个对象。在new对象的时候对成员变量初始化,因为d1是用无参构造方法创建的对象,所以成员变量会赋默认值(这里是int型,所以默认值是0),而d2创建对象的时候给了一个值,所以输出的就会是给的那个值。
Date d1=new Date();
d1.show();
Date d2=new Date(2001,9,25);
d2.show();
public Date() {
}
public Date(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
运行结果:
若是在无参构造里面直接给成员变量赋值,创建对象的时候就不会给成员变量赋默认值,就相对与你在无参构造里面赋值就是给成员变量的默认值。
Date d1=new Date();
d1.show();
public Date() {
this.year=2001;
this.month = 12;
this.day = 5;
}
如果你将上述代码换成this(2001,12,5);就是在无参构造方法里面调用了有参方法,实现了代码的复用。
public Date() {
this(2001,12,5);
}
注意:this()只能出现在代码的第一行!!一个构造方法里面也只能有一个this()
2.1 super
super的使用:
super.属性名 【访问父类的属性】
super.方法名() 【访问父类的方法】
super() 【调用父类的构造方法】
当子类中有和父类同名的属性或同样的方法时,可以用super.
来访问父类的属性或方法
例:
public class superTest {
public static void main(String[] args) {
Vip v=new Vip("张三");
v.shopping();
}
}
class Customer1{
String name;
public Customer1() {}
public Customer1(String name) {
this.name = name;
}
public void shopping(){
System.out.println("这是父类的方法");
}
}
class Vip extends Customer1{
String name;
public Vip(String name) {
super(name);//调用父类的成员变量name
//this.name=null; 会给Vip里面的成员变量赋默认值null
}
public void shopping(){
super.shopping();//调用父类的shopping()方法
System.out.println(this.name+"正在购物!");
System.out.println(super.name+"正在购物!");
System.out.println(name+"正在购物!");//name前面应该有一个"this."被省略了
}
}
2.2 super()
super()可以在子类的构造方法中调用父类的构造方法。格式如下
super(参数列表);
例:
public class superTest {
public static void main(String[] args) {
new B();
}
}
class A{
public A() {
System.out.println("A的无参构造!");
}
}
class B extends A{
public B() {
System.out.println("B的无参构造");
}
}
为什么上述代码明明是调用B的构造方法去创建对象,怎么A的构造方法也运行了呢?
其实子类的构造方法中,第一行默认会有super();
的代码,只是我们看不到,但是当我们手动写了这行代码之后,默认的super();
就没有了。
new B();
public B() {
super();
System.out.println("B的无参构造");
}
注意:跟this()一样,super()也只能出现在方法里的第一行
那么如果一个构造方法里面同时有this()和super(),那程序到底运行的是谁呢?
我们把上面的例子改一下:
class B extends A{
public B() {
this(10);
super();
System.out.println("B的无参构造");
}
public B(int a){
System.out.println("B的有参构造");
}
}
运行后发现报错,说“super必须是构造器中的第一个语句”。
我们将this()和super()交换位置后,发现无论是this()还是super()都要放在第一行。
class B extends A{
public B() {
super();
this(10);
System.out.println("B的无参构造");
}
public B(int a){
System.out.println("B的有参构造");
}
}
所以在一个构造方法中,有了this()就不能有super(),有了super()就不能有this()。
那如果构造方法里面有了this(),那到底是运行this()还是运行super()呢?
public class superTest {
public static void main(String[] args) {
new B();
}
}
class A{
public A() {
System.out.println("A的无参构造!");
}
}
class B extends A{
public B() {
this(10);
System.out.println("B的无参构造");
}
public B(int a){
//super();
System.out.println("B的有参构造");
}
}
这里是new B();
调用B的无参构造----->运行this(10);
去调用B的有参构造----->运行默认的super();
,去调用A的无参构造----->输出“A的无参构造!”(A的无参构造运行结束)----->输出“B的有参构造”(B的有参构造运行结束)----->输出“B的无参构造”(程序运行结束)
所以,当构造方法里面有了this()之后,默认的super()就不存在了。
学习总结
1. this
- this是一个关键字,是一个引用,保存内存地址指向自身。
- this可以使用在实例方法中,也可以使用在构造方法中。
- this出现在实例方法中其实代表的是当前对象。
- this不能使用在静态方法中。
this.
大部分情况下可以省略,但是用来区分局部变量和实例变量(成员变量)的时候不能省略。this()
这种语法只能出现在构造方法的第一行,表示当前构造方法调用本类其他的构造方法,目的是代码复用。
2. super
- super能出现在实例方法和构造方法中。
- super的语法是
super.
和super()
。 - super不能使用在静态方法中。
super.
大部分情况下是可以省略的。- 当父类和子类中有同名属性,或者是有同样的方法,想在子类中访问父类的属性或者是方法,
super.
不能省略。 super()
只能出现在构造方法的第一行,通过当前的构造方法去调用”父类“中的构造方法,目的是:创建子类对象的时候,先初始化父类特征(属性)。