JDK8以前:
1.接口的基本概念
接口定义:接口就是全局常量和抽象方法的结合,在Java中使用interface定义。接口的命名一般以I开头。
子类实现接口,必须使用implements关键字来实现接口。子类命名一般以Impl结尾。
与类不同的是,一个子类可以实现多个接口,如果子类不是抽象类,那么子类必须覆写接口的全部方法。
实现接口:
interface IMessage{
public static final String MSG = "HELLO";//全局变量
public abstract void print();//抽象方法
}
interface INews{
public abstract String getNew();
}
class MessageImpl implements IMessage,INews{
public void print(){
System.out.println(MSG);
}
public String getNew(){
return IMessage.MSG;
}
}
public class Ex1(){
public static void main(String args[]){
IMessage msg = new MessageImpl();
msg.print();//只能使用IMessage定义的方法
//父接口的相互转换,和向下转型有点像,先找一个公共子类,建立联系
//同 INews news = new MessageImpl();
INews news = (INews)msg;
news.getNew();
}
}
如图:
实现接口与抽象类:
interface IMessage {
//public static final String MSG = "hello";
String MSG = "hello";// static final 在接口中这些修饰符之所以可以不写
void play();
}
abstract class News{
public abstract void getMsg();
}
class MessageImpl extends News implements IMessage{
public void play(){
System.out.println("lalala");
}
@Override
public void getMsg() {
System.out.println(MSG);
}
}
public class Ex2 {
public static void main(String[] args) {
IMessage msg = new MessageImpl();
msg.play();
News news = (News)msg; //News news = new MessageImpl();
//可以理解为News news = new MessageImpl();
news.getMsg();
}
}
接口之间可以相互继承:
interface A{
void playA();
}
interface B{
void playB();
}
interface C extends A,B{
void playC();
}
class Cimpl implents C{
public void playA(){
System.out.println("A");
public void playB(){
System.out.println("B");
public void playC(){
System.out.println("C");
}
}
public class Ex3 {
public static void main(String[] args) {
C c = new CImpl();
c.playA();
c.playB();
c.playC();
}
}
2.接口的使用限制:
- 接口中只允许public权限。(不管是属性还是方法,其权限都是public)
- 在接口中public、static、final、abstract均可省略不写。
阿里编码规约:接口中的方法和属性不要加任何修饰符号,public也不要加,保持代码的简洁性。 - 当一个子类需要实现接口与抽象类时,先用extends继承一个抽象类,再用implements继承多个接口。
- 一个抽象类可以用implements实现多个接口,但是接口不能继承抽象类。
interface IMessage{
void print();
}
abstract class News implements IMessage{
public void getNews();
}
class MessageImpl extends News{
public void print(){
System.out.print("IMessage");
}
public void getNews(){
System.out.println("News");
}
}
public class Ex4{
public static void main(String args[]){
// MessageImpl是抽象类和子类的共同子类
IMessage m = new MessageImpl();
m.print;
News news = (News)m;
news.getNews();
}
}
JDK8以后:
早期版本的接口已经有很多子类实现了,后来发现接口中的方法需要改动甚至新增方法,但由于接口是由全局常量+静态方法组成,无法修改,所以将接口作了扩充:
-
支持default定义的普通方法,通过子类调用,并且所有子类均拥有此方法。
-
static定义的静态方法,通过接口名称直接调用。
/*
JDK1.8以后接口的新特性
*/
interface ISubject{
void test();
//此处default表示接口中的普通方法
default void fun(){
System.out.println("接口中的普通方法,通过子类对象调用");
}
//看到static就知与对象无关
static void fun1(){
System.out.println("可以通过接口直接调用");
}
}
class SubjectImpl implements ISubject{
@Override
public void test() {
System.out.println("接口中的抽象方法");
}
}
public class Test1 {
public static void main(String[] args) {
ISubject subject = new SubjectImpl();//通过子类向上转型
subject.test();
subject.fun();
ISubject.fun1();
}
}
整体来讲,接口感觉更像抽象类了,但是比抽象类更强大的在于:接口的子类依然可以实现多继承的关系,而抽象类依然保持单继承。
因为时间一长,许多的支持就会出现问题(量大的问题),这个时候为了解决这种扩充的问题,才追加了此类支持。但是此操作不属于标准设计,属于挽救设计。