第六章
- 继承
- 方法的覆盖与多态
- super关键字
case1:引用既可以是局部变量,也可以是实例变量,也可以是静态变量!!!
**case2: **==System.out.println();==解析
System是一个类名,类名后面要么接静态变量,要么接静态方法。因为out没有带(),所以一定是静态变量。由于out后还有,所以out是一个引用,println是实例方法。
继承的作用
基本作用:子类继承父类,代码可以得到复用。
重要作用:因为有了继承关系,才有了后期方法的覆盖和多态机制。
继承的相关特性
B类继承A类,则称A类为超类(superclass)、父类、基类。
B类为子类(subclass)、派生类、扩展类。
Java中的继承只支持单继承,不支持多继承。C++支持多继承,且支持指针,所以Java具有简单性。
支持 class C extends B,class B extends A。
Java中规定,子类继承父类,==除构造方法不能继承之外,剩下的都可以继承。==但是私有的属性无法在子类中直接访问。(可以间接的访问,通过get、set方法)
Java中的类没有显示的基础父类,则默认继承Object类,Object类是Java语言提供的根类(老祖宗类),也就是说,一个对象与生俱来就有Object类型中所有的特征。
继承的缺点:代码的耦合度高,父类修改,子类受牵连。
方法的覆盖或重写
回顾方法重载:在同一个类中,方法名相同,形参列表不同(NOT原则:个数,顺序,类型)
方法覆盖条件:
两个类有继承关系
重写后的方法具有相同的返回值类型、方法名、形参列表。
访问权限不能更低(public protected default private)
重写之后的方法不能比之前的方法抛出更多的异常,可以更少。
这里还有几个注意事项:
注意1:方法覆盖只针对方法,与属性无关
注意2:私有方法无法覆盖。
注意3:构造方法不能被继承,所以构造方法也不能被覆盖。
注意4:方法覆盖只针对实例方法,静态方法覆盖没有意义。
注意5:私有方法可以被继承,但不能被覆盖。
什么时候考虑方法覆盖?
当父类方法无法满足子类也无需求时。
多态的基础语法
第一个:向上转型 子=>>父(自动类型转换)
第二个:向下转型 父=>>子(强制类型转换,需要加强制类型转换符)
注意:无论是向上转型还是向下转型,都要有继承关系,否则编译器会报错。
多态指的是:
Animal a = new Cat();
父类引用指向子类对象。
包括编译阶段和运行阶段。
编译阶段:静态绑定绑定父类的方法。
运行阶段:动态绑定子类型对象的方法。
多种形态。
java中只有 “类名” 或者 “引用” 才能去点
类名.
引用.
万变不离其宗,只要你想 “点” , “点” 前面要么加上类名,要么是一个引用。
什么时候需要向下转型?
如果你需要访问的方法是子类特有的方法时
向下转型存在风险
报错异常:
如何避免ClassCastException异常的发生?
用运算符 instanceof(运行阶段动态判断)
第一:instanceof可以在运行阶段判断引用指向的对象类型。
第二:instanceof的语法(引用 instanceof 类型)。
第三:instanceof运算符的运算结果只能是true/false。
第四:c是一个引用,c保存了内存地址指向堆中的对象。
假设(c instanceof Cat)为true表示:
c引用指向堆中的java对象是一个Cat
假设(c instanceof Cat)为false表示:
c引用指向堆中的java对象不是一个Cat
程序员要养成一个好习惯:
任何时候,对类型进行向下转型时,一定要使用instanceof运算符进行判断。(这样可以很好地避免:ClassCastException)。
if(a6 instanceof Cat){//如果a6是一只Cat
Cat y = (Cat)a6;//再进行强制类型转换
y.catchMouse();
}
访问子类特有的方法要向下转型,且需用到instanceof运算符
多态在开发中的应用(重要!!!)
多态在开发中有什么作用?非常重要,五颗星!!!(多态你会天天用,到处用!!!)
降低程序的耦合度,提高程序的扩展力。
public class Master{
public void feed(Dog d){}
public void feed(Cat c){}
}
以上代码表示:Master和Dog以及Cat的关系很紧密(耦合度高)。导致扩展力很差。
public class Master{
public void feed(Pet p){}
}
以上代码表示:Master和Dog以及Cat的关系就脱离了,Master关注的是Pet类。这样Master和Dog以及Cat的耦合度就降低了,提高了软件的扩展性。
软件开发七大原则最基本的原则:OCP(对扩展开放,对修改关闭)
目的是:降低程序的耦合度,提高程序的扩展力。
面向抽象编程,不建议面向具体编程。
public class Pet {
public void eat(){
System.out.println("吃饭啦!");
}
}
public class Dog extends Pet{
@Override
public void eat() {
System.out.println("狗吃骨头啦!!");
}
}
public class Cat extends Pet{
@Override
public void eat() {
System.out.println("猫吃鱼啦!!");
}
}
public class YingWu extends Pet{
@Override
public void eat() {
System.out.println("鹦鹉吃小虫子啦!!");
}
}
public class Master {
public void feed(Pet pet){//多态!!!要面向父类编程,面向抽象编程,这样会增加软件的扩展力。
pet.eat();
}
}
public class Test {
public static void main(String[] args) {
Dog dog = new Dog();
Cat cat = new Cat();
YingWu yingWu = new YingWu();
Master master = new Master();
master.feed(dog);
master.feed(cat);
master.feed(yingWu);
}
}
解释之前的遗留问题:
构造方法不能被继承。
私有方法不能被覆盖。
方法覆盖与多态不能分开。
静态方法不存在方法覆盖。
什么条件满足后,会构成方法的覆盖呢?
具有继承关系的两个类
父类中的方法和重写后的方法具有相同的返回值类型、方法名、参数列表。
学习了多态机制后:
“相同的返回值类型” 可以修改一下吗?
对于返回值类型是基本数据类型来说,必须一样。
对于引用数据类型而言,重写的时候返回值类型由Animal变成了Cat,变小了(可以,java允许),但意义不大;重写的时候返回值类型由Animal变成了Object,变大了。(不行)
super关键字(对比this)
this:
this可以出现在实例方法和构造方法中。
this的语法是:“this.“ 、”this()“
this不能使用在静态方法中。
this. 大部分情况是可以省略的。
this. 在区分局部变量和实例变量的时候不可以省略。
public void setName(String name){ this.name=name; }
this()只能出现在构造方法第一行,通过“本类”的构造方法去调用其他的构造方法。目的是:代码复用。
super:
super可以出现在实例方法和构造方法中。
super的语法是:“super.“ 、”super()“
super不能使用在静态方法中。
super. 大部分情况是可以省略的。
super. 在???的时候不可以省略。
super()只能出现在构造方法第一行,通过“父类”的构造方法去调用其他的构造方法。目的是:创建子类型对象的时候,先初始化父类型特征。
super()表示通过子类的构造方法调用父类的构造方法。
上图得出重要结论:
当一个构造方法第一行:
既没有this()又没有super()的话,默认会有一个super();表示通过当前子类的构造方法调用父类的无参数构造方法。所以必须保证父类的无参数构造方法是存在的。
this()和super()都要在构造方法第一行,因此this()和super()不能共存!!!
无论怎样折腾,父类的构造方法是一定会执行的。(百分百)
super和this的练习
new C()后的运行结果顺序?A无、B有、C有(String,int)、C有(String)、C无。(压栈的过程)
super(实参):
super调用内存分析
该过程中对象只创建了一个
当父类型当中和子类型当中有同名属性时,super.不能省略
也就是:父中有,子中也有,如果想在值中访问父的时候super.不能省略。
null,张三,null
Vip中的String name;去掉后结果就完全不一样了。就变成 张三、张三、张三 了