定义接口使用的是接口是interface
接口型引用:如果接口的子类实现了接口中的所有的功能,那么这个子类就可以被实例化,
子类就符合这个规则,所以接口型引用指向的都是自己的子类对象(多态)。
对于接口中常见的成员,而且这些成员都有固定的修饰符(不写帮你加):
1、全局常量:public static final(不定义为常量的话会被接口所实现的类到处修改,且接口名可以直接调用)
2、抽象方法:public abstract
接口的特点:
1、接口是对外暴露的规则
2、接口是程序的功能扩展
3、接口的出现降低了耦合性
4、接口是对方法的抽象
接口与抽象类的区别:
相同点:都是不断向上抽取而来
不同点:
1、抽象类需要被继承且只能单继承,接口需要被实现且可以多实现
2、抽象类中可以定义抽象方法和非抽象方法,子类继承后可以直接使用非抽象方法
接口中只能定义抽象方法,必须由子类实现
3、抽象类的继承是is a关系,在定义该体系的基本共性内容
接口实现是like a关系,在定义体系额外功能
接口中的成员都是公共的权限
只能由实现了接口的子类并覆盖了接口中所有的抽象方法后,该子类才可以实例化。否则,这个子类就是一个抽象类。
在JAVA中不直接支持多继承,因为会出现调用的不确定性,所以在JAVA中变成了多实现。
一个类可以实现多个接口。
接口的好处可以体现在下图中:
接口A和接口B中有相同的方法,但是接口是抽象方法,需要实现,因此Test这个实现类可以把两个接口中的方法都覆盖掉,从而解决冲突。
一个类在继承另一个类的同时,还可以实现多个接口
接口与接口之间是继承关系,而且接口可以多继承!!!!!!!!
Java8对接口的更新:
在Java8中对接口进行了两类更新:1、接口中可以添加静态方法 2、接口中可以添加默认实现
1、静态方法:
在以前的类库中,经常会看到成对出现的接口和工具类(Collection/Collections、Path/Paths)通常是把静态方法放在工具类中。但在Java8中,可以将Paths.get()这一静态方法直接定义在Path接口中,这样Paths就不是必须的了:
public interface Path
{
public static Path get(String first, String...more) {
return FileSystems.getDefault().getPath(first, more)
}
}
2、默认方法:
1)使用
可以在接口中添加方法的一个默认实现(需要用default修饰)。例如在Java8中MouseListener可以改写为如下:
public interface MouseListener
{
default void mouseClicked(MouseEvent e) {}
default void mousePressed(MouseEvent e) {}
default void mouseReleased(MouseEvent e) {}
default void mouseEntered(MouseEvent e) {}
default void mouseExcited(MouseEvent e) {}
}
这样以来不再需要MouseAdapter适配器来先覆盖接口再拿匿名内部类来实现(接口必须实现全部方法,适配器抽象类需要用空方法实现接口全部方法),只需要覆盖相应监听器方法即可(default已经使用空方法实现)。
此外,默认方法可以调用其他任何方法(包括没有实现的!):
public interface Collection
{
int size(); // abstract method!
default boolean isEmpty() {
return size() == 0;
}
}
这样无须担心isEmpty()的问题。
2)解决冲突
冲突解决遵循一下两项原则:
1、父类优先:如果同时继承一个父类和一个接口,若父类提供了一个具体方法,同名而且有相同参数类型的默认方法会被忽略。
2、接口冲突 :如果Person和Named两个接口提供了不一致的getName()方法,则Java会报告错误让程序员解决这个二义性问题(Person.super.getName()或Named.super.getName())。只要有一个接口提供了默认实现,编译器就会报错。
interface Named
{
default String getName() {return "N";}
}
interface Person
{
default String getName() { return "P"; }
}
public class Student implements Person, Named
{
public String getName() { return Person.super.getName(); } // 注意此处指定方法的写法!
public static void main(String[] args) {
System.out.println(new Student().getName()); // 结果为
}
}
注:不可让一个默认方法重新定义Object类中的某个方法(不能将equals()和toString()定义为默认方法),因为父类优先原则,这样的方法无法超越Object.equals()和Object.toString()!