理解Java多态以及super和this的用法【自用】

71 阅读6分钟

1、this的使用

  • 1.1、this是一个关键字,是一个引用,保存内存地址指向自身。
  • 1.2、this 可以便用在实例方法中,也可以使用在构造方法中。
  • 1.3、this出现在实例方法中其实代表的是当前对象。
  • 1.4、this不能使用在静态方法中。因为this表示当前对象,而static不需要创建对象就存在。
  • 1.5、this.大部分情况下可以省略,但是用来区分局部变量和实例变量的时候不能省略。
  • 1.6、this()这种语法只能出现在构造方法第一行,表示当前构造方法调用本类其他的构造方法,目的是代码复用。
public class Date {
private int month;
private int year;
private int day;
//this使用在构造方法中,
// 构造方法的作用就是给类中的变量赋值
    public Date() {
        this.year = 1977;
        this.month = 9;
        this.day = 21;
    }

    public Date(int year, int month, int day) {
        this.month = month;
        this.year = year;
        this.day = day;
    }
//this使用在实例方法中,d1传过来就代表d1,d2穿过来就代表d2
    public void detail(){
        System.out.println(this.year+"年"+month+"月"+day+"日");
    }

}
测试类:
public class Test {
    public static void main(String[] args) {
        Date d1 = new Date();
        d1.detail();//1977年9月21日
        Date d2 = new Date(2001, 9, 21);
        d2.detail();//2001年9月21日
    }
}

2、封装:

就是指private属性不能继承,并且需要设置set和get方法来获取,使其他人得不到内部细节

3、理解继承、多态

两点理解:

(1)向上转型 (父类是上,子类是下)

Person p = new Student();

Person p = new Teacher();

在调用方法时,编译看左边,运行看右边。 在调用属性时,编译和运行都看右边。

(2)向下转型(要注意转时的判断)

public class People {
    public String name;

    public People(){
//      构造方法的作用是为了给属性赋值,如果方法体为空,则赋默认值,如String类型默认赋null
        this.name = "人";
    }

    public People(String name) {
        this.name = name;
    }

    void run(){
        System.out.println("人会跑");
    }
// 定义方法的时候,使用父类型作为参数,该方法就可以接收这一父类的一切子类对象,体现出多态的扩展性与便利
//此时在父类People中添加一个PK()方法,其中的形参设置为“People a”要优于“Student a”,
//为什么呢?第一种可以接收该父类的一切子类对象,而第二种只能接收一种,具有局限性
    public void PK(People a){
        System.out.println(a.name+"参加比赛了!");
    }
    public void methodA(){
        System.out.println("人的方法");
    }


    public static void main(String[] args) {
        People p1 = new Student();
        People p2 = new Teacher();

//多态中成员访问特点:

//方法调用:编译看左,运行看右;(run方法)

//在编译的时候,先访问“People a1 = new Student();”的左边“People父类”中的方法,而在运行的时候,会访问右边“Student子类”中的方法;

//变量调用学会分析,分清楚子父类的变量能不能共享,如果子类重新定义了name,
// 那么在子类构造方法中的name就不会是父类.name的值,父类.name的值应该由父类的构造方法确定
//变量调用:编译看左,运行也看左。(多态注重行为多态)

//在编译的时候,会访问“People a1 = new Student();”的左边“People父类”中的变量,并且在运行的时候,仍然访问左边“People父类”中的变量。

        p1.run();//学生跑得慢
        p2.run();//老师跑的快
        System.out.println(p1.name);//人
        System.out.println(p2.name);//人
//      p1是自动类型转化
//      多态下不能使用子类的独有功能
//      p1.sick();

//既然前面说到“多态下不能使用子类的独有功能”,那么该由谁来调用呢?
// 子类独有功能当然还是由子类自己来调用,此时我们就需要引入类型转换的概念:
// 类型转换分为两种,分别是:“自动类型转换、强制类型转换”。
//强制类型转换
        People s1 = new Student();
        Student s2 = (Student) s1;
        s2.sick();
        System.out.println(s2.name);//输出子类的name

//        检查类型是否正确
        People p = new Student();
        if (p instanceof Student){
            Student s = (Student) p;
            s.sick();
        }else if (p instanceof Teacher){
            Teacher t = (Teacher) p;
            t.run();
        }
//
    }
}
public class Student extends People {
    public String name;//这一行注释后,this.name和super.name的值表示一样,都表示的是父类中的name

