JAVA零基础小白学习教程之day08_接口多态

news2024/11/18 5:27:22

day08-JAVAOOP

课程目标

1. 【理解】什么是接口
2. 【掌握】接口的定义格式
3. 【掌握】接口的使用
4. 【理解】接口的成员特点
5. 【理解】类和接口 抽象类和接口之间的关系
6. 【掌握】单继承多实现 
7. 【理解】接口之间的多继承
8. 【掌握】接口的案例 

9. 【理解】什么是多态
10. 【理解】使用多态的前提
11. 【掌握】多态的格式
12. 【理解】多态中的成员访问特点
13. 【理解】多态中的好处和弊端
14. 【理解】多态中的转型
15. 【理解】转型的异常
16. 【掌握】综合案例

接口

接口基本概述及语法

接口概述

接口,是Java语言中一种引用类型,是方法的集合,如果说类的内部封装了成员变量、构造方法和成员方法,那么接口的内部主要就是封装了方法(功能),包含抽象方法 、默认方法和静态方法、私有方法。

  • 概念

接口就是一种公共的规范标准,只要符合规范标准,大家都可以通用。都可以参与进来进行编码,java就是面向接口的编程。

Java中的接口更多的体现在对行为的抽象!

接口语法

接口用关键字interface修饰

public interface 接口名 {} 

接口的使用

接口是不能创建对象,必须有实现类才能使用,类实现接口用implements表示。

public class 类名 implements 接口名 {}

接口成员的特点

成员变量

只能是常量,默认修饰符:public static final

成员方法

只能是抽象方法,默认修饰符:public abstract

构造方法

无,因为接口主要是扩展功能的,而没有具体存在

代码演示

  • 接口

    public interface Inter {
        //接口只能是常量
        //默认修饰符:public static final
        public int num1 = 10;
        public final  int num2 = 20;
        public static final int num3 = 30;
        int num4 = 40;
    
        //接口没有构造方法
        // public Inter() {}
        //接口中不能有方法主体
        // public void show() {}
        //默认修饰符:public abstract 
        public abstract void method1();
    
        public void method2();
        void show();
    }
    
  • 实现类

    //子类可以是抽象类。但是意义不大
    public abstract class InterImpl extends Object implements  Inter {}
    /**
     *   字类是具体类,要实现接口中所有的抽象方法
     *   所有类都默认继承Object类,Object类是所有类的超类
     */
    public class InterImpl extends Object implements  Inter {
        public InterImpl(){
            super();//所有super走得是object类
        } 
        @Override
        public void method1() {
            System.out.println("实现类中的method1");
        }
        @Override
        public void method2() {
            System.out.println("实现类中的method2");
        }
        @Override
        public void show() {
            System.out.println("实现类中的show");
        }
    }
    
  • 测试类

    public class Test {
        public static void main(String[] args) {
            //接口不能实例化
            // Inter i = new Inter();
            //通过多态的方法实
            Inter i = new InterImpl();
            //访问成员变量
            System.out.println(i.num1);
            //接口的常量是不能修改的
            // i.num1 = 100;
    
            i.method1();
            i.method2();
            i.show();
        }
    }
    

类与接口的关系

类与类:
	继承关系,只能单继承,不能多继承,可以多层继承(Father son sun)。
	extends 	
接口与接口:
	继承关系,可以单继承也可以多继承。public interface Sister extends I1,I2 
    
类与接口:
	实现关系,可以单实现,也可以多实现。 public class Son extends Object implements I1,I2 
	并且还可以在继承一个类的同时实现多个接口。

抽象类和接口的区别

A:成员区别
	抽象类:
		成员变量:可以变量,也可以常量
		构造方法:有
		抽象类不能实现化
		成员方法:可以抽象,也可以非抽象
	接口:
		成员变量:只可以静态常量  可以省略 static final
		构造方法:无
		接口不能实例化
		成员方法:只可以抽象     可以省略abstract
B:关系区别
	类与类
		继承,单继承, 多层继承
	类与接口
		实现,单实现,多实现
	接口与接口
		继承,单继承,多继承

