接口
接口:接口是对行为的抽象。
在java中,接口不提供具体的实现,它仅仅是描述了某些事物的共同具有的功能的抽象,并非具体实现。
例如:人和猫都是生物,都需要进食和休息,那么就可以描述一个名为生物的接口,将进食和休息的行为抽象的描绘出来,再由人和猫分别实现生物这个接口,根据他们特有的进食和休息方式,去实现这个抽象行为的具体细节。
接口的特征(jdk8以前)
1.接口中所有方法不能有具体实现,即所有方法都必须为抽象方法,不能有方法体,方法修饰默认为public abstract(可省略);
2.接口中不能定义实例变量,非抽象实例方法,静态方法(jdk8以前);
3.接口没有构造方法,也不能被实例化;
4.接口中声明的成员变量都是public static final修饰的,必须显式的初始化;
5.接口中不能实现接口,但是可以多继承;
6.接口需要通过子类来实现他的抽象方法;
接口:
public interface InterfaceDIY {
public static final int a = 1234;//全局变量:默认为public static final修饰的变量
int fun();//方法默认为public abstract修饰
//接口中的方法不能有方法体(jdk8以前,可认为接口所有方法都是抽象方法)
}
实现类:
public class test extends AbstractDIY implements InterfaceDIY {
@Override
public int fun() {
return 0;
}
}
7.如果一个类无法实现接口中的所有方法,这个类该设计为抽象类,即并非所有类都必须实现接口所有方法(抽象类)。
public abstract class AbstractDIY implements InterfaceDIY {
//抽象类并非必须实现fun方法
}
8.不允许创建接口的实例,但是可以定义接口类型的引用变量,引用实现该接口类的实例。
public static void main(String[] args) {
InterfaceDIY interfaceDIY=new InterfaceDIY() {
@Override
public int fun() {
return 0;
}
};
interfaceDIY.fun();
}
9.接口中的方法发生改变,其子类也需进行相对的改变(jdk8以前)
在接口中添加print方法。
public interface InterfaceDIY {
public static final int a = 1234;//全局变量:默认为public static final修饰的变量
//jdk8以前
int fun();//方法默认为public abstract修饰
//接口中的方法不能有方法体
int print();//新添加了print方法
}
实现类需要再次实现print方法,否则编译异常。
public class test implements InterfaceDIY {
@Override
public int fun() {
return 0;
}
@Override
public int print() {
return 0;
}
}
接口在jdk8中的新特性
jdk8后接口可使用默认方法和静态方法。
jdk8新特性参考:https://mp.weixin.qq.com/s?src=11×tamp=1604888589&ver=2695&signature=sSjp1ZoOE-uy9-TpZFGn4Ol6hyAbw9cUUPAwgy0kfd7hsSRpKILZ5iRPKNGuZUpjYVXY8bSC3K4Lyi7qcTvF-2c3iDg7a2lLlJyP4dsQLC8oO9HZaFRyAYIqExje3h&new=1
1.默认方法(default)
默认方法使得开发者可以在 不破坏二进制兼容性的前提下,往现存接口中添加新的方法,即不强制那些实现了该接口的类也同时实现这个新加的方法。
接口:添加了默认方法deffun()
public interface InterfaceDIY {
public static final int a = 1234;//全局变量:默认为public static final修饰的变量
//jdk8以前
int fun();//方法默认为public abstract修饰
//接口中的方法不能有方法体
public static void main(String[] args) {
}
default void deffun() {//默认方法
System.out.println("def");
}
}
实现类:创建接口引用可直接调用
InterfaceDIY interfaceDIY=new InterfaceDIY() {
@Override
public int fun() {
return 0;
}
};
interfaceDIY.deffun();
默认方法和抽象方法之间的区别在于抽象方法需要实现,而默认方法不需要。接口提供的默认方法会被接口的实现类继承或者覆写。
尽管默认方法有这么多好处,但在实际开发中应该谨慎使用:在复杂的继承体系中,默认方法可能引起歧义和编译错误。
情景题:若是实现类实现了两个接口,两个接口同时实现了一个默认方法,实现类如何分辨需要实现哪个接口下的默认方法?
答:这种情况下,编译系统会要求实现类覆盖这个默认方法,对该默认方法进行重写。
另一个接口:定义一个与第一个接口相同的方法deffun()
public interface InterfaceDIY1 {
default void deffun() {
System.out.println("def1");
}
}
实现类:重写该默认方法
public class test implements InterfaceDIY,InterfaceDIY1 {
@Override
public int fun() {
return 0;
}
@Override
public void deffun() {
System.out.println("childdef");
}
}
2.静态方法
直接用接口调用这些静态方法
public static void main(String[] args) {
InterfaceDIY.stafun();
}
jdk8中,接口中可定义main()方法,并编译运行
public interface InterfaceDIY {
public static final int a = 1234;//全局变量:默认为public static final修饰的变量
//jdk8以前
int fun();//方法默认为public abstract修饰
//接口中的方法不能有方法体
public static void main(String[] args) {
System.out.println("运行main方法");
}
default void deffun(){
System.out.println("def");
}
static void stafun(){
System.out.println("sta");
}
}
运行结果如下:
使用接口的原因
1.接口被用来描述一种抽象;
2.接口可用来实现解耦;
3.Java通过实现接口来实现多继承;
4.抽象类内部可能包含非final的变量,但是在接口中存在的变量一定是final,public,static的。
抽象类
抽象类可以理解为:没有足够的信息描绘一个完整的对象而存在的类。
抽象类的特征
1.抽象类不能直接实例化为具体对象,必须通过其他类继承才能使用,或者使用子类进行向上转型实现抽象类的实例化;
2.一个类只能继承一个抽象类,通过在类名后加extends继承;
3.抽象类的修饰符不能是private和final;
4.抽象类不一定有抽象方法,但是有抽象方法的类一定是抽象类(和接口);
5.抽象类可以有构造方法,但是不能直接实例化为对象,构造方法可以用来初始化抽象类内部声明的通用变量,抽象类的子类隐含父类的构造方法;
public abstract class AbstractDIY {
AbstractDIY() {
}
}
6.抽象类的子类需给出抽象类中抽象方法的具体实现,除非该子类也是抽象类。
抽象类:内含抽象方法abs()
public abstract class AbstractDIY {
AbstractDIY() {
}
abstract void abs();
}
实现类:若是抽象类,则非必须实现抽象方法
public class test extends AbstractDIY{
@Override
void abs() {
System.out.println("抽象方法");
}
}
7.外部类抽象类不允许使用static修饰,内部类抽象类可以。
public abstract class AbstractDIY {
AbstractDIY() {
}
static abstract class AbStractInside {
}
abstract void abs();
}
接口与抽象类的区别(jdk8以前)
- 方法实现:抽象类可以有方法的具体实现,而接口只有抽象方法,不能有具体实现;
- 子类继承方面:实现抽象类使用extends关键字来继承抽象类,实现接口使用的是implements;
3.继承: 一个类只能继承一个抽象类,但一个类却可以实现多个接口; - 构造方法:抽象类可以有构造器,接口不可以有构造器;
- 方法修饰符:接口方法默认修饰符是public,而抽象方法可以使用public、protected和default等
- 增加新方法对子类的影响:抽象类添加默认方法无需修改子类,接口只能添加抽象方法,所以子类也需要进行改变;
- 静态修饰符:接口不能含有静态代码块和静态方法,抽象类可以;
- 成员变量:抽象类的成员变量可以是各种类型,而接口的成员变量只能是由public static final修饰的;
- main方法:抽象类可以有main方法,而且可以运行,但是接口不能定义main方法(因为不能有静态方法)。