接口、接口和抽象类的区别、接口静态方法、JDK8基于接口的新特性、函数式接口(@FunctionalInterface)与lambda表达式、内部类

接口

接口(interface)是一种特殊的抽象类,本质上不是一个类,里面只能包含常量和方法的定义(不允许实现),接口就是一套未实现方法的集合。

声明语法

[修饰符] <interface> 接口名称{

[常量定义]

[抽象方法的定义]

}

例如

public interface Flyable{
    //public static final String NAME = "bird";
    String NAME = "bird";
    
    //public abstract void fly();
    void fly();
}

从以上表现来看,接口中不存在像普通类一样的属性,以及普通方法,因此接口实际上就是一套标准,既然是标准,那就必然存在实现,java中的类可以实现多个接口,从而弥补了类只能单继承的缺点。

实现类

public class Bird implements Flyable{
    
    public void fly(){
        System.out.println("自由自在的飞翔");
    }
    
}

并且接口也允许有多个子类实现

实现类2

public class plane implements Flayble{
    public void fly(){
        System.out.println("从北京飞武汉");
    }
}

同时java中的类可以实现多个接口

接口2

public interface Singable{
    void sing();
}

实现类3

public class Bird implements Flyable,Sinable{
    public void fly(){
        
    }
    public void sing(){
        
    }
}

如果一个子类实现了多个接口,那么这个子类就必须实现所有的抽象方法(除非这个子类是抽象类).

注意事项:

  1. 接口中只能存在常量和抽象方法(JDK1.8以前)

  2. 接口允许继承接口,并且能多继承

  3. 接口不允许继承任何类(包括抽象类)

  4. 接口允许有多个子类实现,并且子类可以同时实现多个接口

  5. 接口不属于类,因此不存在构造器,所以也无法实例化

接口(标准)和抽象类(类)的区别

  1. 接口通常表示对行为(动词,或形容词)的抽象;抽象类一般为对具备相同的属性的类(名词)的抽象

  2. 接口中只允许常量和抽象方法;抽象类中具备普通的类所有特征,同时也支持抽象方法

  3. 接口允许多实现,接口允许继承多个接口;抽象类只能单继承

  4. 接口不存在构造器,无法实例化;抽象类虽然存在构造器,但是也无法实例

JDK8基于接口的新特性

JDK版本更新迭代后新版本的JDK中对于接口新增很多新特性,比如:接口默认方法,静态方法,函数式接口等。

默认方法

某些情况下,可能实现类只需要对于接口中的部分方法实现而非所有方法,因此在这种需求下JDK新增了默认方法的设定,将一些实现类只需选择性实现的方法定义为default方法,这样一来,这些子类(实现类)就可以不一定实现,例如:

public interface CategoryManage {
​
    boolean add(Category c);
    
    //JDK8默认方法
    default boolean updateCname(Category c){
        return false;
    }
    
    //JDK8默认方法
    default boolean delete(int cid){
        return false;
    }
    
    ArrayList<Category> findAll();
    
    Category findById(int cid);
}
​
​

以上接口中updateCname和delete方法为默认方法,因此,子类可以无需实现这两个方法,如下:

public class CategoryManageImpl implements CategoryManage{
​
    @Override
    public boolean add(Category c) {
        // TODO Auto-generated method stub
        return false;
    }
​
    @Override
    public ArrayList<Category> findAll() {
        // TODO Auto-generated method stub
        return null;
    }
​
    @Override
    public Category findById(int cid) {
        // TODO Auto-generated method stub
        return null;
    }
​
}
​

这种操作,是JDK中一种兼容性的解决方案。

接口静态方法

JDK中除了对接口新增默认方法外,还新增接口的静态方法,即在接口直接将方法定义为静态的已实现方法,这样一来,就无需创建接口的实现类来调用,直接通过接口名.方法()即可调用,大大提高方法调用的便利性.

public interface CategoryManage {
​
    boolean add(Category c);
    
    //JDK8接口静态方法:该方法可以直接通过接口名调用(无需创建对象)
    static String showMsg(){
        return "HelloInterface";
    }
    
    ArrayList<Category> findAll();
    
    Category findById(int cid);
}
​
​

函数式接口(@FunctionalInterface)与lambda表达式

所谓函数式接口是JDK8中新增的一种概念,表名一个接口中只存在一个未实现方法(可以包含默认方法,静态方法和从Object中继承的方法)

@FunctionalInterface
public interface Flyable {
​
    void fly();
    
}
​

@FunctionalInterface是注解,用于检查接口是否只包含一个未实现的方法。

lambda表达式

public class Test{
    public static void main(String[] args){
        Flyable f = ()->{};
    }
}

实际应用

