java中的抽象类和接口以及区别
抽象类:类和类之间有共同特征,将这些具有共同特征的类再进一步抽象就形成了抽象类。
由于类本身是不存在的,所以抽象类无法创建对象。
抽象类和抽象类实际上可能还会有共同特征,还可以进一步再抽象。
抽象类也属于引用数据类型。
定义语法:
[修饰符列表] abstract class 类名{
类体;
}
抽象类是无法实例化的,无法创建对象的,所以抽象类是用来被子类继承的。
final和abstract关键字不能联合使用,这两个关键字是对立的。
抽象类的子类可以是抽象类。
抽象类虽然无法实例化,但是抽象类有构造方法,这个构造方法是供子类使用的。
抽象类关联到一个概念,抽象方法,抽象方法就是没有实现的方法,没有方法体的方法。例如 public abstract void doSome();
抽象类中不一定有抽象方法。但是抽象方法必须出现在抽象类中。
重要结论:
一个非抽象的类继承一个抽象类。必须将抽象类中所有的抽象方法全部实现。
接口的基本语法:
接口是一种引用数据类型。
接口是完全抽象的。(抽象类是半抽象。)或者也可以说接口是特殊的抽象类。
接口的语法(接口在编译后,也是生成.class文件)
[修饰符列表] interface 接口名{}
接口支持多继承,一个接口可以继承多个接口。
接口中只包含两部分内容,一部分是:常量。一部分是:抽象方法。
接口中的所有元素都是public修饰的,都是公开的。
接口中的抽象方法定义时:public abstract修饰符可以省略。
接口中的方法都是抽象方法,所以接口中的方法不能有方法体。
接口中的常量public static final可以省略。
接口中不能有方法体。
一个类可以实现多个接口。
一个非抽象的类实现接口的时候,必须将接口中所有方法加以实现。
抽象类和接口的区别:
接口和接口之前支持多继承。
一个类可以同时实现多个接口。弥补了java中类之间的单重继承。
经过测试:接口和接口之间在进行强制类型转化的时候,没有继承关系,也可以强转。但是运行时可能出现classCastException异常。
一个类可以实现多个接口。
使用接口,可以使用多态(父类型的引用指向子类型的对象)。
public class JK1{ public static void main(String[] args){ Flyable cat = new Cat(); cat.fly(); Flyable pig = new Pig(); pig.fly(); } } class Animal{ } class Cat extends Animal implements Flyable{ public void fly(){ System.out.println("Cat is flying"); } } class Pig extends Animal implements Flyable{ public void fly(){ System.out.println("Pig is flying"); } } interface Flyable{ void fly(); }
接口在开发中的作用:
接口在开发中的作用,类似多态在开发中的作用。
多态:面向抽象编程,不要具体面向具体编程。降低程序的耦合度。提高程序的扩展力。 举个例子:要面向父类编程,父类比子类的更具有抽象性。 要面向抽象编程,不要面向具体编程。如此以来,这样的程序的扩展力就比较强。
接口的使用,会使程序的扩展力很强。更加抽象。接口是一个抽象的概念。
***********
凡是能用is a表示的都可以设置为继承。、
凡是满足has a的表示都以属性的形式存在。(通过这样的方式,来建立两个类之间的关系。
************
接口的使用离不开多态机制。接口加多态才可以达到降低耦合度的效果。
接口可以解耦合。可以实现将调用者和实现者解耦合。
调用者面向接口调用。
实现着面向接口编写实现。
(测试题)
接口练习:
去餐厅吃饭
通过(菜单menu)接口解耦合 顾客(customer)和后厨(cooker)的关系 其中后厨和顾客通过菜单沟通。
思想:通过消费者去调用接口;厨师通过接口去实现。
菜单接口
interface Menu{ void xhsjd(); //抽象方法不能有方法体也就是{}。并且需要以分号结尾。 void yxrs(); }
国厨类
public class ChinaCooker implements Menu{ public ChinaCooker(){} public void xhsjd(){ System.out.println("中国厨子做的西红柿鸡蛋"); } public void yxrs(){ System.out.println("中国厨子做的鱼香肉丝"); } }
外厨类
public class AmericaCooker implements Menu{ public AmericaCooker(){} public void xhsjd(){ System.out.println("美国厨子做的西红柿鸡蛋"); } public void yxrs(){ System.out.println("美股厨子做的鱼香肉丝"); } }
消费者类
public class Custom{ private Menu menu; //此处是一个has a 的关系,所以要用属性的方式表达出来。 public Custom(){} public Custom(Menu menu){ this.menu = menu; } //setter和getter方法(只要封装就养成写set和get的好习惯) public void setMenu(Menu menu){ this.menu = menu; } public Menu getMenu(){ return menu; } public void order(){ //Menu menu = this.getMenu; menu.xhsjd(); menu.yxrs(); } }
测试类
public class InterfaceTest{ public static void main(String[] args){ //欲先调用 //先得生成 Menu cooker1 = new ChinaCooker(); Custom custom = new Custom(cooker1); custom.order(); } }
//本接口练习题的总结:通过定义接口实现解耦合消费者类和厨师类;接口多态的体现:通过接口指向厨师的实现(父类型的引用指向子类型的对象)。在消费者类中,将菜单作为成员属性,将消费者和厨师建立关系。在此方法中使用接口
//通过利用多态,面向抽象编程,遵循OCP原则。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?