在Java中,一个没有方法体的方法应该定义为抽象方法,而如果一个类中含有抽象方法,则该类必须定义为一个抽象类。接口是功能的集合,同样可看做是一种特殊的数据类型,是比抽象类更为抽象的类,接口只描述所应该具备的方法,并没有具体实现,具体的实现由接口的实现类(相当于接口的子类)来完成。这样将功能的定义与实现分离,优化了程序设计
~
本篇主要记录内容包括:抽象类、接口、抽象类和接口的差异、接口的新特性——默认方法和静态方法、 标记接口等相关内容
在Java中,一个没有方法体的方法应该定义为抽象方法,而如果一个类中含有抽象方法,则该类必须定义为一个抽象类
抽象类通常作为一个框架,把子类将实现的抽象方法组织起来,简化或限制子类的设计
抽象方法定义的格式:public abstract 返回值类型 方法名(参数);
抽象类定义的格式:abstract class 类名 {}
abstract
修饰。抽象方法一定要定义在抽象类中;static、final、private
不能与 abstract
同时出现;static
修饰的方法),不能声明为抽象方法;接口是功能的集合,同样可看做是一种特殊的数据类型,是比抽象类更为抽象的类,接口只描述所应该具备的方法,并没有具体实现,具体的实现由接口的实现类(相当于接口的子类)来完成。这样将功能的定义与实现分离,优化了程序设计
接口的声明:使用interface
代替了原来的class
其他步骤与定义类相同
接口的实现类:使用implements
关键字实现接口,当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象类
接口中方法的修饰符:public abstract(默认不写)
public static final
(默认不写,也可以选择性写)所以接口中的变量也称之为常量,其值不能改变;public abstract
(默认不写,也可以选择性写),不能指定其它的访问控制修饰符;public abstract 返回值类型 方法名字(参数列表)
;Override
),但没有实际的意义,因为接口中不提供方法的实现;public static final
类型的static
修饰的方法),而抽象类是可以有静态代码块和静态方法;总的来说,优先选用接口,尽量少用抽象类,需要定义子类的行为,又要为子类提供共性功能时才选用抽象类
default
关键字,只能通过接口实现类的对象来调用;public
interface Test{
//这个是默认方法
default String get(String aa){
System.out.println("我是jdk1.8默认实现方法...");
return "";
}
//这个是静态方法
static void staticmethod(){
System.out.println("我是静态方法");
}
}
default
默认方法关键字只能用在接口中;Java中的标记接口(Marker Interface),又称标签接口(Tag Interface),是没有任何方法和属性的接口,它不对实现它的类有任何语义上的要求,它仅仅表明实现它的类属于一个特定的类型
在Java中很容易找到标记接口的例子,比如JDK中
的Serialzable
接口就是一个标记接口
标记接口并不是Java语言独有的,而是计算机科学中的一种通用的设计理念。
The tag/marker interface pattern is a design pattern in computer science, used with languages that provide run-time type information about objects. It provides a means to associate metadata with a class where the language does not have explicit support for such metadata.
具体说的就是,标记接口是计算机科学中的一种设计思路,用于给那些面向对象的编程语言描述对象。因为编程语言本身并不支持为类维护元数据,而标记接口可以用作描述类的元数据,弥补了这个功能上的缺失。对于实现了标记接口的类,我们就可以在运行时通过反射机制去获取元数据。
以Serializable
接口为例,如果一个类实现了这个接口,则表示这个类可以被序列化。因此,我们实际上是通过了Serializable
这个接口给该类标记了【可被序列化】的元数据,打上了【可被序列化】的标签。这也是标记/标签接口名字的由来。
具体在Java中,标记接口主要有以下两种目的:
EventListener
接口,一个由几十个其它接口扩展的Java API,当一个接口继承了EventListener
接口,Java虚拟机(JVM)就知道该接口将要被用于一个事件的代理方案。同样的,你可以使用一个标记接口来建立一组接口的父接口。
java.awt.event
包中的MouseListener
接口继承的java.util.EventListener
接口定义如下:package java.util; public interface EventListener {}
- 1
- 2
Java源码中几个标记接口的优秀例子:
java.io.Serializable
:未实现此接口的类将无法使其任何状态序列化或反序列化。为保证serialVersionUID
值跨不同Java编译器实现的一致性,序列化类必须声明一个明确的 serialVersionUID
值。java.lang.Cloneable
:表明Object.clone()
方法可以合法地对该类实例进行按字段复制。实现此接口的类应该使用公共方法重写Object.clone
(它是受保护的)。如果在没有实现 Cloneable接口的实例上调用Object的clone()方法,则会导致抛出CloneNotSupportedException
异常。java.util.RandomAccess
:用来表明其支持快速(通常是固定时间)随机访问。此接口的主要目的是允许一般的算法更改其行为,从而在将其应用到随机或连续访问列表时能提供良好的性能。java.rmi.Remote:Remote
接口用于标识其方法可以从非本地虚拟机上调用的接口。任何远程对象都必须直接或间接实现此接口。只有在远程接口(扩展java.rmi.Remote
的接口)中指定的这些方法才可远程使用。