【Java基础】抽象类、接口、内部的运用与作用分析,枚举类型的使用

1. 抽象类

在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,

  • 如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
  • 抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法、初始化块和构造方法和普通类一样。

并且抽象类和普通类相比还多出了抽象方法。

格式:

[修饰符] abstract class 类名{
    //零到多个成员变量
    //零到多个构造器
    //零到多个普通方法
    //零到多个抽象方法
    //零到多个初始化块
}

1.1 抽象方法:

抽象方法只包含一个方法名,而没有方法体,使用abstract修饰。
格式:

[修饰符] abstract 返回值类型 方法名(形参列表);

修饰符 (public protected private) 三选一

1.2 抽象类总结:

  1. 抽象类必须使用abstract修饰符来修饰,抽象方法也必须使用abstract修饰符来修饰,抽象方法不能有方法体。
  2. 抽象类不能被实例化,无法使用new关键字来调用抽象类的构造器创建抽象类的实例。
  3. 抽象类可以包含成员变量、方法(普通方法和抽象方法都可以)、构造器、初始化块、内部类(接 口、枚举)5种成分。
  4. 抽象类的构造器不能用于创建实例,主要是用于被其子类调用。
  5. 抽象类中不一定包含抽象方法,但是有抽象方法的类必定是抽象类
  6. abstract static不能同时修饰一个方法
  7. 抽象类可以有主函数,可以执行。

2. 接口 interface

接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。

  • 一个类通过实现接口的方式,从而来实现接口的抽象方法。

接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。

2.1 接口定义

[public] interface InterfaceOne [extends fatherInterface1,fatherInterface2...]{
    [public] [static] [final] type CONSTANT_NAME=Value;//定义常量
    //[public] [static] [final]可以不写,一般也不用写。 编译时自动为接口里定义的成员变量增加public static final修饰符

    [public] [abstract] returnType methodName(参数列表);//声明方法
    //[public] [abstract] 可以不用写,一般也不写。编译时自动为接口里定义的方法添加public abstract修饰符
}

接口有以下特性:

  1. 接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。
  2. 接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键字。
  3. 接口中的方法都是公有的。
  4. 编译时自动为接口里定义的方法添加public abstract修饰符
  5. Java接口里的成员变量只能是public static final共同修饰的,并且必须赋初值,可以不写public
  6. static final,编译的时候会自动添加

2.2 接口的实现

当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。
类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。
注意:JDK1.8+可以通过添加default关键字,不必强制实现所有方法。
Java中类可以实现多个接口
格式:

[修饰符] class 类名 [implements 接口1, 接口2, 接口3..., ...]
{
}

2.3 接口的继承

一个接口能继承另一个接口,和类之间的继承方式比较相似。接口的继承使用extends关键字,子接口继承父接口的方法。接口允许多继承

3. 抽象类和接口的对比

默认的方法实现:

  • 抽象类: 可以有默认的方法实现
  • 接口: 接口完全是抽象的,不存在方法的实现。但是从JDK1.8开始,接口也可以默认方法的实现。

实现:

  • 抽象类: 子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的抽象方法的实现。
  • 接口: 类使用关键字implements来实现接口。
    它需要提供接口中所有声明的方法的实现.但是从JDK1.8开始,接口也可以默认方法的实现。

构造器:

  • 抽象类: 抽象类可以有构造器
  • 接口: 接口不能有构造器

与正常Java类的区别:

  • 抽象类: 除了不能实例化抽象类之外,它和普通Java类没有任何区别
  • 接口: 接囗是完全不同的类型

访问修饰符:

  • 抽象类: 抽象方法可以有pubic、private、protected等修饰符
  • 接口: 接口方法默认修饰符是public。可以有pubic、private、protected等修饰符。

main方法:

  • 抽象类: 可以有main方法并且我们可以运行它
  • 接口: 接口有main方法,因此我们可以直接运行它。

多继承:

  • 抽象类: 抽象类可以继承一个类和实现多个接口
  • 接口: 接口可以继承一个或多个其它接口

添加新方法:

  • 抽象类: 如果你往抽象类中添加新的方法,你可以给它提供默认的实现。因此你不需要改变你现在的代码。
  • 接口: 如果你往接口中添加方法,那么你必须改变实现该接口的类。但是从JDK1.8开始,接口也可以默认方法的实现。

相同点:

  • 都位于继承的顶端,用于被其他类实现或继承;
  • 都不能直接实例化对象;
  • 都包含抽象方法,其子类都“必须”覆写这些抽象方法;

区别:

  • 抽象类为部分方法提供实现,避免子类重复实现这些方法,提高代码重用性; 接口“只能”包含抽象方法;
  • 一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;
  • 抽象类是这个事物中应该具备的内容, 继承体系是一种 is…a关系 ;接口是这个事物中的额外内容,实现体系是一种 like…a关系

二者的选用:

  • 优先选用接口,尽量少用抽象类;
  • 需要定义子类的行为,又要为子类提供共性功能时才选用抽象类;
  • 要实现的方法不是当前类族的必要,而是扩展,用接口.

4. 内部类

4.1 Java静态内部类

  • ( 可以看着两个普通类的访问关系 只是静态内部类的类名需要通过 外部类.内部类 )
    静态内部类有如下特点:
  1. 在创建静态内部类的实例时,不需要创建外部类的实例。
  2. 静态内部类中可以定义静态成员和实例成员。外部类以外的其他类需要通过完整的类名访问静态内部类中的静态成员,如果要访问静态内部类中的实例成员,则需要通过静态内部类的实例。
  3. 静态内部类可以直接访问外部类的静态成员,如果要访问外部类的实例成员,则需要通过外部类的实例去访问。
  4. 外部类可以通过静态内部类的类名直接访问静态内部类的静态成员,如果要访问静态内部类的实例成员,则需要通过静态内部类的实例去访问。

