java核心技术读书笔记(第五天:接口与lambda表达式)

1.接口🤨

Arrays类中的sort方法可以对对象数组进行排序,但对象所属的类必须实现Comparable接口

public interface Comparable<T> {
    int compareTo(T other);
}
  • 接口中的所有方法自动是public方法
  • 接口中不能有实例字段,可以看成没有实例字段的抽象类

检查一个类是否实现了特定的接口:

if(anObject instanceof Comparable){...}

接口可以继承其他的接口,可以有常量:

public interface Powered extends Comparable{
    double SPEED_LIMIT=95;
    double milesPerGallon();
}

实现了Cloneable方法才可以使用clone创建副本(浅克隆)

jdk8之后允许在接口中加入静态方法

jdk9中接口中的方法可以是private,private方法可以是静态方法或实例方法,不过只能在接口本身使用

可以为接口提供一个默认方法:

//用于访问一个数据结构中的元素,实现迭代器就要提供hasNext和next方法
public interface Iterator<E>{
    boolean hasNext();
    E next();
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
    ...
}

默认方法可以调用其他方法:

public interface Collection{
    int size();
    default boolean isEmpty(){
        return size() == 0;
    }
    ...
}

接口冲突:

interface Person{
    default String getName(){return "";};
}

interface Named{
    default String getName(){return getClass().getName();};
}

类同时继承两个接口是编译器会报错,解决(类优先规则):

class Studen implements Person,Named {
    public String getName(){return Person.super.getName();}
}

对象克隆

要实现Cloneable接口,重写其中的clone方法

clone方法是protected的,要重写为public方法

浅克隆只是克隆出了一个引用对象,深克隆会从最低层的数据克隆出一份,改变原数据是引起的克隆数据变化也不一样

关于深浅克隆的更多实例介绍详见另一篇笔记(原型模式):

https://blog.csdn.net/m0_57538148/article/details/123723453?spm=1001.2014.3001.5502


2.lambda表达式🧐

函数式接口

只有一个抽象方法的接口(接口可以声明非抽象方法)

基本用法

new Thread(() -> {
    System.out.println("");
});
var timer = new Timer(1000,event -> System.out.println(event));

方法引用

指示编译器生成一个函数式接口的实例,覆盖这个接口的抽象方法来调用给定的方法

直接把println方法传递到Timer构造器

var timer = new Timer(1000,System.out::println);
Arrays.sort(strings,String::compareToIgnoreCase);

总结:用::运算符分隔方法名与对象或类名,主要分3种情况:

object::instanceMethod		
  //等价于向方法传递参数的lambda表达式 
    //System.out::println即x->System.out.println(x)
Class::instanceMethod
  //第一个参数会变成方法的隐式参数,
    //String::compareToIgnoreCase即(x,y)->x.compareToIgnoreCase(y)
Class::staticMethod
  //所有参数都传递到静态方法
    //Math::pow即(x,y)->Math.pow(x,y)

只有当lambad表达式的体只调用一个方法而不做其他操作时,才能把lambda表达式重写为方法引用

比如:s->s.length() == 0 不能使用方法引用

可以在方法引用中使用this参数,比如:this::equals等价于x->this.equals(x)

使用super也是合法的:super::instanceMethod

使用this作为目标,会调用给定方法的超类版本

//每次定时器滴答时会执行super::greet方法
class Greeter{
    public void greet(ActionEvent event){
        System.out.println("Hello,the time is"+Instant.ofEpochMilli(event.getWhen()));
    }
}

class RepeatedGreeter extends Greeter{
    public void greet(ActionEvent event){
        var timer = new Timer(1000,super::greet);
        timer.start();
    }
}

构造器引用

例如:Person::new是Person构造器的一个引用

可以用数组类型建立构造器引用:int[] :: new等价于x->new int[x]

无法构造泛型类型T的数组,表达式new T[n]会产生错误,会自动改为new Object[n]

比如:Object[] people = stream.toArray()

解决:Person[] people = stream.toArray(Person[]::new) toArray调用构造器来得到正确类型的数组,填充并返回这个数组

变量作用域

lambda表达式实现了闭包

  • lambda表达式中捕获的值必须是事实最终变量,这个变量初始化之后不能再赋值\更改,包括外部
  • lambda表达式的体与嵌套块有相同的作用域,在表达式中不能有同名的局部变量
  • 使用this时用法并没有特殊之处

不合法举例:

//只能引用值不会改变的变量
pulic static void countDown(int start,int delay){
    ActionListener listener = event ->{
        start--;
    };
    new Timer(delay,listener).start();	//此时并发执行多个动作不安全
}
//引用另一个变量
pulic static void countDown(String text,int count){
    for(int i=1;i<=count;i++){
        ActionListener listener = event ->{
        	System.out.println(i+":"+text); //捕获的值i不能改变
        };
    }
    new Timer(delay,listener).start();	
}

处理lambda表达式

特点

延迟执行

  • 在一个单独的线程中运行代码
  • 多次运行代码
  • 在算法的适当位置执行代码(排序中的比较操作)
  • 发生某种情况时执行代码(点击按钮\数据到达等)



🧱后续待更。。。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晓晓的雨夜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值