Java中的闭包

背景

方法是一堆声明和业务逻辑代码,返回结果给调用者。方法也可以执行特定的逻辑,不返回任何值给调用者。

方法能够复用代码,但是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表达式作用:

  1. 能够把方法作为函数参数
  2. 创建函数不属于任何类
  3. 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()); 
    } 
} 

 

 

 

 

 

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页