函数式接口

16 篇文章 1 订阅

欢迎点击

类的继承

继承的特点

单继承

class A{}
class B extends A{}  ‍️
class C extends A,B{} ‍️

多级继承

  • Java.long.Object

    class A{}
    class B extends A {} ‍️
    class C extends B {} ‍️

多子类

抽象类 (abstract)

  • P165

    • 子类就是一个父类,所以是继承关系。
    • 子类中共有的方法,但是所有子类都不一样

格式

含有抽象方法的类,必须是抽象类
    public abstract class Animal{
        //抽象方法定义
        public abstract void eat();
        //普通方法定义
        public void move (){

        }
    }
  • 不能直接使用new关键字
  • 必须用子类继承抽象父类
  • 子类必须实现父类中所有的抽象方法
  • 创建子类对象进行使用

public class Cat extends Animal{
    @Override
    public void eat(){
        sout("猫吃鱼!");
    }
}

Cat cat = new Cat;
cat.eat();

注意

  • 抽象类不能创建对象
  • 抽象类中,可以有构造函数,是供子类创建对象时,初始化父类成员使用的。
    • 如果构造函数是抽象的,则子类中用 supper()调用
    • 先创建父类
    • 后创建子类
  • 抽象类不一定有抽象方法,没有抽象方法的抽象类,也不能直接创建对象
  • 抽象类的子类,必须实现父类所有的抽象方法,否则依然是一个抽象类

发红包案例

分析
红包分为普通红包和运气红包
  1. 群主有钱
  2. 成员收红包,余额增加
  • 类: 群主、普通成员、用户类
  • 共性:姓名、余额
  • 独有:
    • 群主: 发红包
    • 成员: 收红包
  • 发红包
    • 返回值类型: ArrayList
    • 方法名称: send
    • 参数列表:
      • 总金额: int totalMoney
      • 分数: int count
public ArrayList <Integer> send (int totalMoney,int count){
    ...
}
  • 收红包
    • 返回值类型:void
    • 方法名:receive
    • 参数列表:ArrayList
public void receive (ArrayList <Integer> list){
    ...
}

接口(interface)

接口就是一个 公共的规范接口
符合标准 -> 通用
关键字 interface -> .class 文件

  • 包含的内容
    • 常量
    • 抽象方法
    • 默认方法 JDK8
    • 静态方法 JDK8
    • 私有方法 JDK9

接口是引用类型

public interface 接口名称{
//接口内容
}

  • 定义
  • 注意:
    • 接口不能直接使用,必须使用一个实现类来实现接口
      public class 实现类名 implements 接口名称{
      
      }
      
    • 实现类必须重写 接口中所有的抽象类
    • 创建实现类使用接口
    • 如果有抽象方法没有重写,那么该类就是一个抽象类

默认方法

  • 从JDK8 允许默认方法

  • 可以解决接口升级问题

    • 如果接口添加抽象方法,就会导致所有子类全部实现
    • 使用default 方法,在接口中实现方法体
  • 使用

    public default 返回值 方法名称(方法参数){
        //可以有方法体
        //public 可以省略
    }
  • 默认方法会被实现类所继承
  • 也可被实现类重写

静态方法

static :共享方法

    public static void test(){
        //带有方法体
    }
  • 接口名称可以直接 . 调用
  • 不能通过实现类调用静态方法
    • 实现多个接口,静态方法可能发生冲突
    • 不需要创建实现类对象

私有方法

一种安全机制
  • 普通
    • 多个默认方法之间重复代码问题
private void test(){

}
  • 静态
    • 多个静态方法之间重复代码问题
private static void test(){

}

常量

接口中够可以定义成员"变量" public static final (省略依旧)
不可修改

public static final int x = 1;

共有、接口名称 . 访问

  • 常量必须赋值
  • 完全大写
  • 下划线连接单词

接口小结

小结

  • 在Java 9+ 版本中,接口的内容有:
  1. 成员变量其实是称量,格式:
    • [public] [static] [final] 数据类型 常量名 = 数据值;
    • 注意:
      • 常量必须进行赋值,且不可改变
      • 常量名完全大写,用下划线分割
  2. 接口中最重要的是抽象方法,格式:
    • [public] [abstract] 返回值类型 方法名称 (参数列表);
    • 注意:
      • 实现类必须实现所有的抽象方法
  3. 从Java8 开始 ,允许定义默认方法,格式:
    • [public] default 返回值类型 方法名称(参数列表){ 方法体 }
    • 注意:
      • 默认方法也可以被覆盖重写
  4. 从Java8 开始, 允许定义静态方法,格式:
    • [public] static 返回值类型 方法名称(参数列表) { 方法体 }
    • 注意:
      • 通过接口名称直接调用,不能通过实现类进行调用
  5. 从Java9 开始, 允许定义私有方法,格式:
    • 普通私有方法:private 返回值类型 方法名称(参数列表){ 方法体 }
    • 静态私有方法:private static 返回值类型 方法名称(参数列表){ 方法体 }
    • 注意:
      • private 的方法只能在接口内调用,不能被实现类和别人使用。

