面向对象4 09

★ abstract

抽象类、抽象方法 。

抽象方法:有abstract修饰,没有方法体。

 抽象类:使用abstract修饰的类

有得有失: 有得:抽象类可以有抽象方法

 有失:抽象类不能创建实例。

 即使该抽象类的所有方法都已提供了实现,该抽象类依然不能创建实例。

★ 接口

  相当于彻底抽象的类,更加不可能创建实例。
   接口相当于公开的规范,因此接口中的所有成员都是public。

 语法格式:

[修饰符] interface <接口名> extends 父接口1, 父接口2, ...

{

// 常量定义
          // 抽象方法(无方法体的实例方法)、default方法(有方法体的实例方法)、static方法
          // 内部类、内部接口、内部枚举

}

 接口:用于被实现。
           实现接口,其意义就是相当于继承父类。
           一个类,可以同时实现多个接口,这样就弥补了Java单继承的灵活性不足的问题。

★ 内部类

 内部类:直接放在另一个类的类体中定义

 内部类:直接放在另一个类的类体中定义。


     外部类(宿主类)
     内部类(嵌套类、寄生类)




     ★ 内部类与外部类的语法上区别:


      - 内部类可以使用private|protected|public、static、final|abstract修饰,外部类只能使用public、final|abstract。


      - 非静态内部类不允许拥有静态成员,除非静态成员变量,且使用final修饰,且指定了初始值。


      - 静态内部类不允许直接访问外部类的实例成员


        内部类class文件名:  外部类$内部类.class


     ★ 为什么要定义内部类?内部类的便捷之处?


        1. 内部类可以提供更好的封装。
           内部类在外部类中可使用private、protected、public修饰,因此可以更好地进行封装。


        2. 内部类可以直接访问外部类的成员,即使是外部类的private成员。
           静态内部类(类成员)不允许直接访问外部类的实例成员。


           当内部类的实例变量名与外部类的实例变量名冲突时。
           要显式添加   外部类.this. 来限定访问外部类的实例变量


     ★ 使用内部类:
         如果只是在外部类的里面使用内部类(除了注意:静态成员不能访问非静态成员之外),
        使用内部类,与使用普通外部类几乎没有区别。


         ▲ 使用静态内部类
            静态内部类的实例,必须寄生在外部类的类本身里 
            在外部类以外的地方使用静态内部类:
            声明变量、调用类方法或访问类变量、创建对象、派生子类 
            —— 做这些事情时,应按如下格式使用静态内部类


            外部类.内部类  —— 相当于外部类是内部类的一个包名。




         ▲ 使用非静态内部类 - 【难理解,仅供参考】


            【总原则】:非静态内部类的实例,必须寄生在外部类的实例里 
                        ——如果没有外部类的实例,不可能有非静态内部类实例。


            
            ◆ 使用非静态内部类定义变量:
           
               外部类.内部类 变量名;


            ◆ 使用非静态内部类创建实例
           
               宿主.new 非静态内部类构造器();




            ◆ 使用非静态内部类派生子类
           
               extends 外部类.内部类


               在非静态内部类的子类的构造器的第一行,必须使用
               宿主.super(参数)调用非静态内部类的子类的构造器




         ▲ 使用局部内部类  - 很少见、简单了解。
               
              比较鸡肋的语法。


              将类定义在方法里,该类就只能在该方法体内使用,离开了该方法就无效。
              局部内部类只能用final|abstract修饰。其他private、protected、public、static一概不行。


              局部内部类只能在该方法内使用,因此比较简单。




              局部内部类的class文件的文件名: 外部类$N局部内部类.class




      课堂练习:定义一个内部类,去访问外部类出private成员。
                在外部类以外的地方使用静态内部类。
           
         ▲ 匿名内部类 - 【重点】


              new 接口|父类构造器()
              {
                    // 重写方法
              }


           - 匿名内部类要么就实现一个接口,要么继承某个父类,二者只能选择其中之一。
             不能同时实现多个接口,也不能既实现接口,也继承父类。


           - 匿名内部类以后没法复用。


           - 定义匿名内部类的同时,会立即创建匿名内部类的实例。
             因此匿名内部类不可能是抽象类。
               
             匿名内部类的class文件的文件名: 外部类$N.class

