Java自学笔记Day17
本帖最后由 JXNU1999python 于 2021-12-4 09:11 编辑<font face="微软雅黑" size=5 color=#660000 >
Java学习笔记Day17
一、今日学习:
面向对象第六节
二、学习目标
(一)、继承
(二)、方法覆盖
(三)、多态
三、学习内容
(一)、继承
1、继承语法
【修饰符列表】+class+类名+extends+父类名{}
public class Computer extends Book{
//Book是父类,也称超类、基类、superclass
//Computer是子类,也称派生类、subclass
}
2、继承类的数量
java中继承只支持单继承,一个类只能继承一个类。
3、子类继承父类,继承的数据
构造方法不继承,私有的都不继承,其他数据可以被继承。
4、间接继承
class A{
}
class B extends A{
}
class C extends B{
}
class D extends C{
}//这样类D就能间接继承类A。
(二)、方法覆盖
1、方法覆盖又称方法重写,在子类中重新书写父类的方法称为方法覆盖,官方用语overwrite。
2、怎么进行方法重写?有什么需要注意的?
方法重写,方法名、修饰符列表、形参列表、返回值类型都相同。里面的其他java语句可以修改。
public class AnimalTest {
public static void main(String[] args) {
Animal a1=new Bird();//鸟类转化为动物类
}
public void move(){
System.out.println("小鸟飞向天空");//这里的move方法就是方法重写,修改里面的内容
}
}
public class Animal {
public void move(){
System.out.println("动物在移动!!!");
}
}
public class Bird extends Animal {
public void move(){
System.out.println("猫在移动");
}
// 也有自己特有的方法
public void sing(){
System.out.println("鸟儿在唱歌!!!");
}
}
3、注意事项
方法覆盖只存在与有继承关系的父子类之间。
静态方法不存在方法覆盖,构造方法和私有都无法继承,所以也无法覆盖。
方法重写时,访问权限不能降低,但可以更高。
抛出异常只能更少,不能增多。
父类中的方法无法满足业务需求时,子类有必要对继承的方法进行重写,此时需要进行方法覆盖。
(三)、多态(多态的作用是什么?)
1、向上转型(upcasting)需要有继承关系存在
不需要强制转化符,子类转成父类
向下转型(downcasting)需要有继承关系存在
需要强制转化符,父类转子类,可以这么理解,但是不能说父类强制转化为子类。
public class AnimalTest {
public static void main(String[] args) {
Animal a1=new Bird();//鸟类转化为动物类,向上转型
a1.sing();//这里无法调用sing方法,因为编译阶段只会从Animal中寻找sing方法。
Animal c1=new Cat();
Cat c3=(Cat)a1;//将父类Animal转为子类Cat,然而a1实际类是Bird,语法虽然没错,但执行阶段Cat和Bird没有继承关系,所以会出错,类型转换异常。
}
}
注意:java程序分为编译阶段和运行阶段。
先来分析编译阶段:
对于编译器来说,编译器只知道a2的类型是Animal,
所以编译器在检查语法的时候,会去Animal.class
字节码文件中找move()方法,找到了,绑定上move()
方法,编译通过,静态绑定成功。(编译阶段属于静态绑定。)
再来分析运行阶段:
运行阶段的时候,实际上在堆内存中创建的java对象是
Cat对象,所以move的时候,真正参与move的对象是一只猫,
所以运行阶段会动态执行Cat对象的move()方法。这个过程
属于运行阶段绑定。(运行阶段绑定属于动态绑定。)
多态表示多种形态:
编译的时候一种形态。
运行的时候另一种形态。
class Animal\Bird\Cat
public class Animal {
public void move(){
System.out.println("动物在移动!!!");
}
}
public class Bird extends Animal {
public void move(){
System.out.println("鹰击长空");
}
// 也有自己特有的方法
public void sing(){
System.out.println("鸟儿在唱歌!!!");
}
}
public class Cat extends Animal {
public void catchMouse(){
System.out.println("猫抓老鼠");
}
public void move(){
System.out.println("走猫步!");
}
}
2、防止类型转换异常的方法
instanceof (运行阶段动态判断)
第一:instanceof可以在运行阶段动态判断引用指向的对象的类型。
第二:instanceof的语法:
(引用 instanceof 类型)
第三:instanceof运算符的运算结果只能是:true/false
第四:c是一个引用,c变量保存了内存地址指向了堆中的对象。
假设(c instanceof Cat)为true表示:
c引用指向的堆内存中的java对象是一个Cat。
假设(c instanceof Cat)为false表示:
c引用指向的堆内存中的java对象不是一个Cat。
System.out.println(a6 instanceof Cat); //false
if(a6 instanceof Cat){ // 如果a6是一只Cat
Cat y = (Cat)a6;// 再进行强制类型转换
y.catchMouse();
}
if(a6 instanceof Bird){ // 如果a6是一只Bird
Bird y = (Bird)a6;// 再进行强制类型转换
y.sing();
}
3、面向抽象编程
public class Pet{
// 吃的行为(此方法可以不给具体的实现。)
public void eat(){
}
}
public class Master{
// 假设主人起初的时候只是喜欢养宠物狗狗
// 喂养宠物狗狗
public void feed(Dog d){
d.eat();
}
// 由于新的需求产生,导致我们“不得不”去修改Master这个类的代码
public void feed(Cat c){
c.eat();
}
// 让Master主人这个类以后不再修改了。
// 即使主人又喜欢养其它宠物了,Master也不需要修改。
// 这个时候就需要使用:多态机制。
// 最好不要写具体的宠物类型,这样会影响程序的扩展性。
public void feed(Pet pet){
// 编译的时候,编译器发现pet是Pet类,会去Pet类中找eat()方法,结果找到了,编译通过
// 运行的时候,底层实际的对象是什么,就自动调用到该实际对象对应的eat()方法上。 这就是多态的使用。
pet.eat();
}
}
public class Dog extends Pet{
public void eat(){
System.out.println("狗狗喜欢啃骨头,吃的很香。");
}
}
public class Cat extends Pet{
public void eat(){
System.out.println("猫咪喜欢吃鱼,吃的很香!!!");
}
}
四、总结,继承是为了节省代码,多态是为了提高代码的复用性 谢谢分享
谢谢分享 学习逻辑很清楚 不错,支持一下 可以啊老哥 支持一下,支持就是动力。。 public class Master {
public static void main(String[] args) {
Master m=new Master();
Pet dog=new Dog();
m.feedPet(dog);
Pet cat01=new Cat();
m.feedPet(cat01);
Pet cat02=new Cat();
m.feedPet(cat02);
}
public void feedPet(Pet pet){
// Dog erha=new Dog(); //没有采用多态的方式
// erha.eat();
// Cat jiafei=new Cat();
// jiafei.eat();
pet.eat();
}
}
多态可以提高代码复用性,不用修改喂养的feedPet方法,即可实现多种宠物喂养。 谢谢楼主分享 学习了,多谢分享
页:
[1]
2