当你可以灵活的使用抽象类和接口进行设计的时候,那么基本上就表示你面向对象的概念理解了。

接口的基本定义

  • 抽象类与普通类相比最大的优势在于:可以实现对子类覆写方法的控制,但是在抽象类里面可能依然会保留一些普通方法,而普通方法里面可能会涉及到一些安全或者隐私的操作问题,那么这样在进行开发的过程之中,如果要对外部隐藏全部的实现细节,则就可以通过接口进行描述。
  • 接口可以理解为纯粹的抽象类(最原始的定义接口之中只包含有抽象方法与全局常量),但是从JDK1.8开始,由于引入了Lambda表达式的概念,所以接口的定义也得到了加强,除了抽象方法与全局常量之外,还可以定义普通方法或静态方法。如果从设计本身的角度来讲,接口之中的组成还是应该以抽象方法和全局常量为主。
  • 在Java中接口主要使用interface关键字来进行定义。
    范例:定义一个接口
//由于类名称与接口名称相同,所以为了区分出接口,名称前往往会加入I(interface简写)
interface IMessage{	//定义了一个接口
	public static final String INFO = "我是一个常量";//全局常量
	public abstract String getInfo();//抽象方法
}

但是现在很明显的问题出现了,此时的接口肯定无法就直接产生实例化对象。 所以对接口的使用原则如下:

  • 接口需要被子类实现(implements),一个子类可以实现多个接口
  • 子类(如果不是抽象类)那么一定要覆写接口中的抽象方法
  • 接口对象可以利用子类对象的向上转型进行实例化

范例:定义接口子类

//由于类名称与接口名称相同,所以为了区分出接口,名称前往往会加入I(interface简写)
interface IMessage{	//定义了一个接口
	public static final String INFO = "我是一个常量";//全局常量
	public abstract String getInfo();//抽象方法
}

class MessageImpl implements IMessage	//实现了接口
{
	public String getInfo(){
		return "我是接口子类的覆写方法";
	}
}
class JavaDemo
{
	public static void main(String[] args){
		IMessage msg= new MessageImpl();//向上转型
		System.out.println(msg.getInfo());
		System.out.println(IMessage.INFO);	//直接输出全局常量
	}
}

结果:

接口 定义consumes_抽象方法

以上是接口的基本使用,在Java里面之所以使用接口主要的目的是一个子类可以实现多个接口,利用接口可以实现多线程的概念。

范例:观察子类实现多个父接口

//由于类名称与接口名称相同,所以为了区分出接口,名称前往往会加入I(interface简写)
interface IMessage{	//定义了一个接口
	public static final String INFO = "我是一个常量";//全局常量
	public abstract String getInfo();//抽象方法
}
interface IChannel	//通道接口
{
	public abstract boolean connect();//定义抽象方法
}

class MessageImpl implements IMessage,IChannel	//实现了接口
{
	public String getInfo(){
		if(this.connect()){
			return "我是接口子类String的覆写方法";
		}
			return "通道建立失败,消息无法获取";
	}
	public boolean connect(){
		System.out.println("我是一个接口子类boolean的方法覆写,通道创建成功");
		return true;
	}
}

class JavaDemo
{
	public static void main(String[] args){
		IMessage msg= new MessageImpl();
		System.out.println(msg.getInfo());
	}
}

结果:

接口 定义consumes_java_02


但是这个时候就需要考虑一个情况,关于对象的转型问题了。

接口 定义consumes_子类_03

此时MessageImpl子类的对象可以任意的实现父接口的转换。

范例:观察转换

主方法:

class JavaDemo
{
	public static void main(String[] args){
		IMessage msg= new MessageImpl();
		IChannel chl = (IChannel)msg;
		System.out.println(chl.connect());
	}
}

结果:

接口 定义consumes_接口 定义consumes_04

由于MessageImpl子类实现了IMessage与IChannel两个接口,所以这个子类可以是这两个接口任意一个接口的实例,表示此时这两个接口实例之间是可以转换的。

在java程序里面接口是不允许去继承父类的,所以接口绝对不是Object的子类,但是根据之前的分析可以发现, MessageImpl是Object的子类,所以接口一定可以通过Object接收。
范例:观察Object与接口转换
主方法:

class JavaDemo
{
	public static void main(String[] args){
		IMessage msg= new MessageImpl();
		Object obj  = msg;//向上转型
		IChannel chan = (IChannel)obj;
		System.out.println(chan.connect());
	}
}

结果:

接口 定义consumes_子类_05

Object类对象可以接收所有数据类型,包括基本数据类型、类对象、接口对象、数组。

由于接口描述的是一个公共的定义标准,所以在接口之中所有的抽象方法的访问权限都为public,例如下面的两个接口本质是完全相同的:

完整定义:

interface IMessage{
	public static final String INFO = "我是一个常量";
	public abstract String getInfo();
}

简化定义:

interface IMessage{
	 String INFO = "我是一个常量";
	 String getInfo();
}

方法不写访问权限也是public,不是default,所以覆写的时候只能够使用public 。
接口虽然已经成功定义,但是千万不要忽略,在实际的开发过程之中,实现接口的有可能是抽象类,一个抽象类可以实现多个接口,而一个普通类只能够继承一个抽象类并且可以实现多个父接口,但是要求先继承后实现。
范例:子类继承抽象类并且实现接口

//由于类名称与接口名称相同,所以为了区分出接口,名称前往往会加入I(interface简写)
interface IMessage{	//定义了一个接口
	public static final String INFO = "我是一个常量";//全局常量
	public abstract String getInfo();//抽象方法
}
interface IChannel	//通道接口
{
	public abstract boolean connect();//定义抽象方法
}



abstract class DatabaseAbstract {	//定义一个抽象类
	//接口中的abstract可以省略,抽象类中不允许省略 
	public abstract boolean getDatabaseConnection(); 
}


class MessageImpl extends DatabaseAbstract implements IMessage,IChannel	//实现了接口
{
	//覆写接口IMessage的方法           
	public String getInfo(){
		if(this.connect()){
			if(this.getDatabaseConnection()){
				return "数据库中得到消息";
			}else{
				return ",数据库消息无法为访问";
			}
		}
		return "通道建立失败";
	}

	//覆写接口IChannel的方法
	public boolean connect(){
		System.out.println("我是一个接口子类boolean的方法覆写,通道创建成功");
		return true;
	}

	//覆写父类DatabaseAbstract的方法
	public boolean getDatabaseConnection(){
		return true;
	}
}
class JavaDemo
{
	public static void main(String[] args){
		IMessage msg= new MessageImpl();//向上转型
		System.out.println(msg.getInfo());
	}
}

结果:

接口 定义consumes_子类_06

虽然接口无法继承父类,但是一个接口却可以通过extends若干个父接口,此时成为接口的多继承。

范例:实现接口多继承

interface IMessage //定义了一个接口
{
	public abstract String getInfo();
}
interface IChannel
{
	public abstract boolean connect();
}
//extends在类继承上只能继承一个父类,但是接口上可以继承多个
interface  IServeice extends IMessage,IChannel
{
	public abstract String service();
}

class MessafeService implements Iservice{
	//接口的每一个抽象类方法否要覆写,包括父接口继承的父接口的方法
	public String getInfo(){
		return "获取了信息";
	}
	public boolean connect(){
		return true;
	}
	public  String service(){
		return "获取消息服务";
	}
}

class JavaDemo
{
	public static void main(String[] args){
	}
}

在实际开发之中,接口的使用往往有三种形式;

  • 表示标准设置
  • 表示一种操作的能力
  • 暴露远程方法视图,这个一般都在RPC分布式开发中使用