Java知识点整理(继承,this,super,重写,引用类型转换,动态多态)

1.继承

按照翻译来说应该是基于已有的进行扩展,

假设现在有学生和老师两个类,每个类所拥有的属性如下

  • Student
    • stuId
    • stuName
    • stuAge
    • stuGender
  • Teacher
    • teaId
    • teaName
    • teaAge
    • teaGender
    • teaCourse

从属性上来看,可以发现Student和Teacher有相同的一部分(看的是逻辑含义,不要看变量名),都有id,name,age,gender.如果在Student和Teacher中都定义一次,属于典型的代码重复。为了复用这一部分内容,我们可以把公共的抽取出来组成一个单独的类:Person,然后Student和Teacher分别基于Person做扩展,继承使用的关键字为extends.

public class Person {
    private int id;
    private int age;
    private String name;
    private String gender;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getGender() {
        return gender;
    }
    public void setGender(String gender) {
        this.gender = gender;
    }
    public void showInfo(){
        System.out.println(""+id + name + age + gender);
    }
}




public class Teacher extends Person{
}


Teacher中没有任何内容,但是我们构建一个Teacher对象试试。


public class Test {
    public static void main(String[] args) {
        Teacher teacher = new Teacher();
        //-- Teacher 扩展了Person后,就拥有Person的所有内容
        teacher.setId(1);
        teacher.setAge(19);
        teacher.setName("张三");
        teacher.setGender("男");
        teacher.showInfo();
    }
}

Teacher中没有内容,他的方法是从person那里继承来的,一旦继承关系成立,那Teacher叫做子类,而Person叫做父类,Java中的继承是单继承,从血缘关系上讲,我们只有一个直系父亲一样,对于任意一个子类来说,都有且只有一个父类,继承成功之后,我们可以访问到的只有非私有内容,私有的内容是无法访问的

2.this关键字

this是一个关键字,用于代表当前对象。对于类来收,就是当前类的一个实例,对于方法来说就是当前调用方法的对象。最终指向的都是对象。

this有两个用法

  • this.
  • this()

2.1this.的用法

public class A {
    public void method01(){
        System.out.println("this is method01");
        this.method02();
        //-- 因为当前类,就是本类,所以this可以省略
        method02();
    }
    public void method02(){
        System.out.println("this is method02");
    }

对象不仅可以调用方法,还可以调用属性

public class B {
    public int i = 3;
    public static int j = 4;
    public void method01(){
        System.out.println(this.i);
        System.out.println(i);
    }
    public static void method02(){
        System.out.println(B.j);
        System.out.println(j);
    }
}

2.2this()的用法

首先先引入一个概念,方法签名 = 方法名称+参数列表

this()一般用于简化构造方法重载!

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

    public Person(){
    }

    public Person(int age,String name){
        //this.age = age;
        //this.name = name;
        //-- 不再需要写大量的this.XXX = XXX类,直接调用本类的其它构造方法
        //-- 小括号的内参数决定所调用的构造方法是哪个!
        this(0,age,name);
    }

