抽象类和接口
概念:类和类之间有共同的特征,将这些共同特征的类再进一步抽象形成了抽象类
注解:由于类本身是不存在的,所以抽象类无法创建对象(无法实例化),抽象类和抽象类实际上可能还会有共同特征还可以进一步再抽象,抽象类也属于引用数据类型
抽象类的定义
语法:[修饰列表符] abstract class 类名{类体}
抽象方法的定义
public abstract void 方法名();
抽象方法特点:
没有方法体,以分好结尾,前面的修饰符列表中有abstract关键字
注意:
-
抽象类是无法实例化的,无法创建对象的,所以抽象类是用来被子类继承的
-
final和abstract不能联合使用,这两个关键字是对立的
-
抽象类的子类可以是抽象类。也可以是非抽象类。
-
抽象类虽然无法实例化,但是抽象类有构造方法,这个构造方法是供子类使用的
-
抽象类中不一定有抽象方法,抽象方法必须出现在抽象类中
-
一个非抽象的类,继承抽象类,必须将抽象类中的抽象方法进行覆盖/重写/实现。
注意:java语言中凡是没有方法体的方法不一定都是抽象方法
例如:Object类中就有很多方法都没有方法体,都是以“;”结尾的,但他们都不是抽象方法。
例如:public native int hashCode();
这个方法底层调用了C++写的动态链接库程序
前面修饰符列表中没有:abstract。有一个native。表示调用JVM本地
接口的定义:[修饰符列表] interface 接口名{}
接口特点:
-
接口是完全抽象的
-
接口支持多继承(不支持实现,接口不能实现接口,只能继承)
-
接口中只有常量+抽象方法(JDK1.8之后接口里面可以有默认方法(default修饰的)和静态方法)
-
接口中所有的元素都是public修饰的
-
接口中抽象方法的public abstract可以省略
-
接口中常量的public static final可以省略
-
接口中方法不能有方法体(都是抽象方法)
-
一个非抽象的类,实现接口的时候,必须将接口中所有方法加以实现
-
一个类可以实现多个接口。类似多继承(这种机制(java中的接口)弥补了单继承的带来的缺陷)
-
extends和implements可以共存,extends在前,implements在后(一个类先继承父类再实现接口)
-
一个类实现了多个接口,多个接口中有同名的抽象方法时,子类只会实现一个抽象方法
使用接口,写代码的时候,可以使用多态(父类型引用指向子类型对象)(面向接口编程)
例子:
1 public interface MyAnimal{ 2 void eat();//public abstract 接口会默认加上 3 } 4 5 public class CatImpl implements MyAnimal{ 6 public void eat(){ 7 8 } 9 } 10 public class Test{ 11 public static void main(String[] args){ 12 MyAnimal my = new CatImpl();//这是可以的 13 my.eat(); 14 } 15 }
注意:接口和接口之间在进行强制类型转换的时候,没有继承关系,也可以强转,编译没问题,但是要注意,运行的时候可能会出现ClassCastException异常
例子:
1 public interface A{} 2 public interface B{} 3 public class C implements A{} 4 public class Test{ 5 public static void main(String[] args){ 6 A a = new C(); 7 B b = (B)a;//编译没问题,运行有问题 8 //所以先判断 9 if(a instanceof B){ 10 B b = (B)a; 11 } 12 } 13 } 14 public interface D{ 15 void a1(); 16 } 17 public interface E(){ 18 void a2(); 19 } 20 public interface F(){ 21 void a3(); 22 } 23 public class G implements D,E,F{ 24 public void a(){} 25 public void b(){} 26 public void c(){} 27 } 28 public class Test(){ 29 public static void main(String[] args){ 30 D d = new G(); 31 E e = new G(); 32 F f = new G(); 33 34 //这个编译没问题,运行也没问题 35 E e1 = (E)d;//想调用其他接口中的方法,需要转型(接口转型) 36 e1.a2();//调a2()方法 37 //也可以一步到位转成G 38 G g = (G)d; 39 g.a2(); 40 g.a3(); 41 } 42 }
注解:接口中的静态方法的使用:不能通过接口实现类的对象来调用接口当中的静态方法,通过接口名称直接调用其中的静态方法。
接口在开发中的作用:
类似于多态在开发中的作用 面向接口编程
多态:面向抽象编程,不要面向具体编程。降低程序的耦合度。提高程序的扩展力
接口在开发中的作用,一句话:三个字"解耦合"
接口可以解耦合,解开的是谁和谁的耦合?
任何一个接口都有调用者和实现者,接口可以将调用者和实现者解耦合,调用者面向接口调用,实现者面向接口编写实现。
面向接口编程,可以降低程序的耦合度,提高程序的扩展力。符合OCP开发原则。
接口的使用离不开多态机制。(接口+多态才可以达到降低耦合度。)
类和类之间的关系
三个术语
描述 | 关系 |
---|---|
is a | 继承关系 |
has a | 关联关系 |
like a | 实现关系 |
is a:
1 //Cat is a Animal(猫是一个动物) 2 //凡是能够满足is a的表示“继承关系” 3 public class Cat extends Animal{}
has a
1 //I has a Address(我有一个地址) 2 //凡是能够满足has a关系的表示“关联关系” 3 public class User{ 4 Address address; 5 }
like a:
1 //Cooker like a FoodMenu(厨师像一个菜单一样)((想象你雇佣了一个私人厨师,想吃什么给他说,他就是一个移动菜单)) 2 //凡是能够满足like a关系的表示“实现关系” 3 //凡是能够满足like a关系的表示“实现关系” 4 public class Cooker implements FoodMenu{}
抽象类和接口有什么区别?
区别 | 抽象类 | 接口 |
---|---|---|
抽象类是半抽象的 | 接口是完全抽象的 | |
抽象类中有构造方法 | 接口中没有构造方法 | |
类和类之间只能单继承 | 接口和接口之间支持多继承 | |
一个抽象类只能继承一个类(单继承) | 一个类可以同时实现多个接口 | |