菜鸟学JAVA之——接口(interface)

接口(interface)

引入:

接口是大家一起约定俗成的对一个对于类型的规范(仅仅是一套规范),抽象类存在的意义是被继承,它是一个模板,它里面也可以包含方法体被实现的方法(普通方法),这时如果子类继承了抽象类,忘了重写这个普通方法,但是他要用的是被重写的方法,这时虽然说代码编译不会出错,但是逻辑上出错了。这就是抽象类的不好的地方,另一个不好的是抽象类是类的范畴,它也是只能单继承,不能实现多继承。怎么办呢?这里就开辟了一个接口范畴,引入了接口。(接口编译后也被编译为.class文件)

接口的命名规则:

  • 只要是接口一定要以大写的“I”开头,后面跟接口名

  • 如果类要实现接口,则命名是最好在类名后加Impl

public interface IUsb {
 /*public static final*/int HIGHT = 3;
 /*public abstract*/ void foo();
    Object input();
    Object output();
}

注意事项:

  • 接口中定义的所有变量默认是public static final的,不能是其他类型的

  • 接口中只能有抽象方法(只关心有没有这个方法,不关心怎么实现它),且方法一定是public的

  • 接口中不会有任何一个方法是公共的(有方法体),但抽象类中有

  • 接口用来做一套模板规范,关心的是整个体系,而不关心某个个体,实现的类来关心个体(使用抽象类和接口只是为了说明要干什么事,而让他们的实现类去根据自己的需要去实现这些方法 )

  • 类和接口是实现的关系,可以多实现

  • abstract跟final一定不能放一起,因为abstract是必须被继承重写,而final是一定不能被继承

  • static 与 abstract也不能一起用,因为static是放在元数据区的,一定是被实现了的,实际存在的。但是abstract没有被实现,实际并不存在

  • 接口里面不能放普通属性,但是想个办法可以放普通方法

    接口里面的方法,其实可以有方法体

    public interface IUsb {
        //1.静态方法
        static void foo() {
            System.out.println("s");
        }
        //2.默认方法,且可以被重写
        default void output() {
            System.out.println("s");
    
        }
    }
    

接口里面可以放:

1.属性:PSF(public static final)如果不显示的声明,默认就是PSF,显示的声明也是必须是PSF

2.普通方法,都是PA(public abstract) 没有方法体

3.静态方法,static方法,可以有方法体,这个方法放在方法区的元数据区,但是静态方法不能由实现他的类继承( 因为一个类可以实现多个接口。如果多个接口具有相同的静态方法,它们都将被继承,编译器就不知道要调用哪个接口)

4.默认方法,有方法体,代表显式的去除了abstract的修饰

抽象类有构造方法,接口里没有构造方法,没有能力创建对象

其实接口也可以创建对象,通过匿名类创建!

public class Main {
     public static void main(String[] args) {
         IUsb iUsb = new IUsb() {
                @Override
                public void doo() {

                }
            };
     }   
}

注意这是用匿名类的构造方法创建的对象,而不是接口创建的

有构造方法的类就可以创建对象。 错

抽象类也不能直接创建对象,必须要用匿名类来创建对象。匿名类创建对象是用抽象类在创建对象吗?不是,他是一个没有名字,继承了抽象类的一个类,只是在这里实现了他的抽象方法,是通过自己的构造方法创建的对象

java里的继承是单继承 错

条件不明确,java里类范畴的继承是单继承,多实现。接口范畴没有实现,但可以多继承

代码实现

接口可以继承扩展,但是只能继承接口,不能继承抽象类

public interface IPlastic {
    
}
public interface IMetel {
    
}

public interface IToy extends IPlastic,IMetel {
    
}

接口与接口之间没有实现关系,只有继承关系 ;类与接口是实现的关系,类与类之间是继承的关系

总结:

在这里插入图片描述

接口是继承的一种,符合里氏替换原则,父类能干的事,他的实现类也能干

public interface IMetel {
    public void asyourwish();
}

public interface IUsb {
    void doo();
    void input();
    void output();

}

public class USBImpl implements IUsb,IMetel {

    @Override
    public void doo() {
        //这个方法是实现的
        System.out.println("我是实现类的doo方法");
    }

    @Override
    public void input() {
        System.out.println("我是实现类的input方法");
    }

    @Override
    public void output() {
        //这个方法是重写的
        System.out.println("我是实现类的output方法");
    }
    
    @Override
    public void asyourwish() {
		System.out.println("我是实现类的asyouwish方法");
    }
}

场景类

public class Main {
    public static void main(String[] args) {
        IUsb usb1 = new USBImpl;
        usb1.input();  //这个input走的是USBImpl的input
        //李氏替换原则:我要的是父类,你给我的是哪个子类我不关心
        //usb1.asyourwish();//不能这样写,上面的声明过程是把usb1当成IUsb接口来用,而IUsb里面没有asyouwish方法,USBImpl有这个方法,但不能用。除非类型转换,如下
        USBImpl myUsb = (USBImpl)usb1;//myUsb与usb1的内存地址是一样的,只是类型不一样了,也就是栈里认为他可以多指几个东西了,但是堆里的东西是没变的(这里可以结合我博客继承里面画的内存分配图理解)
        myUsb.asyourwish();//这样就可以调用了
        //或者可以这样写((USBImpl)usb1).asyourwish(); 
        USBImpl usb = new USBImpl();
        ((IUsb)usb)
    }
}

可以把上面代码这样想:

比如公司把你当成普通员工招进来的,现在让你做精英员工的加班功能,你愿意做吗,肯定不

父类能做的子类一定能做,这里指的是声明的这个父类。普通员工要做加班工作那就应该把他转为精英员工

回顾一下类型转换:小类型向大类型转可以直接转,大类型向小类型转有风险(大类型不能保证小类型就有你要调的某个方法),兄弟类之间进行转换大概率会出错

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值