    public Person(int id,int age,String name){
        this.id = id;
        this.age = age;
        this.name = name;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        //-- 我们可以在方法内添加控制语句.实现对取值和赋值进行控制!
        if (age < 0){
            age = 17;
        }
        this.age = age;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

2.3当this遇到继承

牢记:this代表当前如果当前处于父类,那就是父类的对象,如果当前处于子类,那就是子类的对象

public class C {
    public int i  = 10;
    public static void main(String[] args) {
        C c = new C();
        System.out.println(c.i);
        D d = new D();
        System.out.println(d.i);
    }
}
class D extends C{
    public int i = 100;
}

3.static关键字:

static叫做静态,属于类,通过类名.直接进行访问。所以static修饰的内容绝对不可能是局部的

静态只能直接访问静态,想要访问非静态内容必须通过对象来实现

public class E{
    int i = 10;
    static int j = 20;
    public static void main(String[] args) {
    }
    public static void method01(){
        //Non-static field 'i' cannot be referenced from a static context
        //System.out.println(i);
        //-- 就想访问i怎么办 构建i所属于的对象
        E e = new E();
        System.out.println(e.i);
        System.out.println(j);
    }
  • 非静态的可以访问全部(静态和非静态)

  • 静态是全局的,类的所有实例共享静态的内容

  • 非静态属于对象,每个对象私有。一个对象对其非静态属性做了改变,其它对象不受影响

  • int i = 0;
    static int j = 0;
    public static void main(String[] args){
        E e1 = new E();
        E e2 = new E();
        E e3 = new E();
    
           e1.j = 30;
           System.out.println(e3.j)
    
    }
    
    

    静态优先加载:

  • public class F {
        public F(){
            System.out.println("F");
        }
        //--代码块,因为被static修饰,所以也叫做静态代码块。简称静态域
        static {
            System.out.println(123);
        }
        public static void main(String[] args) {
            new G();
        }
    }
    class G extends F{
        static{
            System.out.println(456);
        }
        public G(){
            System.out.println("G");
        }
    }

    父类静态,然后是子类静态。然后是父类构造,最后是子类构造

  • static中不能写this,因为staitc是优先加载的,那么在main方法执行时,this所代表的对象还没有创建,所以在static中无法使用this.

4.super关键字:

super是在继承之后才有的关键字。它的用法和this类似,分为两种情况

  • super. 代表父类对象
  • super() 代表父类构造方法
  • 此处引入一个概念为Object,Object是Java的根类,在Java中没有显式继承关系时,默认每个类都继承Object
  • public class Teacher {
        public Teacher(){
            //-- super() 指的是父类的构造方法
            //-- 方法是可以重载的,具体那一个构造方法
            //-- 根据小括号中的参数列表决定。当前小括号内没有参数,无参
            //-- 所以调用的是Object的无参构造
            super();
        }
    }

    super()代表父类构造方法,具体哪个方法,由参数列表决定

  • //-- 继承了Object
    public class Animal {
        private String name;
        public Animal(String name){
            super();//-- Object 无参构造
            this.name = name;
            System.out.println("this is animal");
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
    
    
    
    // 有显式的继承关系,那就是继承Animal  就不继承Object
    public class Dog extends Animal{
        public Dog(String name){
            super(name);
        }
    }

super.代表的是父类对象.

public class Animal {
    private String name;
    public Animal(String name){
        this.name = name;
        System.out.println("this is animal");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void showInfo(){
        System.out.println("name:" + name);
    }
}



public class Dog extends Animal{
    public Dog(String name){
        super(name);
    }
    public void showDog(){
        //-- 使用下父类的showInfo
        //--  这时候的super.代表的就是父类对象!
        super.showInfo();
    }
}

4.1super()的使用:

super()只能出现在一个地方,构造方法的第一行。代表调用父类的构造方法,代表调用父类的构造方法

Java中子类只能调用父类的构造方法!并且只能在子类的构造方法中调用,并且必须第一行

public class Hero {
    private int hp;
    private int mp;
    private int attack;
    private int defend;
    public Hero(){
        //-- super()哪怕不写也是存在的。默认隐藏,必须位于构造方法的第一行
        //System.out.println("12");
        //Call to 'super()' must be first statement in constructor body
        //-- 代表调用父类的构造方法。构建父类的对象!
        super();
    }
    //-- 省略了get|set
}

如果父类中没有无参构造怎么办?那子类的super()就会报错,报错原因是没有一个默认的构造方法

public class Hero {
    private String name;
    private int hp;
    private int mp;
    private int attack;
    private int defend;
    public Hero(String name){
        //-- super()哪怕不写也是存在的。默认隐藏,必须位于构造方法的第一行
        //-- 代表调用父类的构造方法。构建父类的对象!
        //super();
        this.name = name;
    }
}




public class ArcherHero extends Hero{
}

这样写会报错,因为子类继承了Hero调用Hero的无参构造,但是Hero中没有无参构造,所以super()找不到方法,我们的解决方案有两个

  • 父类提供一个无参构造
  • 覆盖默认的构造方法,主动调用有参构造
  • public class ArcherHero extends Hero{
        public ArcherHero(String name){
           super(name);
        }
    }

    因为子类的构造方法中,第一行一定是super()所以导致,构造子类时,会先构造它的父类,然后才是子类本身

  • Hero hearo = new Hero();
    //-- 实际上先构造了Object,然后再构造了Hero()

4.2 super.的用法

super代表的是父类对象,所以super.就表示为调用父类的属性或者父类的方法。一样的前提必须是非私有

class Hero{
        public void method(){
        System.out.println("this is hero method");
    }
}




public class ArcherHero extends Hero{
    public ArcherHero(String name){
       super(name);
    }
    public void callBack(){//callback是随便命名的方法
        //-- 使用的是继承到的method
        this.method();
        //-- 强调的是是否用父类的!
        super.method();
    }
}

5.方法重写

方法代表的是类型的行为,子类和父类,针对同一种行为可能有不同的体现。也就是子类保持方法声明不变,但是可以改写继承到的方法体。这种写法叫做方法重写。

public class Hero {
    private String name;
    private int hp;
    private int mp;
    private int attack;
    private int defend;
    public Hero(String name){
        //-- super()哪怕不写也是存在的。默认隐藏,必须位于构造方法的第一行
        //-- 代表调用父类的构造方法。构建父类的对象!
        //super();
        this.name = name;
    }
    //--GET|SET
    public void goHome(){
        System.out.println("父类回城中!");
    }
}



public class ArcherHero extends Hero{
    public ArcherHero(String name){
         //super("弓箭手");
       super(name);
    }
    //-- @Override 注解 表示子类重写类父类的方法!
    @Override
    public void goHome() {
        //super.goHome();
        System.out.println("使用回城特效回城!");
    }
}



public class HeroTest {
    public static void main(String[] args) {
        ArcherHero ah = new ArcherHero("艾希");
        System.out.println(ah.getName());
        ah.goHome();
    }
}

5.1强调使用父类的方法体

这就是super.作用所在,我们可以使用super.来强调使用父类的方法体

如果直接写goHome会自己调用自己,形成递归。我们想要的强调的goHome是父类的,不是子类自己的,就必须加上super.

6.引用类型转换(动态多态)

原生类型转换方式我们知道,有自动转换和强制转换,那我们引用的数据类型也是同样如此,我们知道原生的数据类型转换时根据大小,那我们如何判断引用的数据类型大小呢,我们可以这么理解,宠物 和狗,我们可以说狗是宠物,但是不能说宠物是狗。所以重复的覆盖面要比猫大。所以父类的范围大,子类的范围小。那上面的转换规则我们可以修正下

  • 小-》大 狗-》宠物 子类-》父类。 自动转换 向上转型
  • 大-》小 宠物-》狗 父类-》子类。 强制转换 向下转型

public class Pet {
    private String name;
    public Pet(String name){
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void eat(){
        System.out.println("this is animal eat");
    }
    public void sleep(){
        System.out.println("this is animal sleep");
    }
}



public class Dog extends Pet{
    public Dog(String name){
        //-- super使用最多的地方就是这里了!
        super(name);
    }
}



public class Cat extends Pet{
    public Cat(String name){
        super(name);
    }
}



public class Test {
    public static void main(String[] args) {
        Dog dog1 = new Dog("狗1号");
        //-- 把小的赋值给大的  子类赋值给父类  int-》long
        Pet pet = dog1;
        //-- 把大的赋值给小的  父类赋值给子类   long-》int
        Dog dog2 = (Dog)pet;
    }
}

下面一段代码帮助深入理解

public class Test {
    public static void main(String[] args) {
        Dog dog1 = new Dog("狗1号");
        //-- 把小的赋值给大的  子类赋值给父类  int-》long
        Pet pet = dog1;
        //-- 把大的赋值给小的  父类赋值给子类   long-》int
        Dog dog2 = (Dog)pet;
    }
    public void method01(Dog dog){
    }
    public void method02(Cat cat){
    }
    public void method03(Pet pet){
    }
}

三个方法分别可以接收什么类型的参数

  • method01 -》 只能接收Dog
  • method02 -》 只能接收Cat
  • method03 -》 可以接收Cat,Dog,Pet

为什么?因为Pet是父类,可以接收所有的子类实例。这样做的意义到底在哪里呢?提示下重写。因为子类可以改写父类的方法体,我们使用父类来接收所有的子类实例。在没有明确对象之前,你不知道要执行的是哪个方法体是什么

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值