目录
抽象类-Abstract Class
抽象类特点
代码示例
接口-Interface
接口的特点
代码示例
接口与抽象类的区别总结
语法上的区别
语义上的区别
代码示例
执行结果
在初中级程序员面试中这是一道很常见的面试题,这题不难但是要想有亮点还是有一定的难度。
接口和抽象类都提供了一个将接口和实现分离的结构化的方法
在Java中被abstract关键字修饰的类称为抽象类,被abstract关键字修饰的方法称为抽象方法,抽象方法只有方法的声明,没有方法体。下面是抽象方法的语法:
abstract void method();
如果一个类包含一个或多个抽象方法则这个类必须限定为抽象类,反过来一个抽象类中不一定包含抽象方法。
1、抽象类不能被实例化,即不能使用new关键字来实例化对象,只能被继承;
2、包含抽象方法的一定是抽象类,但是抽象类不一定含有抽象方法;
3、抽象类中的抽象方法的修饰符只能为public或者protected,默认为public;
4、抽象类中的抽象方法只有方法体,没有具体实现;
5、如果一个子类实现了父类(抽象类)的所有抽象方法,那么该子类可以不必是抽象类,否则就是抽象类;
6、抽象类可以包含属性、方法、构造方法,但是构造方法不能用于实例化,主要用途是被子类调用。
动物都有名字,叫声以及叫;动物在叫时,输出 xxx 的叫声是:xxx;
这样我们就可以抽象一个动物类,并定一个一个模版方法speak和一个抽象方法 getCry();让不同的动物去实现这个叫声。
/**
* 抽象动物类,
* 动物都有名字
* 动物都会叫
*/
public abstract class AbstractAnimal {
private String name;
/**
* 不同的动物叫声不同,定义一个抽象方法将叫声的实现由子类实现
*
* @return
*/
public abstract String getCry();
/**
* 动物都会叫,这是一个模版,不管什么动物的叫声输出都是一样的
*/
public void speak() {
System.out.println(name + "的叫声是:" + getCry());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public class Dog extends AbstractAnimal {
public Dog(String name) {
super(name);
}
@Override
public String getCry() {
return "汪汪";
}
}
public class Cat extends AbstractAnimal{
public Cat(String name) {
super(name);
}
@Override
public String getCry() {
return "喵喵";
}
}
Java中接口使用interface关键字修饰就是接口,它是一个完全“抽象方法”的集合
1、接口可以包含变量、方法;变量被隐士指定为public static final,方法被隐式指定为public abstract(JDK1.8之前);
2、接口支持多继承,即一个接口可以extends多个接口,间接的解决了Java中类的单继承问题;
3、一个类可以实现多个接口;
4、JDK1.8中对接口增加了新的特性:
4.1、默认方法(default method):JDK 1.8允许给接口添加非抽象的方法实现,但必须使用default关键字修饰;定义了default的方法可以不被实现子类所实现,但只能被实现子类的对象调用;如果子类实现了多个接口,并且这些接口包含一样的默认方法,则子类必须重写默认方法;
4.2、静态方法(static method):JDK 1.8中允许使用static关键字修饰一个方法,并提供实现,称为接口静态方法。接口静态方法只能通过接口调用(接口名.静态方法名)。
public interface Flyable {
String A = "常量1";
String B = "常量2";
public static final String C = "常量3";
void fly();
default String getTest() {
return "test";
}
static void staticMethod(){
System.out.println("接口中静态方法");
}
}
抽象类 | 接口 | |
实例化 | 不可以 | 不可以 |
构造器 | 支持 | 不支持 |
方法实现 | 抽象类可以有抽象方法也可以有具体方法实现 有抽象方法的类一定是抽象类,但是抽象类不一定是抽象类 |
在JDK1.8之前接口不支持具体方法实现,从1.8开始支持默认方法和静态方法 |
访问修饰符 | 抽象类可以是public, protected,default | 接口只能是public |
成员变量 | 抽象类支持普通成员变量 | 接口中的成员变量都是常量,即使没有使用 public static final 修饰也会被隐式的声明为常量 |
继承 | 抽象类只支持单继承 | 接口可以继承多个接口 |
main方法 | 抽象类可以有main 方法,可以允许 | 接口不可以 |
新增方法 | 抽象类新增方法必须有实现,这样可以向下兼容 | JDK1.8之前接口新增方法不支持向下兼容,自1.8开始新增默认方法则可以向下兼容 |
这道面试题的重点在这里,主要考察的面试者的架构设计能力。
第一点:抽象类是is-a的关系,接口是has-a的关系。我们具体举个例子来说明这个问题,有一个独角兽,我们可以抽象出一个抽象类 Animal ,我们可以说独角兽是动物;我们还可以抽象一个Flyable,因为独角兽具有飞行能力。我们是不会可以将Animal 定义为接口呢?如果设计为接口,那么可以说独角兽有动物能力吗?这样就很难理解和沟通。
第二点:从设计模式角度来讲抽象类是模版方法模式,接口是一个约束范式。
上文说了这些区别点,是不是真的是这样呢,下面我们通过一段demo来看一下
public class InterfaceAndAbstract {
public static class Dog extends AbstractAnimal {
public Dog(String name) {
super(name);
}
@Override
public String getCry() {
return "汪汪";
}
}
public static class Cat extends AbstractAnimal {
public Cat(String name) {
super(name);
}
@Override
public String getCry() {
return "喵喵";
}
}
public static class Unicorn extends AbstractAnimal implements Flyable {
public Unicorn(String name) {
super(name);
}
@Override
public String getCry() {
return "灰吕吕";
}
@Override
public void fly() {
System.out.println(getName() + " 飞起来了");
}
}
/**
* 抽象动物类,
* 动物都有名字
* 动物都会叫
*/
public static abstract class AbstractAnimal {
private String name;
public AbstractAnimal(String name) {
this.name = name;
}
/**
* 不同的动物叫声不同,定义一个抽象方法将叫声的实现由子类实现
*
* @return
*/
public abstract String getCry();
/**
* 动物都会叫
*/
public void speak() {
System.out.println(name + "的叫声是:" + getCry());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 抽象类可以有main方法
*
* @param args
*/
public static void main(String[] args) {
Unicorn unicorn = new Unicorn("独角兽");
unicorn.speak();
Dog dog = new Dog("小狗");
dog.speak();
unicorn.fly();
//只能通过接口调用静态方法
Flyable.staticMethod();
}
}
/**
* 能够f
*/
public interface Flyable {
String A = "常量1";
String B = "常量2";
public static final String C = "常量3";
void fly();
default String getTest() {
return "test";
}
static void staticMethod() {
System.out.println("接口中静态方法");
}
}
}
独角兽的叫声是:灰吕吕
小狗的叫声是:汪汪
独角兽 飞起来了
接口中静态方法