   public Student(){
       super();
       this.name = "小学生";
   }
    public void method(){
        String name="初中生";
        System.out.println(name);
        System.out.println(this.name);
        System.out.println(super.name);
    }
    @Override
    void run() {
        System.out.println("学生跑得慢");
    }
    void sick(){//子类独有的方法
        System.out.println("学生生病了");
    }

    public static void main(String[] args) {
        Student student = new Student();
        student.method();
    }
}
package 多态;

public class Teacher extends  People{
    public String name ;
    public Teacher(){
        this.name = "老师";//此时的name和父类中的name没有关系,这个name赋值仅赋值给Teacher中的name
    }
    @Override
    void run() {
        System.out.println("老师跑的快");
    }

    public void methodB(){
        System.out.println("老师的方法");
    }
}

注意:子类和父类同时出现一样的属性时,要分清楚父类的属性是否会被子类的构造方法所具有的属性传进来。 子类没有父类的属性时,子类可以继承父类的属性,从而父类和子类的属性值相同。

4、super的使用

  • super能出现在实例方法和构造方法中。

  • super的语法是: "super."、 "super()"

  • super不能使用在静态方法中。

  • super.大部分情况下是可以省略的。

  • super.什么时候不能省略呢? 父类和子类中有同名属性,或者说有同样的方法, 想在子类中访问父类的,super.不能省略。

  • super()只能出现在构造方法第一行,通过当前的构造方法先去调用父类中 的构造方法,目的是:创建子类对象的时候,先初始化父类型特征。

  • super的使用: super.属性名 —— 访问父类的属性

    super.方法名(实参)——访问父类的方法

    super (实参)——调用父类的构造方法

理解以下两种参数的传递
public class SuperTest01 {
    public static void main(String[] args) {
        People p1 = new Student("ll");
        People p2 = new Teacher("kk");
        System.out.println(p1.name);
        System.out.println(p2.name);
    }
}
class People{
    public String name;

    public People() {
    }
    public People(String name) {
        super();//默认存在
        this.name = name;
    }
}
class Student extends People{
    public Student() {
    }
//子类Student中没有定义name变量,
//那么其继承父类中的name,也可以构造含参的构造方法
//如果调用子类中的含参构造方法,那么就先调用super(name)即父类的含参构造方法
    public Student(String name) {
        super(name);
    }
}
class Teacher extends People{
    public Teacher() {
    }

    public Teacher(String name) {
        super(name);
    }
}

public class SuperTest02 {
    public static void main(String[] args) {
        People1 p1 = new Student1("ll");
        People1 p2 = new Teacher1("kk");
        System.out.println(p1.name);
        System.out.println(p2.name);
    }
}
class People1{
    public String name;

    public People1() {
        this.name = "人";
    }
    public People1(String name) {
        super();//默认存在
        this.name = name;
    }
}
class Student1 extends People1{
    public String name;
    public Student1() {
    }

//如果调用子类中的含参构造方法,那么就先调用super(name)即父类的含参构造方法
    public Student1(String name) {
        super(name);//默认的是super(),不含参,含参这一部分将people中的name也定义为kk和ll
        this.name = name;
    }
}
class Teacher1 extends People1{
    public String name;
    public Teacher1() {
    }

    public Teacher1(String name) {
//这里省略的是super()即跳转到不含参的父类构造方法,
// 所以对象p2的name值没有传过来,故Teacher1.name的值为kk,而People1.name的值为“人“
        this.name = name;
    }