【Java】抽象类、接口、内部类

1、抽象类

如果父类的方法本身不需要实现任何功能,仅仅是为了定义方法签名,目的是让子类去覆写它,那么,可以把父类的方法声明为抽象方法。

如果一个class定义了方法,但没有具体执行代码,这个方法就是抽象方法,抽象方法用abstract修饰。

因为无法执行抽象方法,因此这个类也必须申明为抽象类(abstract class)。

使用abstract修饰的类就是抽象类。我们无法实例化一个抽象类,因为抽象类本身被设计成只能用于被继承,因此,抽象类可以强迫子类实现其定义的抽象方法,否则编译会报错。因此,抽象方法实际上相当于定义了“规范”。

为什么需要抽象类?
抽象方法是空方法体,子类继承抽象类必须要重写抽象方法。那定义一个空方法体不就行了吗?不行的。使用抽象方法而非空方法体,子类就知道它必须要实现该抽象方法,否则编译器会出错。

小结:

  • 通过abstract定义的方法是抽象方法,它只有定义,没有实现。抽象方法定义了子类必须实现的接口规范;

  • 定义了抽象方法的class必须被定义为抽象类,从抽象类继承的子类必须实现抽象方法;

  • 如果不实现抽象方法,则该子类仍是一个抽象类;

  • 面向抽象编程使得调用者只关心抽象方法的定义,不关心子类的具体实现。

2、接口

如果一个抽象类没有字段,所有方法全部都是抽象方法,就可以把该抽象类改写为接口:interface

所谓interface,就是比抽象类还要抽象的纯抽象接口,因为它连字段都不能有(可以有public static final字段)。因为接口定义的所有方法默认都是public abstract的,所以这两个修饰符不需要写出来(写不写效果都一样)。

一个类可以实现多个interface

在接口中,可以定义default方法。实现类可以不必覆写default方法。default方法的目的是,当我们需要给接口新增一个方法时,会涉及到修改全部子类。如果新增的是default方法,那么子类就不必全部修改,只需要在需要覆写的地方去覆写新增方法。

default方法和抽象类的普通方法是有所不同的。因为interface没有字段,default方法无法访问字段,而抽象类的普通方法可以访问实例字段。

使用接口的优点:

  • 代码复用: 同一套代码可以处理多种不同的数据类型。
  • 降低了耦合,提高了灵活性

接口的细节:

  1. 接口中可以定义变量,修饰符public static final,可以写也可以不写。
  2. 一个接口可以继承其他接口,还可以有多个父接口。
  3. 类可以在继承基类的情况下,同时实现一个或多个接口。
  4. 可以用instanceof判断一个对象是否实现了某接口。

需要说明:
以上都是Java8之前的接口特性,Java8和Java9允许在接口中定义静态方法和默认方法

小结:

  • Java的接口(interface)定义了纯抽象规范,一个类可以实现多个接口;

  • 接口也是数据类型,适用于向上转型和向下转型;

  • 接口的所有方法都是抽象方法,接口不能定义实例字段;

  • 接口可以定义default方法(JDK>=1.8)。

3、接口与继承的比较

abstract calssinterface
继承子类只能extends一个abstract calss可以implements多个interface
字段可以定义实例字段不能定义实例字段
抽象方法可以定义抽象方法可以定义抽象方法
非抽象方法可以定义非抽象方法不能定义非抽象方法

联系: 抽象类和接口是配合而非替代关系,他们经常一起使用,接口声明能力,抽象类提供默认实现,实现全部或部分方法,一个接口经常有一个对应的抽象类。(Java编程的逻辑P110)

4、Java中访问修饰符public、private、protect、default范围

自身同包子类不同包子类同包类其他类
private访问访问,不能继承访问,不能继承不能访问不能访问
package/friendly/default访问继承访问,不能继承继承不能访问
protected访问继承继承访问不能访问
public访问继承继承访问访问

5、内部类(Nested class/Inner Class)、静态内部类(Static Nested Class)和匿名类(Anonymous Class)

内部类分为四种:

  • 非静态内部类
  • 静态内部类
  • 匿名类
  • 本地类

非静态内部类(普通内部类Nested class/Inner Class)

class Outer {
    class Inner {
        // 定义了一个Inner Class
    }
}

上述定义的Outer是一个普通类,而Inner是一个Inner Class,它与普通类有个最大的不同,就是Inner Class的实例不能单独存在,必须依附于一个Outer Class的实例。

语法: new 外部类().new 内部类()

Inner Class除了有一个this指向它自己,还隐含地持有一个Outer Class实例,可以用Outer.this访问这个实例。所以,实例化一个Inner Class不能脱离Outer实例。

Inner Class和普通Class相比,除了能引用Outer实例外,还有一个额外的“特权”,就是可以修改Outer Classprivate字段,因为Inner Class的作用域在Outer Class内部,所以能访问Outer Classprivate字段和方法。

静态内部类(Static Nested Class)

与非静态内部类不同,静态内部类的实例化 不需要一个外部类的实例为基础,可以直接实例化

语法:new 外部类.静态内部类()

因为没有一个外部类的实例,所以在静态内部类里面不可以访问外部类的实例属性和方法
除了可以访问外部类的私有静态成员外,静态内部类和普通类没什么大的区别

匿名类(Anonymous Class)

匿名类指的是在声明一个类的同时实例化它,使代码更加简洁精练
通常情况下,要使用一个接口或者抽象类,都必须创建一个子类

有的时候,为了快速使用,直接实例化一个抽象类,并“当场”实现其抽象方法
既然实现了抽象方法,那么就是一个新的类,只是这个类,没有命名。
这样的类,叫做匿名类
匿名类和Inner Class一样,可以访问Outer Classprivate字段和方法。之所以我们要定义匿名类,是因为在这里我们通常不关心类名,比直接定义Inner Class可以少写很多代码。

本地类

本地类可以理解为有名字的匿名类

内部类与匿名类不一样的是,内部类必须声明在成员的位置,即与属性和方法平等的位置。
本地类和匿名类一样,直接声明在代码块里面,可以是主方法,for循环里等等地方

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值