Java接口


java中的接口是类的蓝图。 它有静态常量和抽象方法。java中的接口是一种实现抽象的机制。 接口中只有抽象方法而不是方法体。接口用于在Java中实现抽象和多重继承。Java接口也表示IS-A关系。它不能像抽象类一样被实例化。

q) Java为什么需要接口

  • 通过接口实现多继承
  • 用于实现耦合
    如下图所示,一个类扩展了另一个类,一个接口扩展了另一个接口,一个类实现了一个接口。
    在这里插入图片描述

接口的用法

interface Printer{                                                                //打印机的接口
	void print();                                                        //打印机的打印方法
}

电脑来了

class  Computer implements Printer{                                           //computer连接了Printer的方法
	@override
	public void print(){
		System.out.println("我是电脑");                                        //把msg的方法打印出来
	}
}

手机来了

class SmartPhone implements Printer{                                   //手机连接了打印机
	@override
	public void print(){
		System.out.println("我是智能手机");                           //手机的println()方法
	}
}

Java 8接口特性

Java 8以前的接口只能有抽象方法,不能有方法体
Java 8开始可以有方法体,但是只能是默认的方法体和静态方法

Q)为什么要加这两个特性呢?
A)简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。我们只需在方法名前面加个default关键字即可实现默认方法。该策略可以解决多继承的问题。

default方法可以解决兼容性问题和简单的解决多继承问题

Java8之前
HeadFirst Java 时,作者说,为了解决多重继承所引起的“致命方块问题”
在这里插入图片描述
所以Java不用多重继承,用多重实现,但是在多重实现中,这个问题解决了吗?还没有

interface CanonPrinter{
	void print();
}

interface DeliPrinter{
	void ptint();
}

有一个类两个接口都支持,但是当答打印的时候

class Computer implementsCannonPrinter,DeliPrinter{
	@override
	public void print(){
		System.out.println("This is computer!!!");
	}
	public static void main(String[] args){
		new Computer.print();
	}
}

这个时候会出来个问题,你重写的打印的方法到底是实现了哪个接口的打印方法?
如果CannonPrinter接口和DeliPrinter接口的print()方法相同,那么编译器认为你同时都实现了两个接口的两个方法,并且运行哪个方法都可以,因为两个接口的print()方法都一样。
输出结果

This is computer!!!

如果同名方法只是参数类型不同呢?

interface CanonPrinter{
	void print(StringBuilder msg);
}

interface DeliPrinter{
	void ptint(String msg);
}

class Computer implementsCannonPrinter,DeliPrinter{
	@override
	public void print(String msg){
		System.out.println(msg);
	}

	@override
	public void print(StringBuilder msg){
		System.out.println(new StringBuilder(msg));
	}
	
	public static void main(String[] args){
		new Computer.print("This is Computer!!!");
		new Computer.print(new StringBuilder("This is Computer!!!"))
	}
}

编译器可以准确区分,没有产生歧义,所以输出结果

This is Computer!!!
This is Computer!!!

如果print()方法返回参数不同呢?

interface CanonPrinter{
	String print();
}
interface DeliPrinter{
	StringBuilder ptint();
}

class Computer implementsCannonPrinter,DeliPrinter{
	@override
	public String print(){                             //如果只实现了CanonPrinter 的返回类型为String的print(),
		return "This is computer!!!";               //没有实现DeliPrinter的StringBuilder的print()方法,编译器会报错	                                                                         
	}                                                  //所以只实现一个接口的方法,是违背接口的规则的,不能通过编译。

	@override
	public int  print(){                                     //如果实现了两个方法,编译器则会报错,因为名字重复
		return new StringBuilder("This is computer!!!");  //当对象调用的时候,不知道调用的是哪个方法                                                                         
	}                                                        

	
	public static void main(String[] args){
		new Computer.print();                                      //我调用的是哪个方法呢?
	}
}

如果两个不同的接口各有同名且不同返回类型的方法,如果一个类想同时实现这两个接口,无解,在编译时就会报错,没有办法实现。除非把问题变得复杂,使用内部类。

interface CanonPrinter{
	String print();
}
interface DeliPrinter{
	StringBuilder ptint();
}

class Computer implements CannonPrinter{
	@override
	public String print(){                             
		return "This is computer!!!";               
	}                                                  

	@override
	public int  print(){
		return new StringBuilder("This is computer!!!");  
	}                                                        
	class MultiComputer implements DeliPrinter{
		@override
		public String print(){                            
			return "This is computer!!!"; 
		}                                                  

		@override
		public int  print(){
			return new StringBuilder("This is computer!!!");  
		}
	}
}

但是Java8新特性后

public class Java8Tester {
   public static void main(String args[]){
      Vehicle vehicle = new Car();
      vehicle.print();
   }
}
 
interface Vehicle {
   default void print(){
      System.out.println("我是一辆车!");
   }
    
   static void blowHorn(){
      System.out.println("按喇叭!!!");
   }
}
 
interface FourWheeler {
   default void print(){
      System.out.println("我是一辆四轮车!");
   }
}
 
class Car implements Vehicle, FourWheeler {
   public void print(){
      Vehicle.super.print();
      FourWheeler.super.print();
      Vehicle.blowHorn();
      System.out.println("我是一辆汽车!");
   }
}

输出结果

我是一辆车!
我是一辆四轮车!
按喇叭!!!
我是一辆汽车!

这样你就可以区分使用哪个接口的方法。
同时default方法还可以解决兼容性。
当你在接口中添加一个方法时,需要所有实现它的类都实现它的抽象方法。就会带来不必要的操作,但如果使用默认方法,你只需在接口中添加好方法体,之后在需要实现的类中调用就可以了,减少了不必要的操作。
例如:

interface Printer{
	void print{};
}

实现类

class computer implements Printer{
	@override
	public void print(){
		System.out.print("This is Computer");
	}
}
class SmartPhone implements Printer{
	@override
	public void print(){
		System.out.print("This is smartPhone");
	}
}

如果需要给接口添加一个方法

interface Printer{
	void print{};
	default void println(){
		System.out.println("增加了Println()方法")
	};                                                                                   //新添加的方法
}

实体类需要实现

class Computer implements Printer{
	@override
	public void print(){
		System.out.print("This is Computer");
	}
	@override
	default void prinln(){
		System.out.println("This is println() for Computer");             //这里用,就在这里重写好了,其他实现了Printer的类就不用管了
	}
	
}
class SmartPhone implements Printer{
	@override
	public void print(){
		System.out.print("This is smartPhone");
	}
}

接口中的静态方法可以用做保存常用方法

我们知道常量可以用接口来保存
例如

interface addressCodeConstant{
	String CHINA = "CN";
	String AMERICA = "US";
}

同理常用方法,也就是常用工具方法可以用static来修饰
例如

interface getAddressCode{
	static String returnAdressCod(String country){
		switch (country){
			case CHINA :
				return CN;
			case AMERICA:
				return US;
			default:
				retrun null;
		} 	
	}
}

相当于

public final getAddressCode{
	public String returnAdressCod(String country){
    		switch (country){
    			case CHINA :
    				return CN;
    			case AMERICA:
    				return US;
    			default:
    				retrun null;
    		} 	
    	}
}

只不过以后的常用方法可以存储像常量一样存储在接口中了。

标记接口

没有成员的接口(仅定义一个空的接口)称为标记或标记接口。 例如:可序列化,可克隆,远程等。它们用于向JVM提供一些基本信息,以便JVM可以执行一些有用的操作。

//How Serializable interface is written?  
public interface Serializable{  

}
  • 54
    点赞
  • 193
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值