JXNU1999python 发表于 2021-12-3 21:05

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("猫咪喜欢吃鱼,吃的很香!!!");
                }
      }
四、总结,继承是为了节省代码,多态是为了提高代码的复用性

独特丶小白 发表于 2021-12-3 21:33

谢谢分享

li4961 发表于 2021-12-3 21:50


谢谢分享

layuai 发表于 2021-12-3 21:54

学习逻辑很清楚

yshmsns 发表于 2021-12-3 22:05

不错,支持一下

Yxlhsx 发表于 2021-12-4 00:45

可以啊老哥

slbcmgn 发表于 2021-12-4 09:02

支持一下,支持就是动力。。

JXNU1999python 发表于 2021-12-4 09:13

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方法,即可实现多种宠物喂养。

meichangsu 发表于 2021-12-4 10:11

谢谢楼主分享

ieee1395 发表于 2021-12-4 14:37

学习了,多谢分享
页: [1] 2
查看完整版本: Java自学笔记Day17