在阅读别人写的代码的时候,我注意到了一种写法。如下:
public interface Iface {
void doit(Integer i,String s);
}
public class Mapmap {
public static Map map=new HashMap();
}
public class Functiondemo {
{
Mapmap.map.put(1,this::m1);
Mapmap.map.put(2,this::m2);
}
public void m1(Integer i,String s){
System.out.println("m1");
}
public void m2(Integer i,String s){
System.out.println("m2");
}
}
public class Main {
public static void main(String[] args) {
Functiondemo functiondemo=new Functiondemo();
Iface iface = Mapmap.map.get(2);
iface.doit(2, "ss");
}
}
运行结果:
调试后发现iface.doit(2, "ss");执行的是Functiondemo中的m2()。
经过查找之后发现这其实Java 8 中提提供的新特性的一种写法。在上面使用了函数式接口和方法引用一起实现的,这样就可以在一个类中实现多个同一方法。
下面具体了解一下Java 8提供的这两个特性:
1.函数式接口:
函数式接口(functional interface 也叫功能性接口,其实是同一个东西)。简单来说,函数式接口是只包含一个方法的接口。比如Java标准库中的java.lang.Runnable和 java.util.Comparator都是典型的函数式接口。 java 8提供 @FunctionalInterface作为注解,这个注解是非必须的,只要接口符合函数式接口的标准(即只包含一个方法的接口),虚拟机会自动判断,(如上面例子就没有添加注解) 但最好在接口上使用注解@FunctionalInterface进行声明,以免团队的其他人员错误地往接口中添加新的方法。
除上面那种使用方法之外,常常也使用lambda表达式来实现接口。Java中的lambda无法单独出现,它需要一个函数式接口来盛放,lambda表达式方法体其实就是函数接口的实现.
2.方法引用:
其实是lambda表达式的一种简化写法。所引用的方法其实是lambda表达式的方法体实现,语法也很简单,左边是容器(可以是类名,实例名),中间是"::",右边是相应的方法名。如果你觉得lambda的方法体会很长,影响代码可读性,方法引用就是个解决办法。
一般方法的引用格式:
如果是静态方法,则是ClassName::methodName。如 Object ::equals
如果是实例方法,则是Instance::methodName。如Object obj=new Object();obj::equals;
构造函数.则是ClassName::new
如上面所示:
Mapmap.map.put(1,this::m1);
就使用了方法引用。
3.lambda表达式:
ArrayList integers = new ArrayList<>();
for(int i=0;i<10;i++){
integers.add(i);
}
integers.forEach(i-> System.out.println(i));
public static Future schedule(long delay, Runnable runnable) {
return ScheduledThreadPool.schedule(runnable,delay, TimeUnit.MILLISECONDS);
}
//lambda表达式的使用
TimedTaskManager.schedule(
10000, () -> {
casualty.setState(1);
initPlayer(casualty);
notificationManager.notifyPlayer(casualty,casualty.getName()+" 你已经复活 \n");
}
);
包含三部分:
1、一个括号内用逗号分隔的形式参数,参数是函数式接口里面方法的参数(从上面可以看到也可以没有这个括号)
2、一个箭头符号:->
3、方法体,可以是表达式(这个方法只需要执行一行代码,如第一个示例)和代码块(执行多行代码,如第二个示例)。
可以看到lambda表达式就是去执行一个方法,在方法中可以自己书写逻辑或者调用其他已存在的方法。