百家争鸣 Java需要引入闭包吗?

开发 后端
最近有很多人呼吁要在Java的新版本中引入闭包。那么Java或者说 OOPL (面向对象编程语言)需要引入闭包吗?有了对象还需要闭包吗?本文是笔者的一些看法,希望大家来一起辩论。

首先先了解一下什么是闭包

闭包是可以包含自由(未绑定)变量 的代码块;这些变量不是在这个代码块或者任何全局上下文中定义的,而是在定义代码块的环境中定义。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量的存在,相关变量引用没有释放)和为自由变量提供绑定的计算环境(作用域)。

可能上面的定义有点晦涩,下面看一下《Python 核心编程》对闭包的解释。

如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被定义为闭包 。定义在外部函数内的但由内部函数引用或者使用的变量被称为自由变量 。

下面是一个闭包的例子 (由于Java现在不支持闭包,这个闭包的例子是用Python写的,参见了《Python 核心编程》 )

Python代码

def counter(start_at = 0):     
    count = [start_at]     
    def incr():     
        count[0] += 1    
        return count[0]     
    return incr    
 
def counter(start_at = 0):  
    count = [start_at]  
    def incr():  
        count[0] += 1  
        return count[0]  
    return incr  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

这里面count变量 就是一个 相对于函数incr 的自由变量(它在 函数incr 的外部作用域上,但又不在全局作用域上),内部函数incr 可以引用和使用这个变量。这个例子主要模拟一个计数器。

运行下面的代码

Java代码

count = counter(6)     
print count()     
print count()    
 
count = counter(6)  
print count()  
print count()  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

就会打印出

    7

    8

我们发现 内部函数(incr)不但可以引用其自身定义的变量,还可以引用外部函数(counter)定义的变量。或者说 内部函数(闭包) 可以记忆状态, 它可以根据 它记忆的状态 来执行不同的操作。 而外部函数负责初始化状态(内部函数需要记忆的状态)。

那么为什么需要闭包,闭包的优势是什么呢?我觉得就是可以记忆状态,但对象也可以记忆状态(通过对象的属性)。那闭包和对象的区别是什么呢? 我觉得就因为闭包是函数而不是对象。我们会发现,如果用面向对象的方式来表达闭包内部函数(闭包)就像 对象的方法而外部函数  对象的构造器。构造器用来初始化对象状态而对象的方法可以根据 对象的状态 来执行不同的操作。

好!下面我们用面向对象的方式 创建一个 计数器(实现和上例一样的功能,用Java实现)。

Java代码

public class Counter {     
    private int startAt;     
    public Counter() {     
        this(0);     
    }     
    public Counter(int startAt) {     
        this.startAt = startAt;     
    }     
    public int incr(){     
        return ++ this.startAt;     
    }     
}    
 
public class Counter {  
 private int startAt;  
 public Counter() {  
  this(0);  
 }  
 public Counter(int startAt) {  
  this.startAt = startAt;  
 }  
 public int incr(){  
  return ++ this.startAt;  
 }  

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.

运行Test类

Java代码

public class Test{     
    public static void main(String[] args){     
        Counter counter = new Counter(6);     
        System.out.println(counter.incr());     
        System.out.println(counter.incr());     
    }     
}    
 
public class Test{  
 public static void main(String[] args){  
  Counter counter = new Counter(6);  
  System.out.println(counter.incr());  
  System.out.println(counter.incr());  
 }  
}  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.

会打印出(和上例打印输出相同)

    7

    8

那么Java(有了对象)还需要引入闭包吗?我觉得不需要,因为对象完全可以模拟闭包的行为,而且对象才是OOP 的一级元素。闭包是函数式编程(FP)中的概念,引入闭包就相当于引入FP,这只会破坏Java的纯粹与简单。

【编辑推荐】

  1. Java虚拟机几个命令行参数说明
  2. Java虚拟机发展回顾 为跨平台而生
  3. Java虚拟机概念及体系结构
  4. 在Netbeans上安装JavaFX插件
  5. JavaBean中使用JDBC连接进行事务处理
责任编辑:彭凡 来源: javaeye
相关推荐

2014-08-26 14:24:09

华为HCC华为云计算大会云计算

2009-10-21 15:35:22

综合布线市场

2010-01-11 09:00:12

JVMJava 7JDK 7

2010-06-01 10:13:10

2010-08-30 10:38:00

2013-02-19 09:34:53

BYOD解决方案华为

2013-01-08 09:32:46

SaaSOracleSAP

2012-12-17 10:59:50

云计算公有云

2012-07-05 09:01:24

云计算Amazon微软

2017-11-17 08:58:00

智能无人航运

2010-05-19 15:35:32

2009-04-15 09:02:03

2015-12-30 20:17:31

安智超级碗

2010-04-19 09:51:52

2021-04-25 09:17:09

工信部计算技术云计算

2018-04-18 10:19:27

RSA大会区块链云安全

2022-11-02 13:42:08

AI语言模型

2021-12-25 21:57:57

OpenSCA

2018-04-28 08:19:46

首都网络安全日网络安全日网络安全

2022-05-26 09:30:43

WiFi网络技术
点赞
收藏

51CTO技术栈公众号