接口
基本介绍
接口就是给出一些没有实现的方法,封装到一起,到某个类需要使用的时候,再根据实际具体情况把这些方法写出来
implements:实现
语法:
interface 接口名{
//属性
//方法
}
class 类名 implements 接口{
自己属性;
自己方法;
必须实现的接口的抽象方法
}
在JDK7.0前,接口所有的方法都没有方法体,即都是抽象方法
JDK8.0后接口可以有静态方法,默认方法,也就是说接口中可以有方法的具体实现
package Interface_;
public class Interface02 {
public static void main(String[] args) {
A a = new A();
a.hi();
a.ok();
}
}
//如果一个类imlements实现 接口
//需要将该接口的所有抽象方法都实行
class A implements AInterface{
@Override
public void hi() {
System.out.println("hi");
}
}
package Interface_;
public interface AInterface {
//写属性
public int n1=10;
//写方法
//在接口中,抽象方法可以省略abstract关键字
//在JDK7以前,接口中只能有抽象方法
public void hi();//抽象方法
//在JDK8以后,可以有默认实现方法, 需要使用default关键字修饰
public default void ok(){//默认方法---->需要使用default修饰
System.out.println("ok");
}
//在jdk8以后可以有静态方法
public static void cry(){//静态方法
System.out.println("cry");
}
}
接口的注意事项和细节
1、接口不能被实例化
package Interface_;
public class Interface01 {
public static void main(String[] args) {
IA ia = new IA();//'IA' 为 abstract;无法实例化
}
}
interface IA{
}
2、接口中所有的方法都是public方法,接口中的抽象方法可以省略abstract修饰
3、一个普通类实现接口,就必须将该接口中的所有方法都实现
4、抽象类实现接口,可以不用实现接口的方法
package Interface_;
public class Interface01 {
public static void main(String[] args) {
}
}
interface IA{
//接口的修饰符是可选的。当省略时,则默认为默认访问权限。如果要用修饰符进行修饰,则只能用public修饰符。
//接口中的方法默认为public abstract的,在声明时可以显式地注明,也可以省略
void say();
/**
* 此处不允许使用修饰符 'private'
* 此处不允许使用修饰符 'protected'
*/
public abstract void hi();//修饰符 'abstract' 对于接口方法是冗余的
}
class Cat implements IA{//将接口中所有的方法都实现,将鼠标光标移动到实现接口的类的接口名上,可以使用Alt+enter快捷键
@Override
public void say() {
//Interface_.Cat' 中的 'say()' 与 'Interface_.IA' 中的 'say()' 冲突;尝试分配较弱的访问权限('package-private');曾为 'public
}
@Override
public void hi() {
}
}
abstract class Tiger implements IA{//抽象类
// @Override
// public void hi() {
// 抽象类实现接口,可以不用实现接口的方法
// }
}
5、一个类可以同时实现多个接口
package Interface_;
public class InrerfaceDate01 {
public static void main(String[] args) {
}
}
interface IB{
void hi();
}
interface Ic{
void say();
}
class pig implements IB,Ic{
@Override
public void hi() {
}
@Override
public void say() {
}
}
6、接口的属性只能是final(最终的),而且是public static final修饰符
比如:
int a=1;
实际上:
public static final int a=1;(必须初始化)
package Interface_;
public class InrerfaceDate01 {
public static void main(String[] args) {
System.out.println(IB.n1);//没有实例化能够通过接口名.属性名调用,说明接口中的属性是static(静态的)
IB.n1=1111;//无法将值赋给 final 变量 'n1'
pig pig = new pig();
pig.n1=1;//无法将值赋给 final 变量 'n1'
// --->无法给n1赋值说明接口中的属性是final(最终的)
}
}
interface IB{
//接口的属性只能是final(最终的),而且是public static final修饰符
int n1=100;
// public static final int n1=100;
void hi();
}
7、接口中的属性的访问形式:接口名.属性名
System.out.println(IB.n1);
8、一个接口不能继承其他的类,但是可以继承多个别的接口
package Interface_;
public class InrerfaceDate01 {
public static void main(String[] args) {
}
}
interface IB{
}
interface IC{
}
class JA{
}
interface ID extends JA{
//一个接口不能继承其他的类
}
interface IF extends IB,IC{
}
9、接口的修饰符只能是public 和默认,这点和类的修饰符是一样的
接口和继承的比较
package Interface_;
/**
* 接口和继承的比较
*/
public class ExtendsVsInterface {
public static void main(String[] args) {
LittleMonkey wukong = new LittleMonkey("孙悟空");
wukong.climbing();
wukong.swimming();
wukong.flying();
}
}
//猴子类
class Monkey{
private String name;
public Monkey(String name) {
this.name = name;
}
public void climbing(){
System.out.println("猴子"+name+"会爬树");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//接口
interface Fishable{
void swimming();
}
//接口
interface Birdable{
void flying();
}
//继承,只要继承了就会自动拥有climbing方法
/**
*小结:
* 当子类继承了父类,就自动拥有了父类的功能
* 如果子类需要扩展功能,可以通过实现接口的方式来进行扩充
* 实现接口是对java单继承的补充
*/
class LittleMonkey extends Monkey implements Fishable,Birdable{
public LittleMonkey(String name) {
super(name);
}
@Override
public void swimming() {
System.out.println("猴子"+getName()+"通过学习学会了游泳");
}
@Override
public void flying() {
System.out.println("猴子"+getName()+"通过学习学会了飞翔");
}
}
1、接口和继承解决的问题不同
基础的价值主要在于:解决代码的复用性和可扩展性
接口的主要价值在于:设计,设计好各种规范(方法),让其他类去实现这些方法
2、接口比继承更加灵活
接口比继承更加灵活,继承满足is-a的关系,而接口满足的是like-a的关系
理解:先天继承和后天学习的区别
先天从父类处继承某些特性,后天学习某些行为
例子:
一个女孩子先天从父母处继承类似的长相,后天通过学习化妆展现不同的面容
3、接口在一定程度上实现代码解耦
接口的多态特性
1、多态参数
package Interface_;
public class InterfacePolyParameter {
public static void main(String[] args) {\
//接口的多态体现
//接口类型的变量aa01可以指向AA接口的对象实例
AA aa01=new monster();
aa01=new car();
//继承体现的多态
//父类类型的变量bb可以指向继承了BB的子类的对象实例
BB bb = new BB();
bb=new CC();
}
}
interface AA{
}
class monster implements AA{
}
class car implements AA{
}
class BB{
}
class CC extends BB{
}
class DD extends BB{
}
2、多态数组
package Interface_;
public class InterfacePolyArr {
public static void main(String[] args) {
//多态数组-->接口型数组
Usb[] usbs = new Usb[2];
usbs[0]=new phone_();
usbs[1]= new Camera_();
/**
* 给Usb数组中,存放phone和相机对象,phone类中还有一个特有的方法call()。
* 请遍历Usb数组,如果是phone对象,除了会调用Usb接口定义的方法外,还需要调用phone特有的方法
*/
for (int i = 0; i < usbs.length; i++) {
usbs[i].work();//会进行动态绑定
//需要调用phone对象的特有方法,需要进行类型的向下转型
if (usbs[i] instanceof phone_){//判断它的运行类型是phone
((phone_)usbs[i]).call();
}
}
}
}
interface Usb{
void work();
}
class phone_ implements Usb{
public void call(){
System.out.println("手机可以打电话");
}
@Override
public void work() {
System.out.println("手机工作中");
}
}
class Camera_ implements Usb{
@Override
public void work() {
System.out.println("相机工作中");
}
}
3、接口存在多态传递现象
package Interface_;
public class InterfacePolyPass {
public static void main(String[] args) {
//接口类型的变量可以指向,实现该接口的类的对象实例
G g = new teacher();
//如果G接口继承了H接口,teacher实现了G接口
//就相当于teacher类也实现了H接口
//多态传递现象
H h=new teacher();//如果接口G不继承H,报错,类似与teacher也实现了H接口
}
}
interface H{
}
interface G extends H{
}
class teacher implements G{
}
练习:
interface A{
int x=0;//等价于:public static final int x=0;
}
class B{
int x=1;
}
class C extends B implements A{
public void PX(){
//如果调用接口A的x---->A.x
//如果调用父类的x--->super.x
System.out.println(x)//此处代码运行无法知道想要打印那个x
}
public static void main(String[] args){
new C().PX();
}
}