背景
方法是一堆声明和业务逻辑代码,返回结果给调用者。方法也可以执行特定的逻辑,不返回任何值给调用者。
方法能够复用代码,但是java里面的方法必须属于某个类。
在看闭包之前,我们先复习一下lamada表达式。
lamada表达式是函数式接口的实例。lamda表达式实现了唯一的抽象方法,也就是实现了函数式接口。
如果函数式接口有多个抽象方法定义,就无法用lamada表达式实现多个方法,如下:
函数式接口(functional interface 也叫功能性接口,其实是同一个东西)。简单来说,函数式接口是只包含一个方法的接口。比如Java标准库中的java.lang.Runnable和 java.util.Comparator都是典型的函数式接口。
备注:接口的方法都是抽象的,除非利用default关键字定义方法
interface GreetingService {
void sayMessage(String message);
default void sayMessage2(String mess){
}
}
我们看下面的例子:
package com.java.bitmap;
public class Java8Tester {
public static void main(String args[]){
Java8Tester tester = new Java8Tester();
// 不用括号
GreetingService greetService1 = message -> System.out.println("Hello " + message);
// 用括号
GreetingService greetService2 = (message) -> System.out.println("Hello " + message);
greetService1.sayMessage("Runoob");
greetService2.sayMessage("Google");
}
interface GreetingService {
void sayMessage(String message);
}
}
总结:
- 函数式接口就是仅定义一个抽象方法的接口。
- lamada表达式实现了仅有的抽象方法,也就是实现了函数式接口
lamada表达式作用:
- 能够把方法作为函数参数
- 创建函数不属于任何类
- lamada表达式能够像对象一样传递,按需执行
lamada表达式限制:lamada表达式的引用的外层变量都是final类型,无法改变值,否则会报错。为了解决这个问题,闭包出现了。
闭包
定义
闭包函数:声明在一个函数中的函数,叫做闭包函数。
闭包:内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。
我们来看JS里面的闭包定义,首先看下面的代码:
function init() {
var name = 'Mozilla'; // name is a local variable created by init
function displayName() { // displayName() is the inner function, a closure
alert(name); // use variable declared in the parent function
}
displayName();
}
init();
上面代码分析:
- name是init函数的局部变量,displayName方法没有任何变量,但是作为init的内部函数,他可以访问name变量
- 内部函数可以访问外部函数的变量,但是反之,外部函数无法访问内部函数的变量
修改后如下:
function makeFunc() {
var name = 'Mozilla';
function displayName() {
alert(name);
}
return displayName;
}
var myFunc = makeFunc();
myFunc();
myFunc
是displayName的引用,在makeFunc执行的时候被创建的- 在makeFunc 执行结束后,我们仍然可以访问name变量,这就是闭包的作用
闭包的作用
- 让外部访问函数内部变量成为可能;
- 局部变量会常驻在内存中;
- 可以避免使用全局变量,防止全局变量污染;
- 会造成内存泄漏(有一块内存空间被长期占用,而不被释放)
闭包例子
function funA(){
var a = 10; // funA的活动对象之中;
return function(){ //匿名函数的活动对象;
alert(a);
}
}
var b = funA();
b(); //10
function outerFn(){
var i = 0;
function innerFn(){
i++;
console.log(i);
}
return innerFn;
}
var inner = outerFn(); //每次外部函数执行的时候,都会开辟一块内存空间,外部函数的地址不同,都会重新创建一个新的地址
inner();
inner();
inner();
var inner2 = outerFn();
inner2();
inner2();
inner2(); //1 2 3 1 2 3
var i = 0;
function outerFn(){
function innnerFn(){
i++;
console.log(i);
}
return innnerFn;
}
var inner1 = outerFn();
var inner2 = outerFn();
inner1();
inner2();
inner1();
inner2(); //1 2 3 4
Java中的闭包实现
(argument_list) -> {func_body}
e
edit
play_arrow
brightness_4
// Java program to demonstrate
// how a closure is implemented
// using lambda expressions
import java.io.*;
// Defining an interface whose
// implementation is given in
// the lambda expression.
// This uses the concept of
// closures
interface SalutationInterface {
public String salHello();
}
class GFG {
// Driver code
public static void main(String[] args)
{
// Lambda Expression
SalutationInterface obj = () ->
{
return "Hello, GFGians!";
};
// Calling the above interface
System.out.println(obj.salHello());
}
}