注意

接口不能有静态代码块和构造方法 抽象类有构造方法
一个类的直接父类只有一个,但是可以实现多个接口
    public class MyInterfaceImpl implements MyInterfaceA,MyInterfaceB{}
两个抽象方法重名,只需覆盖重写一次即可
重名的默认方法,实现类一定对重复的覆盖重写    
一个类如果直接父类中的方法,和接口中的方法发生冲突,直接使用父类的方法
继承 优先于 接口实现
  • 类与类是单继承的

  • 类与接口是多实现的

  • 接口与接口之间是多继承的

    • 多个父接口当中的抽象方法冲突可以
    • 多个父接口当中的默认方法冲突,那么子接口必须进行默认方法覆盖,【必须带着 default 关键字】
  • P184 结束


函数式接口

  • P410 开始

    有且只有一个抽象方法的接口,称之为函数式接口
    可以包含其他的方法(默认方法、静态方法、私有方法)
    函数式编程 Lambda

/**
    @FunctionalInterface    
    可以监测是否是一个函数式接口
 */
@FunctionalInterface
public interface MyFocationInterface{
}
    public abstract void method();

使用

一般可以作为参数和返回值来使用
参数
	//定义一个方法,参数使用函数式接口 
	public static void test (MyFunctionInterface myInter){
		myInter.method();
	}

	main(){
		//调用 show 方法,参数使用函数式接口的实现类对象 
		show (new MyFunctionInterfaceImpl());
		//调用show方法 ,参数使用 匿名内部类
		show(new MyFunctionInterface(){
			@Override
			public void method(){
				sout("使用匿名内部类重写接口中的抽象方法!");
			}
		});
		//调用show方法 ,参数使用 Lambda 表达式
		show(()-> sout("Lambda实现接口的抽象方法!"));

	}
匿名内部类生成 .class 文件
Lambda表达式不会生成 .class 文件

函数式编程

Lambda 的延迟执行

日志可以快速定位问题

package Demo4.Lambda;

/*
    日志案例

    性能浪费的问题:
        调用  showLog 传递的第二个参数是一个拼接后的字符串
        先拼接 后调用方法
        showLog 如果等级不是 1 级,不会输出,字符串白 拼接了,浪费

     使用Lambda 特性进行 优化
     使用前提:必须存在函数式接口
        延迟加载
*/

public class Demo01Logger {
    //定义一个根据日志等级,显示日志信息
    public static void showLog(int level,String message) {
        if(level == 1){
            System.out.println(message);
        }
    }


    public static void main(String[] args) {
        //定义三个日志信息

        String msg1 = "Hello";
        String msg2 = "World";
        String msg3 = "Java";

        //调用showLog 方法,传递参数
		showLog(1,msg1+msg2+msg3);
		//========================

		//Lambda 优化
		showLog2(1,()->msg1+msg2+msg3);


	}
	
	//传递等级 和 接口
	public static void showLog2(int level ,MessageBuilder builder){
		if(level == 1){
			System.out.println(builder.builderMessage());
		}
	}
}

@FunctionalInterface
public interface MessageBuilder {
    public abstract String builderMessage();
}



使用 Lambda 表达式 作为参数传递,仅仅把参数传递到showLog 中
只有满足条件,日志的等级为1 
	才会调用接口 MessageBuilder 中的方法 BuilderMessage
	才会进行字符串的拼接
如果条件不满足 level != 1
	MessageBuilder 中的方法不会调用
	资源不会浪费

Runable 是一个 函数式接口

public class RunnableLambda {
    public static void threadRun (Runnable run){
        new Thread(run).start();
    }
    public static void main(String[] args) {
        //匿名内部类
        threadRun(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() +"--> 线程启动!");
            }
        });

        //Lambda 表达式
        threadRun(()-> System.out.println(Thread.currentThread().getName() +"--> 线程启动!"));

        new Thread(()->System.out.println(Thread.currentThread().getName() +"--> 线程启动!")).start();
    }
}
返回值

Comparator 也是一个 函数式借口

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值