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{
}