Java-抽象类和接口
知识点1-抽象的概念与定义
-
抽象类的概念: 如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类
-
抽象类必须用abstract关键字来修饰。
-
抽象方法的概念: 没有功能主体的方法称为抽象方法
-
抽象方法必须用abstract关键字来修饰,只有方法声明,没有方法体,且必须定义在抽象类中。
知识点2-抽象类的特点
-
抽象类不可以被实例化,也就是不可以用new创建对象 ,但有构造方法。
-
抽象类通过其子类实例化,而子类需要覆盖(重写)掉抽象类中所有的抽象方法后才可以创建对象,否则该子类也是抽象类。
-
方法只有声明没有实现时,该方法就是抽象方法,需要用abstract来修饰,抽象方法必须定义在抽象类中,该类也必须被abstract来修饰。
-
用abstract修饰的类就是抽象类。抽象方法必须定义在抽象类中。但是抽象类中不一定有抽象方法。
-
抽象类可以有成员属性和非抽象的成员方法。
-
抽象类可以没有抽象方法。
-
抽象类可以继承普通类与抽象类。
-
抽象类不能直接使用类名创建实例,但是有构造方法,构造方法是让子类进行初始化。
-
abstract与其他修饰符的关系:
-
final与abstract不能共存:
-
final:它的作用 修饰类代表不可以继承 修饰方法不可重写
-
abstract修饰类就是用来被继承的,修饰方法就是用来被重写的。
-
-
static 修饰的方法可以用类名调用,对于abstract修饰的方法没有具体的方法实现,所以不能直接调用,也就是说不可以与static共存。
-
private 修饰的只能在本类中使用,abstract方法是用来被子类进行重写的,有矛盾所有不能共存
知识点3-抽象类与普通类的异同
-
相同点
-
抽象类和普通类都是用来描述事物的,都在内部定义了成员。
-
-
不同点
-
普通类有足够信息来描述事物,抽身象类描述事物的信息有可能不够充足
-
普通类不能定义抽象方法,只能定义普通方法,抽象类中可以定义抽象方法,同时也可以定义普通方法
-
普通类可以被实例化,抽象类不可以被实例化
-
知识点4-抽象练习
/**
* 父类(抽象类)
*/
public abstract class MyShape {
//计算周长
public abstract double getLen();
//计算面积
public abstract double getArea();
}
/**
* 子类继承父类(抽象类)
*/
public class Rect extends MyShape {
//定义成员变量 宽高
private double width;
private double height;
public Rect(double width, double height) {
this.width = width;
this.height = height;
}
public double getWidth() {
return width;
}
public double getHeight() {
return height;
}
@Override
public double getLen() {
return 2 * (this.width + this.height);
}
@Override
public double getArea() {
return this.width * this.height;
}
}
/**
* 子类 继承 父类MyShape(抽象类)
*/
public class Circle extends MyShape {
private double r;
private static final double PI = 3.14; //定义常量PI
public Circle(double r) {
this.r = r;
}
public double getR() {
return r;
}
@Override
public double getLen() {
return 2 * PI * this.r;
}
@Override
public double getArea() {
return PI + this.r * this.r;
}
}
public class MyShapeTest {
public static void main(String[] args) {
System.out.println("==矩形的周长和面积==");
MyShape rect = new Rect(20, 30);
showInfo(rect);
System.out.println("==圆形的周长和面积==");
MyShape circle = new Circle(30);
showInfo(circle);
}
public static void showInfo(MyShape shape) {
System.out.println("周长为:" + shape.getLen());
System.out.println("面积为:" + shape.getArea());
}
}
/**
* ==矩形的周长和面积==
* 周长为:100.0
* 面积为:600.0
* ==圆形的周长和面积==
* 周长为:188.4
* 面积为:903.14
*/
知识点5-接口的概念
-
为什么使用接口?
接口(interface):在java中接口主要是使用来拓展定义类的功能,可以弥补Java中单继承的缺点。
-
接口(硬件类接口)
-
人类与电脑等,或人类与程序之间的接口,称为用户界面。
-
-
接口(软件类接口)
-
接口简单理解就是一种约定,接口是设计层面的概念,往往由设计师设计,将定义与实现分离,程序员实现接口,实现具体方法
-
-
接口的定义
-
java接口是一系列方法的声明,是一些抽象的集合,一个接口只有抽象方法没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。
-
简单地说,接口就是特殊的抽象类,即所有方法都是抽象方法的抽象类就是Java中的接口(interface)
-
知识点6-定义接口的格式
-
定义接口
接口中的成员修饰符是固定的:
-
public static final 修饰的变量变常量,该值不能改变,只能读。
-
修饰符:可选,用于指定接口的访问权限,可选值为public。即使省略,也依然是public。
-
接口名:必选参数,用于指定接口的名称,接口名必须是合法的Java标识符。一般情况下,要求首字母大写。
-
方法:接口中的方法只有定义而没有被实现。
-
-
接口中的成员示例:
public interface Pencil { //下面2行代码是等价 //public static final double PI = 3.14; double PI = 3.14; //下面2行代码是等价 //接口的所有方法都是抽象方法,所以abstract就可以省略了 //接口的方法就是方法的规范为其他实现类服务,所以默认public,其他的访问权限限定符不能使用 //public abstract void write(); void write(); }
知识点7-类与接口的关系
-
类和接口是实现关系,实现类的声明形式如下:
-
类与接口之间是实现关系,类实现接口
-
接口不可以被实例化
-
实现了接口的实现类必须重写接口中所有抽象方法后,这个子类才可以被实例化,否则报错
-
一个类可以实现多个接口,多个接口用逗号分隔,也可以不实现接口
-
Java不支持多继承,Java将多继承机制进行改良变成了多实现
-
一个类在继承另一个类同时,还可以实现多个接口
-
接口的出现避免了单继承的局限性
-
-
类实现接口的示例:
public interface Pencil { double PI = 3.14; void write(); }
public interface Eraser { /** * 删除 */ void remove(); }
/** * 接口可以多继承其他接口 */ public interface InterfaceTest extends Pencil, Eraser { }
/** * PencilWithEraser类实现Pencil,Eraser两个 * java的类是单继承(类)多实现(接口) */ public class PencilWithEraser implements Pencil, Eraser { //public class PencilWithEraser implements InterfaceTest { @Override public void remove() { System.out.println("删除数据"); } @Override public void write() { System.out.println("写数据"); } }
public class PencilWithEraserTest { public static void main(String[] args) { PencilWithEraser pwe1 = new PencilWithEraser(); pwe1.write(); pwe1.remove(); //类实现多个接口,使用接口类型接收new的对象,会出现 有的接口类型没有对应方法,进行强转对应的接口类型 // 常用的方法之一 Pencil pwe2 = new PencilWithEraser(); pwe2.write(); //不能调用 因为Pencil接口类型没有remove方法 //pwe2.remove(); //强转成 Eraser 接口类型 Eraser eas = (Eraser) pwe2; eas.remove(); } } /** * 写数据 * 删除数据 * 写数据 * 删除数据 */
知识点8-接口和接口的关系
-
接口和接口之间是继承关系
-
接口与接口之间是继承关系,而且可以多继承
-
接口的出现避免了单继承的局限性
-
案例
-
需求说明: 世界上有很多人种,例如中国人、美国人等,他们所说的语言各不相同。不管是什么人种,他们都是人类
-
实现步骤:
(1) 创建一个接口Person,定义一个抽象方法say()
(2) 创建Chinese 类实现Person,重写say方法
(3) 创建American 类实现Person,重写say方法
public interface Person {
void say();
}
public class Chinese implements Person {
@Override
public void say() {
System.out.println("讲中文");
}
}
public class American implements Person {
@Override
public void say() {
System.out.println("讲英语");
}
}
public class PersonTest {
public static void main(String[] args) {
// Chinese chinese1 = new Chinese();
// chinese1.say();
// American american1 = new American();
// american1.say();
//使用接口做为类型,不再使用具体实现类作为类型,但new还是要使用实现类
//也是多态的表现之一
Person chinese = new Chinese();
chinese.say();
Person american = new American();
american.say();
}
}
/**
*讲中文
*讲英语
*/
知识点9-接口与抽象类的区别
-
在Java中接口是一个比抽象类更加抽象的概念,由于只声明行为,因此在接口中的方法均是抽象的,下表中罗列了接口和抽象类的差异:
abstract class interface 属性 不用限制 public 静态 final 常量 构造方法 可有可无 没有 普通方法 可以有具体方法 必须是public抽象方法 子类 单一继承 多重实现(接口继承接口时为多重继承) -
抽象类体现继承关系,一个类只能单继承
-
接口体现实现关系,一个类可以多实现
-
抽象类是继承 is a关系 (所属关系)在定义该体系的基本共性内容
-
接口是实现是like a关系(不所属关系)在定义该体系额外功能
知识点10-接口可实现多继承原因
-
接口继承与类继承对比:
-
Java类的继承是单一继承,Java接口的继承是多重继承
-
-
接口可实现多继承原因分析:
-
不允许类多重继承的主要原因是,如果A同时继承B和C,而B和C同时有一个D方法,A无法确定该继承那一个
-
接口全都是抽象方法,不存在实现冲突,继承谁都可以,所以接口可继承多个接口
-
知识点11- JDK8接口的默认方法
-
Java8之前,Java接口纯粹是契约的集合,是一种程序设计的表达方式。从数据抽象的角度看,能够在不定义class的同时又可以定义type,是程序设计中强大而有用的机制。Java接口就是这些纯粹的接口组成的数据抽象
-
Java8之前,接口不能升级。因为在接口中添加一个方法,会导致老版本接口的所有实现类的实现新的方法(涉及到的类全部改动)
-
Java8之后,lambda表达式作为核心出现,为了配合lambda表达式,JDK中Collection库需要添加新的方法,如forEach(),stream()等,于是引入了默认方法(defender methods,Virtual extension methods)。
-
默认方法是库/框架设计者的后悔药。对于以前的遗留代码,大家都不知道有这个新方法,既不会调用,也不会去实现,如同不存在;编写新代码的程序员可以将它视为保底的方法体。类型层次中任何符合override规则的方法,优先于默认方法,因为遗留代码可能正好有同样的方法存在
-
默认方法的声明很简单,直接在接口中把方法声明为default,之后再写方法的实现即可。这样所有的实现类都会继承这个方法:
-
默认方法理论上抹杀了Java接口与抽象类的本质区别-前者是行为契约的集合,后者是接口与实现的结合体。当然,语法上两者的差别和以前一样。这就需要我们来自觉维护两者的本质区别,把默认方法作为库、框架向前兼容的手段
-
实例化实现接口的匿名类对象
public interface Apple {
void print();
}
public class AppleTest {
public static void main(String[] args) {
AppleTest test = new AppleTest();
//new 是一个实现Apple接口的匿名类(构造方法),创建了实现Apple接口的匿名类的对象
Apple a = new Apple() {
//匿名类的实现接口的方法 由程序员来完成
@Override
public void print() {
System.out.println("我是苹果");
}
};
//print就是存在就是上面写 匿名类对象的print方法
a.print();
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!