public class TestLambda {
    public static void main(String[] args) {
        //ArrayList
        List<String> list = Arrays.asList("Tom","Jarray","Lily","Lilei","Hanmeimei"); 
        //lambda表达式实际使用
        list.forEach(n->System.out.println(n)); 
    }
}

注意事项:

lambda表达式只能适用函数式接口

内部类

内部类(innerClass),表示的是在一个类的定义中允许出现其他类的声明,这些其他类通常称之为内部类(或:寄生类,类属类),内部类可以访问外部类中的成员(属性,方法),内部类提供了比方法更为强大的封装特性;Java中的内部类分为以下几种:

  • 成员内部类

  • 局部内部类

  • 静态内部类

  • 匿名内部类

成员内部类

成员内部类的权限类似于成员变量,是在类结构的最顶层定义,跟全局变量,方法属于一个访问级别

public class InnerClass {
    
    //成员内部类
    class OtherClass{
        public void m2(){
            System.out.println("成员内部类的方法");
        }
    }
    
    public void m1(){
        System.out.println("外部类的方法");
    }
    
    public static void main(String[] args) {
        //调用内部类方法时必须先创建外部类对象
        new InnerClass().new OtherClass().m2();
    }
​
}
​

局部内部类

java中的内部类还能在构造器,普通方法,语句块中定义,这些内部类称之为局部内部类,局部内部类的使用范围只能在声明区域,局部内部类不能使用访问修饰符修饰,因为在方法级别已经定义的访问权限

public class OutterClass {
    
    public void m(){
        
        class InnerClass2{
            public void m2(){
                System.out.println("内部类方法");
            }
        }
        
        InnerClass2 ic = new InnerClass2();
        ic.m2();
    }
    
    public void n(){
        //局部内部类只能在定义范围使用
//      new InnerClass2();
    }
    
    
    public static void main(String[] args) {
        //局部内部类只能在定义范围使用
//      new OutterClass().new InnerClass2();
    }
    
}

静态内部类

另外java中还提供了静态内部类,在将成员内部类使用static修饰,从而使得在外界需要使用当前类的内部类时,只需要通过外部类的名称.内部类即可访问。

public class OutterClass2 {
​
    //静态内部类
    static class InnerClass2{
        public void m(){
            System.out.println("静态内部类的方法。。");
        }
    }
    
    public void m1(){
        new InnerClass2().m();
    }
    
    public static void main(String[] args) {
        OutterClass2.InnerClass2 oi = new OutterClass2.InnerClass2();
        oi.m();
    }
}

内部类的作用

  1. 内部类提供了比方法更好的封装性

  2. 在单继承的前提下,使用内部类再继承继承其他类,提高了类的扩展性

public class Dog extends Animal{
​
    public class MyPet extends Pet{
        @Override
        public void play() {
            System.out.println("狗子欢快的撒娇。。。。");
        }
    }
    
    @Override
    public void eat() {
        System.out.println("愉快的吃着狗粮、。。");
    }
    
    public void run(){
        new MyPet().play();
        eat();
    }
    
    public static void main(String[] args) {
        new Dog().run();
    }
    
}
​

匿名内部类(重要)

匿名内部类,顾名思义就是没有名字的内部类,所在在使用时一般只能使用一次,匿名内部类的作用简化代码的编写。

例如:为按钮对象绑定事件监听的实现原理

Button.java

public class Button {
​
    private String text;
    private int width;
    private int height;
    private int x;
    private int y;
    
    // setter/getter
    
    /**按钮的点击事件监听*/
    public void setOnClickListener(OnClickListener lis){
        lis.click();
    }
    
    /**监听事件接口*/
    interface OnClickListener{
        void click();
    }
}
​

TestButton.java

public class TestButton {
​
    public static void main(String[] args) {
        
        Button btn = new Button();
        //匿名内部类
        btn.setOnClickListener(new Button.OnClickListener(){
            @Override
            public void click() {
                System.out.println("hello");
            }
        });
        
        //简化写法(lambda表达式)
        btn.setOnClickListener(()->{System.out.println("hello");});
        
    }
}

以上为基于匿名内部类的回调机制实现

Timer&TimerTask

Timer是一个定时器对象,通过Timer对象可以定时执行某些定时任务(TimerTask)

TimerTask通常与Timer结合起来共同使用,TimerTask一般作用为创建一些定时任务(比如:闹钟,定时消息推送)

public class TimerDemo {
​
    public static void main(String[] args) {
        //创建定时器
        Timer t = new Timer();
        //调度定时任务
        t.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("当前时间:"+new Date());
                
            }
        }, 3000, 1000);
        
    }
​
}
​

以上代码为通过定时器调度定时任务,延时3秒(3000毫秒)后每隔1秒(1000毫秒)执行一次定时任务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值