目录

面向对象高级特性


面向对象高级特性

1 抽象

1.1 为什么会有抽象类

  • 当子类中都有一个共同的方法,每一个子类都有不同的实现,在父类中又要体现所有子类的共同的特点,所以要体现有这个方法,但是在父类中又无法给出具体的实现,那么这个时候就需要把这个方法声明为抽象的,而包含抽象方法的类,必须是抽象类
  • 某个父类仅仅是表示一个抽象的概念,不希望它被实例化,这个时候父类中可能没有抽象方法,但是我们也把它声明为抽象类

1.2 如何声明抽象类

  • 语法格式

    • [public/缺省] abstract class 类名{ }

1.3 如何声明抽象方法

  • 语法格式

    • [public/protected/缺省] abstract 返回值类型 方法名([形参列表]);

      • 抽象方法是不能private,static,final修饰的

1.4 抽象类的特点

  • (1)抽象类不能实例化 (2)抽象类可以包含抽象方法,也可以没有抽象方法。 如果一个类有抽象方法,那么这个类必须是抽象类, 如果一个抽象类没有抽象方法,那么它的用意是不想实例化,用它仅仅表示一个抽象的概念。 (3)抽象类生来就是用来被继承的,那么子类在继承它的时候,必须重写(实现)抽象父类的抽象方法, 否则该子类也得是抽象类。 (4)抽象类的变量与子类的对象构成多态引用。 (5)抽象类除了不能实例化,可以包含抽象方法,其他的和非抽象类是一样的, 可以有成员变量(类变量、实例变量)、构造器、代码块(静态代码块和非静态代码块) 方法(静态方法、非静态方法)

1.5 抽象类不能实例化,为什么要有构造器呢?

  • 子类在继承该类时,一定要调用它的构造器,为属性初始化。

    • 因为构造器的作用有两点

      • (1)和new一起创建对象
      • (2)为属性初始化

2 接口

2.1 接口即代表行为标准,功能标准

2.2 如何声明一个接口?

  • 语法结构

    • [public/缺省] interface 接口名{ }