★ Java 8的Lambda表达式


      Lambda可以很好地简化编程,Java 8的最大改变就是Lambda表达式。


      Lambda用于取代匿名内部类,只能为函数式接口创建实例。




      函数式接口:有且仅有一个抽象方法(至于default方法、static方法不关心)的接口,就是函数式接口。


      @FunctionalInterface让编译器对该接口执行检查,如果该接口确实是函数式接口,编译器就不作声;否则就报错。




      Lambda表达式总是去实现函数式接口中唯一的抽象方法。


       语法格式:
         (形参列表) -> {
                方法体
          };
       
        形参列表:可以省略形参类型;如果只有一个形参,连括号都可以省略。


        方法体:如果方法体只有一条代码,花括号也可以省略。  






      ★ Lambda表达式中方法引用与构造器引用:


      ▲ 调用类方法:


         类名::类方法   用于代替执行体中    类名.类方法(参数列表)
         要求调用类方法的参数列表与重写的方法的参数列表完全相同。


      ▲ 调用对象的实例方法:


         对象::实例方法


      ▲ 调用对象的实例方法:


         abc对象的类::实例方法      abc.实例方法(参数1, 参数2, 参数3,...);




      ▲ 构造器引用


         类名::new -   也是省略了参数列表。


         (参数列表)->return new 类名(参数列表)
          简化为:
          类名::new


     
课堂练习: 写一个函数式接口,分别用匿名内部类、lambada表达式创建该类实例。


★ 枚举(JDK 1.5才新增):


      Java程序单元: 类、接口和枚举


      ▲ 定义枚举的语法:


      [修饰符] enum <枚举名>
      {
           // 第一行列出所有枚举实例




      }


      [修饰符]  -  枚举修饰符总有final或abstract修饰。
      


      枚举的构造器必须是private修饰,你不写系统会自动使用private修饰。




      ▲ 枚举到底是什么?


         枚举就是“实例数量固定”的类。


         单例类,相当于一个极端的枚举,可以枚举定义单例更方面。


         枚举类与普通类的区别:
         - 枚举类总是继承java.lang.Enum基类,普通类默认继承Object
         - 枚举类要么使用final修饰,要么使用abstract修饰。
         - 枚举的所有构造器都是private,不管你写还是不写,都在哪里。
         - 枚举要求在第一行列出所有枚举实例。


         普通类能定义的5种成员,枚举类中一样都是可以定义的。


      ▲ 使用枚举


         枚举赋值,直接使用定义枚举时已经指定的实例即可。


         switch(表达式)  switch表达式类型是byte\short\int\char\String\枚举




         只要你定义了枚举,默认即可使用如下方法:
         name() - 该方法返回枚举实例的名字。
         ordinal() - 序号。返回该枚举实例的序号(索引)。
         static values() - 该方法返回所有的枚举实例。
         static valueOf(java.lang.String):根据枚举名来获取实际的枚举实例。
         
         -------------------枚举基础-------------------




      ▲ 枚举的构造器


         枚举的构造器只能是private修饰。


         所有枚举实例,其实就是public static final修饰的常量


         【枚举第一行并不是简单地列出枚举实例,而是要调用指定构造器来创建枚举实例。】




         -------------------枚举进阶-------------------




      ▲ 抽象枚举  (高级,学习才要求掌握)


         【枚举第一行并不是简单地调用构造器来创建枚举实例,开始一段要用匿名内部类创建枚举实例。】


          抽象枚举无法直接创建实例,必须在开始部分用匿名内部类创建抽象枚举的子类的实例。




      ▲ 枚举实现接口


         - 枚举实现接口,并实现接口中所有抽象方法,因此直接定义即可。
         - 枚举实现了接口,但并未实现接口中所有抽象方法,此时就用抽象枚举的语法来创建枚举实例。


         -------------------枚举高级-------------------



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值