本章解决的一个核心问题就是怎么传一个方法 f 给另一个方法 g,让另一个方法 g 可以调用 f
目录
零、接口:
Java没有多继承,想要一个类有多种能力就必须用接口。
接口中可以定义常量,默认是public static final
接口会导致的冲突问题:
1.接口和接口内的方法冲突: 程序员应该给出一个覆盖的实现
2.接口和超类的方法冲突:类优先原则,优先调用类里的同名方法。
演示冲突:
两个接口里有同名方法,编译时就能检查出问题!
类里的同名方法优先被调用:
一、Lambda
在c++、c中可以用function<>,或者函数指针来传一个函数给另一个函数。
在Java里没有函数指针,只存在传对象给某方法,这就暗示着必须用对象把要传递的方法包裹一层。
λ函数就是简化了传接口或者内部类,让代码更好写。
书上举了个例子,Timer中想定时调用某个方法,但Java中方法不能裸奔,只能用一个接口的壳子传给Timer,这个接口被规定为ActionListener。
接口里只有一个抽象方法需要实现的情况,可以用λ表达式替代掉每次创建一个接口的实现类这种繁琐的动作:
public class Test {
public Test(){
}
public static void main(String[] args) throws InterruptedException {
//这三种写法可以理解为等价的!
Timer timer = new Timer(1000,new Printer());
Timer timer1 = new Timer(2000,e->{
System.out.println("2000");
});
Timer timer2 = new Timer(3000, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("3000");
}
});
timer.start();
timer1.start();
timer2.start();
while (true){
Thread.sleep(1000);
}
}
}
用匿名内部类或者lambda都比再额外定义一个class要好。
函数式接口的概念得懂呢!
接下来要解决的问题是,怎么接收一个λ保存到变量里?c++里可以直接用auto,java中则是内置了许多的包装类,比如 BiFuncion, UnaryOperator, Predicate, Supplier, Cosumer ...:
Java中的两个冒号表示方法的引用,也是类似于λ,但功能要弱一些
和c++的两个冒号表示作用域是不同的!
不过方法引用太费脑子了!这下就把java的语法弄得有些复杂了!个人觉得λ已经够用了!
lambda的注意事项:操作外部变量的时候会发生错误!
总结:内置的函数式接口(注意Runnable也是一个!:
二、内部类
内部类可以操作外部类的变量,这是通过隐含地持有一个外部类的引用实现的(也就意味着不可能跳过外部类直接new出内部类的对象!!)
内部类具体的实用价值很多,这里就不一一列举了!
编译器会隐含地生成一个方法,来替换掉内部类对外部类字段的访问:
做个实验:
确实会给外部类隐含生成一个静态方法,来返回private字段a(改成public int a就不行了!)。
局部内部类,就是能在方法里面定义的类。
匿名内部类是局部内部类的一种!暗含着生成了一个没有名字,但实现了某接口的对象:
静态内部类?就是不需要操作外部类变量的类,所以不会带有外部类对象的引用:
小结:本章需要明白lambda,函数式接口,匿名内部类三者间的关系!