2.3 如何实现接口?

  • 语法结构

    • [public/缺省] class 子类名 [extends 父类名] implements 接口名1,接口名2。。。{ //要实现接口的所有抽象方法 }

2.4 接口的特点

  • JDK1.7

    • JDK1.7: (1)接口不能实例化 (2)接口只能有全局静态的常量和公共的抽象方法 (3)接口中不能有构造器,因为它没有属性需要初始化,又不能创建对象 (4)接口生来用来被实现的,那么实现类(像子类)在实现它时,必须实现(和重写要求一样)接口的 所有抽象方法,否则该实现类也得是抽象类 (5)一个类可以同时实现多个接口 (6)一个类还可以继承父类又实现接口,但是必须先继承后实现 (7)接口与接口之间是继承关系,一个接口可以继承多个接口 (8)接口与实现类的对象之间构成多态引用
  • JDK1.8

    • 其他的和JDK1.7一样,不一样的是: JDK1.8之后,接口中除了全局静态的常量和公共的抽象方法以外,可以有静态方法和默认方法

      • 接口中的静态方法

        • 当接口的所有实现类,对这个方法的实现是一样的,这个方法就设计在接口中,设计为静态方法

        • 如何调用

          • 接口名.方法
      • 接口中的默认方法

        • 当接口的大多数实现类,对这个方法的实现是一样,那么这个方法的实现就可以在接口中提供默认实现,如果某个实现类觉得他不合适,只需要重写它即可

        • 如何调用

          • 实现类外

            • 实现类对象.方法
          • 实现类中

            • 如果实现类要重写该默认方法,但是又想调用接口中的默认实现
            • 接口名.super.方法
        • 什么情况下需要重写

          • 接口中的默认实现不适合该实现类

          • 必须重写

            • 一个类同时实现了多个接口,而多个接口中都相同的默认方法(方法名和形参列表都相同),这个时候实现类必须做出选择,要重写,如果需要保留其中一个的话,通过接口名.super.方法,保留它的默认实现
        • 类优先原则

          • 当一个类继承了父类,又实现了接口,而且父类中的某个方法与接口中的默认方法一样(方法名和形参列表),默认保留的是父类中的方法实现

3 枚举

3.1 枚举是指某个类型的对象是有限个,在类型中一一创建并列举它的对象

3.2 JDK1.5之前,如何解决

  • (1)构造器私有化

  • (2)通过常量的方式创建好所有对象

  • 示例

    class Week{

    public static final Week MONDAY = new Week();

    public static final Week TUESDAY = new Week();

    public static final Week WEDNESDAY = new Week();

    public static final Week THURSDAY = new Week();

    public static final Week FRIDAY = new Week();

    public static final Week SATURDAY = new Week();

    public static final Week SUNDAY = new Week();

    private Week(){

    }

    }

    Week w = Week.MONDAY;

3.3 JDK1.5之后,如何解决

  • 如何声明

    • [修饰符] enum 枚举类型名{ 常量对象列表 }
    • [修饰符] enum 枚举类型名{ 常量对象列表; 其他成员; }
  • 特点

    • (1)枚举类型中的构造器都是私有化

    • (2)常量对象列表必须在首行,如果常量对象列表后面还有其他的代码,那么要用;结束

    • (3)枚举类型不能继承别的类型,因为它默认继承java.lang.Enum

      • 它有一些方法

        • name()

          • 返回常量对象名
        • ordinal()

          • 返回常量对象的序号,从0开始
        • 实现了java.lang.Comparable接口,重写compareTo(),按照常量对象的顺序排序

          • 如果自己的枚举类中不适合,可以重写
        • toString()

          • 返回常量对象名

            • 可以重写
      • API中没有的方法

        • 枚举类型名.values()

          • 返回枚举常量对象组成的数组
        • 枚举类型名.valueOf(常量对象的名称)

          • 返回某一个指定的对象
    • (4)switch对枚举加入支持

      • switch(枚举类型表达式){ case 常量对象名1: 语句; [break;] case 常量对象名2: 语句; [break;] case 常量对象名3: 语句; [break;] default: 语句; [break;] }

4 注解

4.1 概念

  • 代码级别的注释

  • 给代码读取的注释

    • 不同普通的注释(给人看的)

      • 单行注释
      • 多行注释

4.2 四种

  • 1、编译器的格式检查

    • (1)@Override:告知编译器对该方法按照“重写”的要求进行格式检查
    • (2)@SuppressWarnings:告知编译器抑制警告
    • (3)@Deprecated:告知编译器某个元素是已过时,有人用了就弹出警告
  • 2、文档注释

    • (1)@version

      • 指定当前版本
    • (2)@author

      • 指定作者
    • (3)@since

      • 指定从哪个版本开始
    • (4)@see

      • 另请参阅
    • (5)param

      • 指定当前方法的形参信息

      • 可以多个

      • 只有方法有形参才能标记

      • 格式:

        • @param 形参名 形参类型 形参的描述信息
    • (6)@return

      • 指定当前方法的返回值信息

      • 一个方法只能有一个,如果方法是void,就不能标记@return

      • 格式

        • @return 返回值的类型 返回值的描述
    • (7)@exception

      • 指定当前方法抛出异常的信息

      • 可以多个

      • 只有方法抛出异常才能标记

      • 格式

        • @exception 异常类型 异常的描述
    • 结合javadoc.exe

  • 3、JUnit的单元测试

    • 白盒测试,程序员自己的测试,在程序员知道当前的代码的功能的

    • @Test

      • 加在方法上
      • 这个方法必须是公共的,无参,无返回值,不能是static
    • @Before

      • 在@Test标记的方法之前运行
    • @After

      • 在@Test标记的方法之后运行
  • 4、各大框架等替代配置文件

4.3 注解的三个部分

  • 1、声明

    • 一般都是别人声明好的
  • 2、使用

  • 3、读取

    • 例如:@Override等,由javac.exe
    • 例如:@author,@param等,由javadoc.exe
    • 例如:@Test等,由JUnit相关的类读取
    • 例如:@WebServlet等,由Tomcat读取
    • 如果自己要读取,通过反射,而且只能读取@Retention(RetentionPolicy.RUNTIME)

4.4 注解的声明

  • (1)无参

    • 声明格式

      • @元注解 [修饰符] @interface 注解名{}
    • 使用格式

      • @注解名
  • (2)有参

    • 声明格式

      • @元注解 [修饰符] @interface 注解名{ 配置参数 }

        • 配置参数

          • 格式

            • 数据类型 参数名();
          • 一个注解可以有多个配置参数

          • 配置参数可以有默认值

            • 数据类型 参数名() default 默认值;
          • 配置参数的类型有要求

            • 类型只能是八种基本数据类型、String类型、Class类型、enum类型、Annotation类型、以上所有类型的数组
    • 使用格式

      • @注解(参数赋值)

        • 如果配置参数有默认值,那么可以在使用时不需要赋值

        • 如果配置参数只有一个,而且名称是value,那么可以在赋值时省略value=

        • 参数赋值的格式

          • 参数名 = 参数值

          • 如果多个使用,分割

          • 如果配置参数的类型是数组类型

            • 如果只有一个元素,那么可以省略{}
            • 如果是多个元素,那么需要{}

4.5 元注解

  • @Target

    • 指定某个注解它的使用目标位置

    • 如何指定它

      • 它配置参数的类型是一个枚举数组

        • ElementType枚举类型

          • 常量对象有:TYPE, FIELD,METHOD等
      • 配置参数的名称是value

      • 如果只有一个

        • @Target(ElementType.METHOD)
      • 如果是多个

        • @Target({ElementType.METHOD,ElementType.FIELD,。。。。})
  • @Retention

    • 指定某个注解的生命周期,可以保留到什么阶段

    • 如何指定它

      • 它的配置参数的类型是一个枚举类型

        • RetentionPolicy类型

          • 常量对象有三个

            • SOURCE,CLASS,RUNTIME
      • 配置参数的名称是value

      • @Retention(RetentionPolicy.RUNTIME)

  • @Documented

    • 表示是否javadoc读取
  • @Inherited

    • 是否被子类继承
  • 在java.lang.annotation包