C:设计理念区别
	抽象类【共性功能】。一般父类抽象
	接口【扩展功能】。 方法集合

继承父类并实现多个接口

之前学过,在继承体系中,一个类只能继承一个父类。而对于接口而言,一个类是可以实现多个接口的,这叫做接口的多实现。并且,一个类能继承一个父类,同时实现多个接口。

多实现语法

class 类名 [extends 父类名] implements 接口名1,接口名2,接口名3... {    
    // 重写接口中抽象方法【必须】
    // 重写接口中默认方法【不重名时可选】
} 

代码演示

  • 定义接口

    interface A {
        public abstract void showA();   
        public abstract void show();
    }
    interface B {
        public abstract void showB();   
        public abstract void show();
    }
    
  • 定义父类

    public class Fu{}
    
  • 定义实现类

    public class C extends Fu implements A,B{
        @Override
        public void showA() {
            System.out.println("showA");    }
        @Override
        public void showB() {
            System.out.println("showB");    }
        @Override
        public void show() {
            System.out.println("show");    }
    }
    
  • 注意事项

    接口中,有多个抽象方法时,实现类必须重写所有抽象方法。如果抽象方法有重名的,只需要重写一次即可!
    如果实现类继承了父类,这个父类是一个抽象类时,我们还需要再重写抽象类中的所有抽象方法。

接口之间的多继承

一个接口能继承另一个或者多个接口,这和类之间的继承比较相似。接口的继承使用extends关键字,子接口继承父接口的方法。如果父接口中的默认方法有重名的,那么子接口需要重写一次。

  • 定义父接口

    interface A {
        public void method1();
    }
    interface B {
        public void method2();
    }
    
  • 定义子接口

    interface D extends A,B{
         public void method2();
    }
    
  • 注意

    接口多继承之后,如果想使用,我们还必须定义实现类,才能使用
    

接口小结