4.2 Java局部内部类

  • 局部内部类是指在一个方法(或代码块)中定义的内部类。

局部内部类有如下特点:

  1. 局部内部类与局部变量一样,不能使用访问控制修饰符(public、private 和 protected)和 static修饰符修饰。
  2. 局部内部类只在当前方法(代码块)中有效。
  3. 局部内部类中不能定义 static 成员。
    可以有 final static修饰的静态常量
  4. 局部内部类中还可以包含内部类,但是这些内部类也不能使用访问控制修饰符(public、private 和 protected)和 static 修饰符修饰。
  5. 在局部内部类中可以访问外部类的所有成员。
  6. 在局部内部类中只可以访问当前方法中 final 类型的参数与变量。如果方法中的成员与外部类中的成员同名,则可以使用 OuterClassName.this.MemberName的形式访问外部类中的成员。
  7. java8开始 自动为在局部内部类中被使用的变量添加final修饰符 (隐式最终)

4.3 Java匿名内部类

  • 匿名内部类是指没有类名的内部类,必须在创建时使用 new 语句来声明类
    匿名内部类有两种实现方式:
  1. 继承一个类,重写其方法。
  2. 实现一个接口(可以是多个),实现其方法。

匿名内部类有如下特点:

  1. 匿名类和局部内部类一样,可以访问外部类的所有成员。如果匿名类位于一个方法中,则匿名类只
    能访问方法中 final 类型的局部变量和参数。
  2. 匿名类中允许使用非静态代码块进行成员初始化操作。
  3. 匿名类的非静态代码块会在父类的构造方法之后被执行。

5. 枚举类型

枚举类型相当于特殊的类,经过编译之后同样产生一个class文件。

  • 枚举类型中可以定义方法(包括构造方法)、属性、静态的方法和属性、继承接口、重载覆盖等,类似于class。

枚举类型使用enum关键字 来声明类型,枚举类型的每一个枚举值(枚举属性)都是枚举类型的实例,且都是public static final类型的实例。

5.1 枚举类型的继承:

所有的枚举类型都隐含的继承自java.lang.Enum类,又因为Java是单继承的,所以一个枚举类型不能继承任何其他的类。
枚举类型因为继承了java.lang.Enum类,又因为java.lang.Enum实现了java.lang.Comparablejava.io.Serializable接口,所以枚举类型也默认实现了这两个接口。

5.2 枚举类型的构造方法:

必须是private访问权限不能使public权限

  • 这样就可以保证在枚举类型定义的外部无法使用new来创建枚举值。

使用构造方法(当然是带参数的构造方法)赋值,则必须给所有的枚举值赋值;如果写了构造方法,却没有使用其用于赋值,则会报错。

继承自父类(java.lang.Enum)的方法:

  1. ordinal()方法: 返回枚举值在枚举类种的顺序。这个顺序根据枚举值声明的顺序而定。
  2. compareTo()方法: Enum实现了java.lang.Comparable接口,因此可以比较象与指定对象的顺序。
    Enum中的compareTo返回的是两个枚举值的顺序之差。当然,前提是两个枚举值必须属于同一个枚举类,否则会抛出ClassCastException()异常。
  3. values()方法: 静态方法,返回一个包含全部枚举值的数组。
  4. toString()方法: 返回枚举常量的名称。
  5. valueOf()方法: 这个方法和toString方法是相对应的,返回带指定名称的指定枚举类型的枚举常量。
  6. equals()方法: 比较两个枚举类对象的引用。

2. ❤️Java基础专栏 - 前篇回顾

  • 认识Java,Java程序的生命周期,运行Java程序
  • Java数据类型阐述、基本数据类型的占用和范围、二进制的讲述
  • 8种基本数据类型的分析、数据类型转换规则、转义字符的列举
  • 五种运算符的说明(&&、||、>=、>、<=、<)、4种控制语句(if、for、while、dowhile)、输入和输出说明
  • 方法的概念、方法的调用、方法重载、构造方法的创建
  • 全方面带你了解Java里的日期与时间内容,介绍 Calendar、GregorianCalendar、Date类
  • 正则表达式的使用与常用类分享
  • Stream流、文件File相关操作,IO的含义与运用
  • Java异常捕捉,throws/throw、finally、try、catch关键字的含义与运用

3. 其他好文推荐

  • 还不了解Git分布式版本控制器?本文将带你全面了解并掌握
  • 带你认识Maven的依赖、继承和聚合都是什么!有什么用?
  • 2-3树思想与红黑树的实现与基本原理
  • !全网最全! ElasticSearch8.7 搭配 SpringDataElasticSearch5.1 的使用
  • 全面深入Java GC!!带你完全了解 GC垃圾回收机制!!
  • 全面了解Java的内存模型(JMM)!详细清晰!
  • 在JVM中,类是如何被加载的呢?本篇文章就带你认识类加载的一套流程!
  • 带你了解Go语言的判断语句、切片和映射表!!
  • (Java并发编程—JUC)带你重新认识进程与线程!!让你深层次了解线程运行的睡眠与打断!!

你可能感兴趣的:(java,java,开发语言,Java,SE,内部类,抽象类,interface接口,枚举类)