一、方法的继承
1.继承中成员变量访问特点:就近原则。
2.先在局部位置找,本类成员位置找,父类成员位置找,逐级往上。
System.out.println(name); //局部位置
System.out.println(this.name); //本类成员位置开始往上找
System.out.println(super.name); //父类成员位置开始往上找
3.方法的调用,前面会隐含this(代表的是被调用者的ip)
二、方法的重写(重写的本质=>父子类继承时虚方法表的覆盖。<对于同名的方法>)
1.重写的方法名、形参列表必须与父类的一致。
2.子类重写父类时,访问权限必须大于等于父类。返回值类型必须小于等于父类。
3.重写的方法尽量与父类保持一致。
4。只有被添加到虚方法表中的方法才能被重写。
5.当父类方法中,不能满足子类现在的需求时,就需要把这类方法重写。子类中重写的方法上面需要加上@override。
6.父类中的构造方法不会被子类继承。
7.子类中所有的构造方法都会默认先访问父类中的无参构造,在执行自己。(子类在初始化时,很有可能会使用到父类中的数据,所以要先完成父类数据空间的初始化。子类构造方法的第一句默认super(),虚拟机默认自动加上,想要调用父类的有参构造必须用super().去调用)。
访问本类构方法指代的是:在无参构造中用this给变量赋予初始化的默认值,再调用有参构造。
三、多态
1.同类型的对象,表现出不同的形态。
2.多态的表现形式:父类类型 对象名称=子类对象
3.前提:①有继承关系。②有父类引用指向子类对象。 ③有方法重写。
4. 如果传递的参数是类名,极为多态。
5.多态调用的内存图解
调用成员变量与成员方法初始化的左边与右边是初始化时的Animal a =new Dog()的左边与右边。调用成员方法时看右边是因为成员方法在变量初始化的时候子类方法会继承(或者覆盖)父类的虚方法表,如果父类中不存在虚方法表那直接报错。
6.多态弊端:不可以调用子类的特有功能。但是可以通过自动类型转换、强制类型转换实现调用子类的功能。(但是注意,可能会出现转换类型与真实对象类型不一致从而产生报错)
Person p =new Student();
Student s=(Student)p
7.将动物类强转成为猫类并用猫类命名。
animal instanceof Cat cat
//动物类 package a04; public class Animal { private String color; private int age; public Animal() { } public Animal(String color, int age) { this.color = color; this.age = age; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void eat(String food){ System.out.println("Animal is eating"); } }//狗继承动物类,并重写吃的方法
package a04; public class Dog extends Animal { public void lookHome() { System.out.println("狗再看家"); } public Dog(String name, int age) { super(name, age); } @Override public void eat(String food) { System.out.println(getAge() + "岁的" + getColor() + "颜色的狗两只前腿死死的抱住" + food+"猛吃"); } }//猫继承动物类,并重写吃的方法
package a04; public class Cat extends Animal { public void catchMouse(){ System.out.println("猫抓老鼠"); } public Cat(String name, int age) { super(name, age); } public Cat() { } public void eat(String food) { System.out.println(getAge() + "岁的" + getColor() + "颜色的猫眯着眼睛侧着头在吃" + food); } }//饲养员(独立的,不具有继承关系)
package a04; public class People { private String name; private int age; public People() { } public People(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public void keepPet(Animal animal, String something){ if(animal instanceof Dog dog){ System.out.println( "年龄为"+age+ "岁的"+name+"养了"+dog.getColor()+"的"+dog.getAge()+"岁的狗"); dog.eat(something); }else if(animal instanceof Cat cat){ System.out.println( "年龄为"+age+ "岁的"+name+"养了"+cat.getColor()+"的"+cat.getAge()+"岁的猫"); cat.eat(something); }else { System.out.println("动物不存在"); } } }//测试类
package a04; public class Test { public static void main(String[] args) { People people=new People("老王",30); Animal dog=new Dog("黑",2); people.keepPet(dog,"肉"); People people1=new People("老李",40); Animal cat=new Cat("灰",3); people1.keepPet(cat,"鱼"); } }
四、包与final
1.final修饰方法时:表明该方法是最终方法,不能被重写。
2.final修饰类时:表明该类是最终类,不能被继承。
3.final修饰变量时:叫做常量,只能被赋值一次。
4.final修饰的变量若是基本数据类型,那么变量存储的数据值不能发生改变。若是引用数据类型,那么变量存储的地址值不能发生改变,对象内部可以发生改变。
五、权限修饰符与代码块
1.权限修饰符
2.局部代码块(提前变量项目的生命周期)
2.构造代码块。(随着类的创建而被创建)
1.写在成员位置的代码块。
2.作用:可以将多个构造方法的代码块抽取出来。
3.执行时机:我们在创建本类对象的时候会先执行构造代码块再执行构造方法。构造代码块优先于构造方法执行的。但是代码不灵活,逐渐淘汰。
解决方法:①、将重复的代码抽象成一个方法。并在构造方法中调用。
②、重复代码写在有参构造中,在无参构造的抽象方法中用this进行调用。
3.静态代码块(用于一些变量的初始化)
格式:static{}
特点:需要通过static关键字修饰,随着类的加载而加载,并且自动触发,只需要执行一次
使用场景:类加载时,做一些数据的初始化。