java--面对对象之this关键字和super关键字

this

一、this调用构造方法

构造方法之间的调用,可以通过this关键字来完成。

构造方法调用格式:

1 this(参数列表);

构造方法的调用:

 

二、this的原理图解

    了解了构造方法之间是可以相互调用,那为什么他们之间通过this就可以调用呢?通过上面的学习,简单知道使用this可以实现构造方法之间的调用,但是为什么就会知道this调用哪一个构造方法呢?接下来需要图解完成。

 图列说明:

1、先执行main方法,main方法压栈,执行其中的new Person(“张三”,23);

2、堆内存中开辟空间,并为其分配内存地址0x33,,紧接着成员变量默认初始化(name=null  age = 0);

3、拥有两个参数的构造方法(PersonString nm , int a))压栈,在这个构造方法中有一个隐式的this,因为构造方法是给对象初始化的,那个对象调用到这个构造方法,this就指向堆中的那个对象。

4、由于PersonString nm , int a)构造方法中使用了this(nm);构造方法Person(String nm)就会压栈,并将“张三”传递给nm。在PersonString nm , int a)构造方法中同样也有隐式的thisthis的值同样也为0x33,这时会执行其中name = nm,即把“张三”赋值给成员的name。当赋值结束后PersonString nm , int a)构造方法弹栈。

5、程序继续执行构造方法(PersonString nm , int a)中的age = a;这时会将23赋值给成员属性age。赋值结束构造方法(PersonString nm , int a)弹栈。

6、当构造方法(PersonString nm , int a)弹栈结束后,Person对象在内存中创建完成,并将0x33赋值给main方法中的p引用变量。

注意:

       this到底代表什么呢?this代表的是对象,具体代表哪个对象呢?哪个对象调用了this所在的方法,this就代表哪个对象。

调用其他构造方法的语句必须定义在构造方法的第一行,原因是初始化动作要最先执行。 

三、成员变量和局部变量同名问题

 

        当在方法中出现了局部变量和成员变量同名的时候,那么在方法中怎么区别局部变量成员变量呢?可以在成员变量名前面加上this.来区别成员变量和局部变量。

public class Person {
    private int age;
    private String name;

    // 给姓名和年龄初始化的构造方法
    Person(String name, int age) {
        // 当需要访问成员变量是,只需要在成员变量前面加上this.即可
        this.name = name;
        this.age = age;
    }

    public void speak() {
        System.out.println("name=" + this.name + ",age=" + this.age);
    }
}
class PersonDemo {
    public static void main(String[] args) {
        Person p = new Person("张三", 23);
        p.speak();
    }
}

四、this的应用

学习完了构造方法、this的用法之后,现在做个小小的练习。

需求:在Person类中定义功能,判断两个人是否是同龄人

 1 class Person {
 2     private int age;
 3     private String name;
 4 
 5     // 给姓名和年龄初始化的构造方法
 6     Person(String name, int age) {
 7         // 当需要访问成员变量是,只需要在成员变量前面加上this.即可
 8         this.name = name;
 9         this.age = age;
10     }
11 
12     public void speak() {
13         System.out.println("name=" + this.name + ",age=" + this.age);
14     }
15 
16     // 判断是否为同龄人
17     public boolean equalsAge(Person p) {
18         // 使用当前调用该equalsAge方法对象的age和传递进来p的age进行比较
19         // 由于无法确定具体是哪一个对象调用equalsAge方法,这里就可以使用this来代替
20         /*
21          * if(this.age == p.age) { return true; } return false;
22          */
23         return this.age = p.age;
24     }
25 }

super

一、子父类中构造方法的调用

 

在创建子类对象时,父类的构造方法会先执行,因为子类中所有构造方法的第一行有默认的隐式super();语句。

 

格式:

1 调用本类中的构造方法
2 this(实参列表);
3 调用父类中的空参数构造方法
4 super();
5 调用父类中的有参数构造方法
6     super(实参列表);

为什么子类对象创建都要访问父类中的构造方法?因为子类继承了父类的内容,所以创建对象时,必须要先看父类是如何对其内容进行初始化的,看如下程序:

 1 //父类
 2 public class Person {
 3     int a=1;
 4     public Person(){
 5         
 6     }
 7     public Person(String name){
 8         a=5;
 9         System.out.println("父类构造方法");
10     }
11 }
12 //子类
13 public class Test {
14 
15     public static void main(String[] args) {
16         Student stu=new Student("name");
17 
18     }
19 }
20 //测试类
21 public class Test {
22 
23     public static void main(String[] args) {
24         Student stu=new Student("name");
25 
26     }
27 }

运行结果为:

父类构造方法
5

总结:通过结果发现,子类构造方法执行时中,调用了父类构造方法,这说明,子类构造方法中有一句super()

那么,子类中的构造方法为什么会有一句隐式的super()呢?

原因:子类会继承父类中的内容,所以子类在初始化时,必须先到父类中去执行父类的初始化动作。这样,才可以使用父类中的内容。

当父类中没有空参数构造方法时,子类的构造方法必须有显示的super语句,指定要访问的父类有参数构造方法。

二 、子类对象创建过程的细节

 

如果子类的构造方法第一行写了this调用了本类其他构造方法,那么super调用父类的语句还有吗?

 

这时是没有的,因为this()或者super(),只能定义在构造方法的第一行,因为初始化动作要先执行。

 

父类构造方法中是否有隐式的super呢?

 

也是有的。记住:只要是构造方法默认第一行都是super();

 

父类的父类是谁呢?super调用的到底是谁的构造方法呢?

 

Java体系在设计,定义了一个所有对象的父类Object

 

 

 注意:

    1、类中的构造方法默认第一行都有隐式的super()语句,在访问父类中的空参数构造方法。所以父类的构造方法既可以给自己的对象初始化,也可以给自己的子类对象初始化。

    2、如果默认的隐式super()语句在父类中没有对应的构造方法,那么必须在构造方法中通过this或者super的形式明确要调用的构造方法。

三、super应用

 

    描述学生和工人这两个类,将他们的共性nameage抽取出来存放在父类中,并提供相应的getset方法,同时需要在创建学生和工人对象就必须明确姓名和年龄。

 

 1 //定义Person类,将Student和Worker共性抽取出来
 2 class Person {
 3     private String name;
 4     private int age;
 5     public Person(String name, int age) {
 6         // super();
 7         this.name = name;
 8         this.age = age;
 9     }
10     public String getName() {
11         return name;
12     }
13     public void setName(String name) {
14         this.name = name;
15     }
16     public int getAge() {
17         return age;
18     }
19     public void setAge(int age) {
20         this.age = age;
21     }
22 }
23 class Student extends Person {
24     // Student类的构造方法
25     Student(String name, int age) {
26         // 使用super关键字调用父类构造方法,进行相应的初始化动作
27         super(name, age);
28     }
29     public void study() {// Studnet中特有的方法
30         System.out.println(this.getName() + "同学在学习");
31     }
32 }
33 class Worker extends Person {
34     Worker(String name, int age) {
35         // 使用super关键字调用父类构造方法,进行相应的初始化动作
36         super(name, age);
37     }
38     public void work() {// Worker 中特有的方法
39         System.out.println(this.getName() + "工人在工作");
40     }
41 }
42 public class Test {
43     public static void main(String[] args) {
44         Student stu = new Student("小明",23);
45 stu.study();
46         
47 Worker w = new Worker("小李",45);
48 w.work();
49     }
50 }

 

posted @ 2018-07-25 17:03  大树*  阅读(328)  评论(0编辑  收藏  举报