第一章.java&golang的区别之:闭包
- java8之前的闭包
public class ClosureBeforeJava8 {
int y = 1;
public static void main(String[] args) {
final int x = 0;
ClosureBeforeJava8 closureBeforeJava8 = new ClosureBeforeJava8();
Runnable run = closureBeforeJava8.getRunnable();
new Thread(run).start();
}
public Runnable getRunnable() {
final int x = 0;
Runnable run = new Runnable() {
@Override
public void run() {
16
System.out.println("local varable x is:" + x);
//System.out.println("member varable y is:" + this.y); //error
}
};
return run;
}
}
上段代码的输出:local varable x is:0
在代码的第13行到第20行,通过匿名类的方式实现了Runnable接口的run()方法,实现了一部分操作的集合(run方法),并将这些操作映射为java的对象,在java中就可以实现将函数以变量的方式进行传递了,如果仅仅是传递函数指针,那还不能算是闭包,我们再注意第17行代码,在这段被封装可以在不同的java对象间传递的代码,引用了上层方法的局部变量,这个就有些闭包的意思在里面了。但是第18行被注释掉的代码在匿名类的情况下却无法编译通过,也就是封装的函数里面,无法引用上层方法所在对象的成员变量。总结一下,java8之前的闭包特点如下:
1.可以实现封装的函数在jvm里进行传递,可以在不同的对象里进行调用;
2.被封装的函数,可以调用上层的方法里的局部变量,但是此局部变量必须为final,也就是不可以更改的(基础类型不可以更改,引用类型不可以变更地址);
- java8里对闭包的支持
java8里对于闭包的支持,其实也就是lamda表达式,我们再来看一下上段代码在lamda表达式方式下的写法:
public class ClosureInJava8 {
int y = 1;
public static void main(String[] args) throws Exception{
final int x = 0;
ClosureInJava8 closureInJava8 = new ClosureInJava8();
Runnable run = closureInJava8.getRunnable();
Thread thread1 = new Thread(run);
thread1.start();
thread1.join();
new Thread(run).start();
}
public Runnable getRunnable() {
final int x = 0;
Runnable run = () -> {
System.out.println("local varable x is:" + x);
System.out.println("member varable y is:" + this.y++);
};
return run;
}
}
上面对代码输出:
local varable x is:0
member varable y is:1
local varable x is:0
member varable y is:2
在代码的第16行到第20行,通过lamda表达式的方式实现了函数的封装(关于lamda表达式的用法,大家可以自行google)。通过代码的输出,大家可以发现,在lamda表达式的书写方式下,封装函数不但可以引用上层方法的effectively final类型(java8的特性之一,其实也是final类型)的局部变量,还可以引用上层方法所在对象的成员变量,并可以在其它线程和方法中对此成员变量进行修改。总结一下:java8对于闭包支持的特点如下:
1.通过lamda表达式的方式可以实现函数的封装,并可以在jvm里进行传递;
2.lamda表达式,可以调用上层的方法里的局部变量,但是此局部变量必须为final或者是effectively final,也就是不可以更改的(基础类型不可以更改,引用类型不可以变更地址);
- golang里对闭包的支持
golang里对于闭包的支持,理解起来就非常容易了,就是函数可以作为变量来传递使用,代码如下:
package main
import "fmt"
func main() {
ch := make(chan int ,1)
ch2 := make(chan int ,1)
fn := closureGet()
go func() {
fn()
ch <-1
}()
go func() {
fn()
ch2 <-1
}()
<-ch
<-ch2
}
func closureGet() func(){
x := 1
y := 2
fn := func(){
x = x +y
fmt.Printf("local varable x is:%d y is:%d \n", x, y)
}
return fn
}
代码输出如下:
local varable x is:3 y is:2
local varable x is:5 y is:2
代码的第24行到27行,定义了一个方法fn,此方法可以使用上层方法的局部变量,总结一下:
1.golang的闭包在表达形式上,理解起来非常容易,就是函数可以作为变量,来直接传递;
2.golang的封装函数可以没有限制的使用上层函数里的局部变量,并且在不同的goroutine里修改的值,都会有所体现。
关于第2点,大家可以参考文章:https://studygolang.com/articles/11627 中关于golang闭包的讲解部分。
- 总结
golang的闭包从语言的简洁性、理解的难易程度、支持的力度上来说,确实还是优于java的。本文作为java和golang对比分析的第一篇文章,由于调研分析的时间有限,难免有疏忽之处,欢迎各位指正。
第一章.java&golang的区别之:闭包的更多相关文章
- 第一章 –– Java基础语法
第一章 –– Java基础语法 span::selection, .CodeMirror-line > span > span::selection { background: #d7d4 ...
- 第一章 Java的I/O演进之路
I/O基础入门 Java的I/O演进 第一章 Java的I/O演进之路 1.1 I/O基础入门 1.1.1 Linux网络I/O模型简介 根据UNIX网络编程对I/O模型的分类,UNIX提供了5中I/ ...
- Java基础知识二次学习-- 第一章 java基础
基础知识有时候感觉时间长似乎有点生疏,正好这几天有时间有机会,就决定重新做一轮二次学习,挑重避轻 回过头来重新整理基础知识,能收获到之前不少遗漏的,所以这一次就称作查漏补缺吧!废话不多说,开始! 第一 ...
- javaSE习题 第一章 JAVA语言概述
转眼就开学了,正式在学校学习SE部分,由于暑假放视频过了一遍,略感觉轻松,今天开始,博客将会记录我的课本习题,主要以文字和代码的形式展现,一是把SE基础加强一下,二是课本中有很多知识是视频中没有的,做 ...
- 第一章 java基本多线程技能
第一章 java多线程技能 1 线程:进程是操作系统结构的基础,是一次程序的执行,是一个程序及其数据在处理顺序时发生的活动:是程序在一个数据集合上运行的过程,他是系统进行资源分配和调度的一个独立单位. ...
- 第一章 Java多线程技能
1.初步了解"进程"."线程"."多线程" 说到多线程,大多都会联系到"进程"和"线程".那么这两者 ...
- 第一章Java学习(查漏补缺)
第一章主要内容: 1.Java的地位:网络地位 语言地位 需求地位 2.Java的特点:①简单 面向对象 平台无关:软件的运行不因操作系统,处理器的变化而无法运行或出现运行错误. ②多线程 动态 3. ...
- 深入Java虚拟机读书笔记第一章Java体系结构介绍
第1章 Java体系结构介绍 Java技术核心:Java虚拟机 Java:安全(先天防bug的设计.内存).健壮.平台无关.网络无关(底层结构上,对象序列化和RMI为分布式系统中各个部分共享对象提供了 ...
- Java核心技术(Java白皮书)卷Ⅰ 第一章 Java程序设计概述
第1章 Java程序设计概述1.1 Java程序设计平台 具有令人赏心悦目的语法和易于理解的语言,与其他许多优秀语言一样,Java满足这些要求. 可移植性 垃圾收集 提供大型的库 如果想要有奇特的绘 ...
随机推荐
- 国内各大支付平台的API地址
1丶目前国内最火的支付平台--蚂蚁金服开放平台(支付宝) https://open.alipay.com/platform/home.htm 2丶国内游戏帝国--腾讯(微信支付) https://pa ...
- Windows10 Ubuntu bash 配置 LAMP+JDK+Tomcat
Windows10的Bash省去了装ubuntu虚拟机的麻烦,而且可以直接用Windows下的浏览器去访问了,Exciting有没有,再也不用去忍受日常崩溃的chromium和慢慢的firefox了. ...
- OpenApi开放平台架构实践
背景 随着业务的发展,越来越多不同系统之间需要数据往来,我们和外部系统之间产生了数据接口的对接.当然,有我们提供给外部系统(工具)的,也有我们调用第三方的.而这里重点讲一下我们对外的接口. 目前,我们 ...
- PAT1036:Boys vs Girls
1036. Boys vs Girls (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue This ti ...
- 多个DbContext修改同一张表测试
多个DbContext修改同一张表经测试是可行的. UserStore和DepartmentStore都可以向SysLog表写入数据 用多个线程同时通过UserStore和DepartmentStor ...
- ASP.NET后台中调用前台Javascript函数的几种方法
做web开发,用的技术是aspx.net,可是由于比较习惯于ASP现在做起来,觉得非常别扭,原因在于有很多功能其实在前台可以处理的,但是因为用到了很多webcontrol,导致不断postback.如 ...
- Linux时间子系统之(四):timekeeping
专题文档汇总目录 Notes:timekeeping模块的狠心数据结构是timekeeper,它维护了系统不同类型时钟的时间值,并且介绍了获取不同类型时钟时间的函数. clocksource切换通过c ...
- async 和 await 之异步编程的学习
async修改一个方法,表示其为异步方法.而await表示等待一个异步任务的执行.js方面,在es7中开始得以支持:而.net在c#5.0开始支持.本文章将分别简单介绍他们在js和.net中的基本用法 ...
- Javascript中没有块级作用域(模仿)
在C/C++中,由花括号封闭的代码块都有自己的作用域,也就是块级作用域(私有作用域).而在javascript中则没有块级作用域,首先来看一段代码: function test(){ for(var ...
- 3. Java面向对象之泛型-指定多个泛型
3. Java面向对象之泛型-指定多个泛型 package generic; class MutiGeneric<K, T> { private K key; private T take ...