接口
约定好规范,然后按照规范来做。接口就是定义规范。(不需要实现)
抽象类中可以有普通方法,而接口中的方法默认都是抽象的,也可以说接口是一个特殊的
抽象类
,接口不能被实例化,而且没有构造方法。
1.定义接口
语法格式:
public interface 接口名{
//接口成员
}
- 接口使用
interface
来表示 - 接口的访问权限是public或者包访问权限,与类的访问权限类似
- 接口可以多继承,继承父类中声明的常量和抽象方法
成员变量声明
[public] [static] [final] 数据类型 成员变量名 = 常量;
- 即接口中成员变量默认都是 public、static、final 的,因此 public static final 可以省略。
- 在接口中定义必须给定初始值
成员方法
[public] [abstract] 返回值类型 方法名称(参数列表);
- 接口中的方法默认都是 public、abstract 的,因此 public abstract 可以省略。
2.实现接口
语法格式:
public 类名 implements 接口名{
实现方法
普通方法
属性
}
- 实现接口使用关键字
implements
,实现抽象类使用关键字extends
。 - 一个类可以实现多个接口,各个接口之间用逗号分隔。
- 实现接口的类必须实现接口中定义的抽象方法,即使类中不使用某个抽象方法也必须实现它,通常用空方法体实现子类不需要的抽象方法,如果抽象方法有返回值,可返回默认值。
- 接口的实现类允许包含普通方法。
- 在实现抽象方法是需要指定
public
权限,否则会产生编译错误。
示例:
/**
* 定义接口,关键词:interface
*/
public interface USBInterface {
void service();
}
// 定义U盘类,实现USB接口
class UDisk implements USBInterface{
// 实现接口的抽象方法
public void service(){
System.out.println("连接USB接口,开始充电");
}
}
class UsbFan implements USBInterface{
public void service(){
System.out.println("连接USB接口,开始转动");
}
}
测试类
public class USBtest {
public static void main(String[] args) {
//创建UDisk对象
USBInterface UDisk = new UDisk();
UDisk.service();
USBInterface UsbFan = new UsbFan();
UsbFan.service();
}
}
3.实现多个接口
接口本身也可以继承接口,接口继承的语法格式如下:
[修饰符] interface 接口名 extends 父接口1,父接口2,... {
// 常量定义
// 方法定义
}
java
中继承是单继承,使用 extends
关键字;但是一个类可以实现多个接口,使用 implements
, 多个接口之间用 ,
隔开。实现多个接口的语法如下:
class 类名 extends 父类名 implements 接口1,接口2,... {
// 类的成员
}
一个类可以同时继承和实现接口,extends
要在 implements
之前
public class LenovoComputer extends Computer implements USBInterface,ChargeInterface{
}
接口与接口之间是继承关系
,使用 extends
关键字。多个接口使用 ,
隔开。
4.JDK8.0
中新特性
1.default
在 jdk8.0
中 default
关键字可用于在接口中修饰方法(默认方法),default
修饰的方法可以具体实现,也只能在接口中出现。default
修饰的方法可以被重写。
示例:
public interface USBInterfaceDefault {
public default void service(){
System.out.println("USB接口");
}
}
class UDisk1 implements USBInterfaceDefault{
public void service(){
System.out.println("连接USB接口,开始充电");
}
}
class UsbFan1 implements USBInterfaceDefault{
}
class USBDefaulttest {
public static void main(String[] args) {
//创建UDisk对象
USBInterface UDisk = new UDisk();
UDisk.service();//连接USB接口,开始充电
USBInterface UsbFan = new UsbFan();
UsbFan.service();//USB接口
}
}
默认方法可以被接口子类覆盖,也可以不被覆盖。
2.static
接口中还可以有 static
修饰的方法,称为静态方法(类方法)。 static
方法必须直接使用接口名.方法名调用。
public interface USBInterfaceStatic {
public static void descriptor(){
System.out.println("USB 3.0接口");
}
}
class Test {
public static void main(String[] args) {
USBInterfaceStatic.descriptor();//USB 3.0接口
}
}
5.jdk 9.0
中接口的新特性
通过将接口中的方法声明为 private
,我们可以定义仅在接口内部使用的辅助方法,这些方法不会成为对外暴露的 API 的一部分。私有方法可以被接口中的其他方法调用,从而提供了代码复用和封装的能力。
public interface USBInterfacePrivate {
//抽象方法不能私有
public abstract void service();
public default void descriptor(){
//调用私有实例方法
print("abc");
System.out.println("接口中私有方法");
}
public static void staticMethod(){
//调用私有静态方法
println("a");
System.out.println("接口中私有静态方法");
}
//私有方法
private static void println(String str){
System.out.println(str);
}
private void print(String str){
System.out.println(str);
}
}
class Usb implements USBInterfacePrivate{
@Override
public void service() {
System.out.println("usb");
}
@Override
public void descriptor() {
USBInterfacePrivate.super.descriptor();
}
}
class Test1 {
public static void main(String[] args) {
//静态方法
USBInterfacePrivate.staticMethod();
Usb u = new Usb();
u.descriptor();
}
}
输出
a
接口中私有静态方法
abc
接口中私有方法
6.抽象类和接口的区别
特性 | 接口 | 抽象类 |
---|---|---|
多继承 | 接口可以继承多个父类接口 | 子类只能继承一个直接抽象类 |
实现 | 子类通过implements 实现多个接口 | 子类通过extends 继承抽象类 |
成员 | 接口中只能有常量、抽象方法。JDK8.0 及以后的版本中可以有static 方法和default 方法 | 抽象类中可以有实例成员、静态成员抽象方法。抽象类中不能使用default 关键字修饰 |
成员修饰符 | 接口中只能定义常量(public static final 修饰的变量) | 抽象类可以定义变量,也可以定义常量 |
子类实现 | 子类在实现抽象方法时必须指定public 权限 | 子类在实现抽象方法时不允许缩小访问权限 |
构造函数 | 接口中不能定义构造函数 | 抽象类可以有构造函数,但不能进行实例化 |
最高层 | 接口没有最高层 | 类的最高层是Object 类 |
相同点 | 两者都不能被实例化 、都是引用数据类型 、都可以包含抽象方法 |
---|---|
7.函数式接口
接口中有一种特殊的接口,这类接口中只有一个抽象方法。我们把这种接口称为函数式接口(FunctionalInterface
),可以使用 @FunctionalInterface
标记函数接口,函数接口表示某个功能(能力)
-
lambda
格式 :- 左边括号:lambda 的形参列表,就好比定义一个接口,里面有一个抽象方法,这个抽象方法的形参列表。
- 箭头:lambda 的操作符。
- 右边 lambda 体:就好比是我们实现了接口中的抽象方法。
-
如果
lambda
中实现只有一句代码则可以省略{}
-
这种写法
java
可以根据变量的类型推断出匿名类实现的接口,以及重写的方法。
方法写法:
- 如果方法没有参数则使用
()
表示。 - 如果有参数, 则需要在
()
写形参列表,在实现中可以使用这些参数。 - 参数的类型可以省略,可以推断出参数类型
- 如果只有一个参数则
()
可以省略
示例:
/*
无参无返回值
*
*/
public interface Lambda1 {
void show();
}
class Test {
public static void main(String[] args) {
Lambda1 l1 = () -> System.out.println("show方法");
Lambda1 l2 = () -> {
System.out.println("show");
System.out.println("第二行");
};
l1.show();
l2.show();
}
}
/*
* 有参有返回值
* */
public interface Lambda2 {
int method(int x,int y);
}
class Test3{
public static void main(String[] args) {
Lambda2 lamba2;
lamba2 = (x,y) ->{
int result =x +y;
return result;
};
System.out.println(lamba2.method(2,5));
}
public static int sum(int x, int y){
return (x+y);
}
}
扩展
克隆
浅克隆, 对象中的引用数据类型的字段是同一个引用 [默认]
深克隆,将对象中的引用数据类型也复制一份