接口案例-TODO

  • 需求

    对猫和狗进行训练,他们就可以跳高了,这里加入跳高功能。

    请采用抽象类和接口来实现猫狗案例,并在测试类中进行测试。

  • 代码实现

    • Animal类
      public abstract class Animal {
          private String name;
          private int age;
      
          public Animal() {
          }
          public Animal(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 abstract void eat();
      }
      
    • 跳高接口Jumping
      public interface Jumpping {
          public abstract void jump();
      

    }

    
    * ##### 猫类(Cat)
    
    ```java
    //子类继承 抽象类,实现接口
    public class Cat extends Animal implements Jumpping {
      public Cat() {
        }
      public Cat(String name, int age) {
            super(name, age);
        }
        @Override
        public void eat() {
            System.out.println("猫吃鱼");
        }
        @Override
        public void jump() {
            System.out.println("猫可以跳高了");
        }
    }
    
    • 测试类
      public class AnimalDemo {
          public static void main(String[] args) {
              Cat c = new Cat();
              c.setName("加菲");
              c.setAge(5);
              System.out.println(c.getName()+","+c.getAge());
            c.eat();
              c.jump();
        }
      }
      

多态

龙生九子

公司:老板下令,开始干活儿;

行政人员、程序猿、财务人员、市场人员;干活,不一样;

什么是多态

多态是继封装、继承之后,面向对象的第三大特性。对象的多种形态。

  • 定义:同一个对象,在不同时刻表现出来的行为是不同的。

前提条件

1.要有继承或实现关系
2.要有方法的重写
3.要有父类引用指向子类对象   fu  f = new zi();

多态中的成员访问特点

Java引用变量有两个类型:编译时类型和运行时类型。编译时类型由声明决定该变量使用的类型,运行时类型由实际赋给该变量的对象决定。简称:编译时,看左边;运行时,看右边。
若编译时类型和运行时类型不一致,就出现了对象的多态性, 多态情况下,
“看左边” :看的是父类的引用(父类中不具备子类特有的方法)
“看右边”:看的是子类的对象(实际运行的是子类重写父类的方法)

编译看左边(父类),运行看右边(子类)

代码演示

  • 动物类(Animal)
    public class Animal {
        public int age = 40;
        public void eat() {
            System.out.println("动物吃东西");
        }
    }
    
  • 猫类(Cat)
    public class Cat extends Animal {
        public int age = 20;
        public int weight = 10;
    
        //子类要重写父类中的方法
        @Override
        public void eat() {
            System.out.println("猫吃鱼");
        }
    
        public void playGame() {
            System.out.println("猫捉迷藏");
        }
    }
    
  • 测试类
    public class AnimalDemo {
        public static void main(String[] args) {
            //有父类引用指向子类对象
            Animal a = new Cat();
    
          	//成员变量
            //编译看左边(父类),运行看左边(父类)
            System.out.println(a.age);
            // System.out.println(a.weight);
    
            //成员方法
            //编译看左边(父类),运行看右边(子类)
            a.eat();
            // a.playGame();
        }
    }
    

多态的好处和弊端

多态的好处

提高程序的扩展性。定义方法时候,使用父类型作为参数,在使用的时候,使用具体的子类型参与操作。

多态的弊端

不能使用子类的特有成员

多态的好处代码演示

实际开发的过程中,父类类型作为方法形式参数,传递子类对象给方法,进行方法的调用,更能体现出多态的扩展性与便利

  • 定义父类
    public abstract class Animal {      
        public abstract void eat();
    }  
    
  • 定义子类
    class Cat extends Animal {  
        public void eat() {  
            System.out.println("吃鱼");  
        }  
    } 
    class Dog extends Animal {  
        public void eat() {  
            System.out.println("吃骨头");      }  
    }
    
  • 定义测试类
    public class Test {
        public static void main(String[] args) {        // 多态形式,创建对象
            Cat c = new Cat();  
            Dog d = new Dog(); 
            // 调用showCatEat 
            showCatEat(c);
            // 调用showDogEat 
            showDogEat(d); 
            /*
           	 多态的好处: 
           	 以上两个方法, 均可以被showAnimalEat(Animal a)方法所替代,而执行效果一致
            */
            showAnimalEat(c);
            showAnimalEat(d); 
        }
    
        public static void showCatEat (Cat c){
            c.eat(); 
        }
        public static void showDogEat (Dog d){
            d.eat();
        }
        public static void showAnimalEat (Animal a){
            a.eat();
        }
    }
    

多态的好处小结

​ 由于多态特性的支持,showAnimalEat方法的Animal类型,是Cat和Dog的父类类型,父类类型接收子类对象,当然可以把Cat对象和Dog对象,传递给方法。当eat方法执行时,多态规定,执行的是子类重写的方法,那么效果自然与showCatEat、showDogEat方法一致,

​ 所以showAnimalEat完全可以替代以上两方法。

​ 不仅仅是替代,在扩展性方面,无论之后再多的子类出现,我们都不需要编写showXxxEat方法了,直接使用showAnimalEat都可以完成。

​ 所以,多态的好处,体现在,可以使程序编写的更简单,并有良好的扩展。

多态中的转型

为什么要用转型

当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误。也就是说,不能调用子类拥有,而父类没有的方法。编译都错误,更别说运行了。这也是多态给我们带来的一点"小麻烦"。所以,想要调用子类特有的方法,必须做向下转型。

向上转型

子类的对象可以被当做基础的对象称为向上对象。系统默认。

  • 使用格式
    向上转型
         父类类型  变量名 = new 子类类型();
    如:Animal a = new Cat();
    

向下转型

父类类型向子类类型向下转换的过程,这个过程是强制的。

一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制类型转换的格式,便是向下转型。

  • 使用格式
    子类类型 变量名 = (子类类型) 父类变量名;:Cat c =(Cat) a;  
    

代码演示

  • 定义类
    abstract class Animal {  
        abstract void eat();  
    }  
    
    class Cat extends Animal {  
        public void eat() {  
            System.out.println("吃鱼");  
        }  
        public void catchMouse() {  
            System.out.println("抓老鼠");      
        }  
    }  
    
    class Dog extends Animal {  
        public void eat() {  
            System.out.println("吃骨头");     
        }  
        public void watchHouse() {  
            System.out.println("看家");  
        }  
    }
    
  • 测试类
    public class Test {
        public static void main(String[] args) {
            // 向上转型     fu f = new zi()
            Animal a = new Cat();  
            a.eat();                     // 调用的是 Cat 的 eat
    
            // 向下转型    zi z = (zi)fu; 
            Cat c = (Cat)a;       
            c.catchMouse();              // 调用的是 Cat 的 catchMouse     
        }
    }  
    

转型的异常

问题描述

转型的过程中,一不小心就会遇到这样的问题,请看如下代码:

 public class Test {
    public static void main(String[] args) {
        // 向上转型  
        Animal a = new Cat();  
        a.eat();        // 调用的是 Cat 的 eat
        
        // 向下转型 
        Cat c = (Cat)a;
        c.catchMouse();//调用自己的方法
        System.out.println("================");
 
        // 向下转型  
        Dog d = (Dog)a;       //引用的父类,是多态cat类,并不是dog
        d.watchHouse();        // 调用的是 Dog 的 watchHouse 【运行报错】    
    }  
}

这段代码可以通过编译,但是运行时,却报出了ClassCastException类型转换异常!这是因为,明明创建了

Cat类型对象,运行时,当然不能转换成Dog对象的。这两个类型并没有任何继承关系,不符合类型转换的定义。

为了避免ClassCastException的发生,Java提供了instanceof关键字,给引用变量做类型的校验,格式如下:

instanceof使用格式

变量名 instanceof 数据类型 
    如果变量属于该数据类型,返回true。
    如果变量不属于该数据类型,返回false

instanceof代码演示

public class Test {
    public static void main(String[] args) {
        // 向上转型  
        Animal a = new Cat();  
        a.eat();               // 调用的是 Cat 的 eat

        // 向下转型  
        if (a instanceof Cat){
            Cat c = (Cat)a;       
            c.catchMouse();        // 调用的是 Cat 的 catchMouse        
        } else if (a instanceof Dog){
            Dog d = (Dog)a;       
            d.watchHouse();       // 调用的是 Dog 的 watchHouse
        }
    }  
}

综合案例-TODO

案例需求

我们现在有乒乓球运动员和篮球运动员,乒乓球教练和篮球教练。

​ 为了出国交流,跟乒乓球相关的人员都需要学习英语。

​ 请用所学知识分析,这个案例中有哪些具体类,哪些抽象类,哪些接口,并用代码实现。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yIATmfsv-1671668242460)(assets/01.png)]

代码实现

  • Person类

    public abstract class Person {
        private String name;
        private int age;
    
        public Person() {
        }
    
        public Person(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 abstract void eat();
    }
    
  • 抽象运动员类(Player)

    public abstract class Player extends Person {
        public Player() {
        }
    
        public Player(String name, int age) {
            super(name, age);
        }
    
        public abstract void study();
    }
    
  • 抽象教练类(Coach)

    public abstract class Coach extends Person {
        public Coach() {
        }
    
        public Coach(String name, int age) {
            super(name, age);
        }
    
        public abstract void teach();
    }
    
  • 学英语接口(SpeakEnglish)

    public interface SpeakEnglish {
        public abstract void speak();
    }
    
  • 蓝球教练(BasketballCoach)

    public class BasketballCoach extends Coach {
        public BasketballCoach() {
        }
    
        public BasketballCoach(String name, int age) {
            super(name, age);
        }
    
        @Override
        public void teach() {
            System.out.println("篮球教练教如何运球和投篮");
        }
    
        @Override
        public void eat() {
            System.out.println("篮球教练吃羊肉,喝羊奶");
        }
    }
    
  • 乒乓球教练(PingPangCoach)

    public class PingPangCoach extends Coach implements SpeakEnglish {
    
        public PingPangCoach() {
        }
    
        public PingPangCoach(String name, int age) {
            super(name, age);
        }
    
        @Override
        public void teach() {
            System.out.println("乒乓球教练教如何发球和接球");
        }
    
        @Override
        public void eat() {
            System.out.println("乒乓球教练吃小白菜,喝大米粥");
        }
    
        @Override
        public void speak() {
            System.out.println("乒乓球教练说英语");
        }
    }
    
  • 乒乓球运动员(PingPangPlayer)

    public class PingPangPlayer extends Player implements SpeakEnglish {
    
        public PingPangPlayer() {
        }
    
        public PingPangPlayer(String name, int age) {
            super(name, age);
        }
    
        @Override
        public void study() {
            System.out.println("乒乓球运动员学习如何发球和接球");
        }
    
        @Override
        public void eat() {
            System.out.println("乒乓球运动员吃大白菜,喝小米粥");
        }
    
        @Override
        public void speak() {
            System.out.println("乒乓球运动员说英语");
        }
    }
    
  • 篮球运动员(BasketballPlayer)

    public class BasketballPlayer extends Player {
        public BasketballPlayer() {
        }
    
        public BasketballPlayer(String name, int age) {
            super(name, age);
        }
    
        @Override
        public void study() {
            System.out.println("篮球运动员学习如何运球和投篮");
        }
    
        @Override
        public void eat() {
            System.out.println("篮球运动员吃牛肉,喝牛奶");
        }
    }
    

Player(String name, int age) {
super(name, age);
}

  @Override
  public void study() {
      System.out.println("乒乓球运动员学习如何发球和接球");
  }

  @Override
  public void eat() {
      System.out.println("乒乓球运动员吃大白菜,喝小米粥");
  }

  @Override
  public void speak() {
      System.out.println("乒乓球运动员说英语");
  }

}


* #### 篮球运动员(BasketballPlayer)

```java
public class BasketballPlayer extends Player {
    public BasketballPlayer() {
    }

    public BasketballPlayer(String name, int age) {
        super(name, age);
    }

    @Override
    public void study() {
        System.out.println("篮球运动员学习如何运球和投篮");
    }

    @Override
    public void eat() {
        System.out.println("篮球运动员吃牛肉,喝牛奶");
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/107334.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一个程序员的新冠防护最佳实践

至今未阳,做了几次抗原检测都是阴性,所以把个人的防护经验给广大程序员朋友分享一下,尤其家里有小孩老人的可以参考一下。 我一天的防护操作 1、午餐 吃午饭时,走楼梯不去挤电梯,而且是在其他人吃完饭后&#xff0c…

Unreal Engine中调试常用方法

目录 常用调试方法 AddOnScreenDebugMessage UE_LOG:在控制台看调试信息 在蓝图中直接调用PrintString 自定义日志分类 声明 定义 简化日志输出的宏 日志格式化输出 常用调试方法 在虚幻引擎中常用的打印日志方法有三种,分别是:UE_…

C++运算符重载,匿名对象

目录 1、加号运算符重载 1.1 通过自己写成员函数,实现两个对象相加属性后返回新的对象 1.2通过成员函数实现加法运算符重载 1.3通过全局函数实现加法运算符重载,运算符重载也可以发生函数重载 1.4总结--对于内置的数据类型的表达式运算符是不可以改变…

Python+Requests实现接口自动化测试

一般对于自动化的理解,有两种方式的自动化。 第一,不需要写代码,完全由工具实现,这种方式的工具一般是公司自己研发的,方便黑盒测试人员使用。这种工具的特点是学习成本低,方便使用,但是通用性…

面向5G C-RAN组网的机房配置标准与模型

【摘 要】当前5G网络建设成本高,投资压力大,基站建设进度受铁塔公司制约;基站机房电费、租赁、服务费用逐年上升,运营维护压力大。面向未来5G建设,通过C-RAN组网,实现BBU集中化部署,可促进降本增效,实现低成本建网。首先分析了C-RAN区所处的网络位置,其次从BBU框多基…

java基于springboot的心理健康管理网站-计算机毕业设计

运行环境: 开发工具:IDEA /Eclipse 数据库:MYSQL5.7 应用服务:Tomcat7/Tomcat8 使用框架springbootvue 项目介绍 心灵治愈交流平台的主要使用者分为管理员和用户、心理咨询师,实现功能包括管理员:首页、个人中心、系统公告管理、用户管理、心…

网上订餐项目(附源代码及数据库)

目录 一、项目概要 二、项目展示 三、数据库 四、项目源码 五、毕设专栏 首页 登录界面 注册页面 一、项目概要 系统主要功能模块有: (1)首页菜品:主要包括购买菜品、菜品加入购物车的功能 (2)我的…

django-rest-framework

文章目录 (1)Web应用模式及API接口 (2)Restful规范 (3)drf安装和简单使用 (4)源码分析 (5)序列化器-Serializer (6)局部和全局响应配…

STL篇之vector

一、介绍 1. vector是表示可变大小数组的序列容器。 2. 就像数组一样,vector也采用的连续存储空间来存储元素。也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它…

NR HARQ (四)dynamic codebook

微信同步更新欢迎关注同名modem协议笔记 上篇提到type-1 HARQ-ACK codebook,即semi-static codebook,UE要为每个PDSCH候选位置生成反馈,也会包含实际没有下行传输的PDSCH,再加上配置CBG的场景,HARQ-ACK 码本中包含的无…

SpringBoot系列之数据库初始化-datasource配置方式

在我们的日常业务开发过程中,如果有db的相关操作,通常我们是直接建立好对应的库表结构,并初始化对应的数据,即更常见的情况下是我们在已有表结构基础之下,进行开发; 但是当我们是以项目形式工作时&#xff…

java微信支付v3系列——3.订单创建准备操作

微信支付的下单操作分为了5种,分别是JSAPI、APP、H5以及Native支付及小程序支付,之所以将支付放在单独一个章节,而不是按照支付类型划分一个章节,是因为支付所传递的数据都是相似的,方便我们更好的封装。 本章节是支付…

20221222英语学习

托福词汇 sociology n.社会学 given adj.规定的,特定的;假定的 narrative n.叙述;记叙体,叙述技巧 deplore vt.悲叹,哀叹,公开谴责 despoil vt.夺取,掠夺;毁坏,破坏…

Kubernetes:环境搭建

文章目录1、k8s 概念1.1、基本概念1.2、基本术语2、k8s 架构2.1、k8s 节点2.2、k8s 组件2.2.1、master 组件2.2.2、node 组件3、k8s 集群安装配置3.1、docker3.2、主机环境调整3.3、安装 kube 工具3.4、Master 节点初始化3.5、node 节点初始化3.6、重置节点4、k8s 集群升级4.1、…

基于node.js网上蛋糕店系统的设计与实现(论文+项目源码)

随着互联网应用技术的突飞猛进。信息化广泛使用,已渗透到各行各业。作为代表的以网上购物商城为例。它极大地改变了人们的出行方式以及线上购物发生的转变。网上购物的需求也随着人们的个性化定制而变得相对复杂。用户量以及需求量在网上商城也带来了很多商家的考验…

c++primer第2章 变量和基本类型

文章目录第2章 变量和基本类型2.1 基本内置类型2.1.1 算术类型2.1.2 类型转换2.1.3 字面值常量2.2 变量2.2.1 变量定义2.2.2 变量声明与定义的关系2.2.3 标识符2.2.4 名字的作用域第Ⅰ部分 c基础 语法特征 类型 变量 语句 控制结构 函数补充:自定义数据类型(语言扩展…

Elasticsearch:如何减少 Elasticsearch 集群中的分片数量

在我之前的文章 “Elasticsearch:我的 Elasticsearch 集群中应该有多少个分片?” , 它描述了在我们实际操作中的分片数量的准则。在文章 “Elasticsearch:如何部署 Elasticsearch 来满足自己的要求” 讲述了如何部署 Elasticsearc…

Prometheus系列之Grafana 版本9.0.0 设置Email邮件报警实战

目录1. 配置文件conf/defaults.ini修改2. Grafana Web页面配置报警邮箱接收者3. 创建Dashboard4. 创建Alert的文件夹5. 设置Notification policies6. 添加Alert7. Alert Rule测试1. 配置文件conf/defaults.ini修改 将conf/defaults.ini的如下内容 ##########################…