android java 闭包

17 篇文章 0 订阅
7 篇文章 0 订阅


这段代码中,程序员希望foo函数中的变量i被内部循环的函数使用,并且能分别获得他们的索引,而实际上,只能获得该变量最后保留的值,也就是说.闭包中所记录的自由变量,只是对这个变量的一个引用,而非变量的值,当这个变量被改变了,闭包里获取到的变量值,也会被改变.

var result=[];
function foo(){
    var i= 0;
    for (;i<3;i=i+1){
        result[i]=function(){
            alert(i)
        }
    }
};
foo();
result[0](); // 3
result[1](); // 3
result[2](); // 3



这段代码中,程序员希望foo函数中的变量i被内部循环的函数使用,并且能分别获得他们的索引,而实际上,只能获得该变量最后保留的值,也就是说.闭包中所记录的自由变量,只是对这个变量的一个引用,而非变量的值,当这个变量被改变了,闭包里获取到的变量值,也会被改变.

<pre name="code" class="javascript">var result=[];
function foo(){
    var i= 0;
    for (;i<3;i=i+1){
        result[i]=(function(j){
            return function(){
                alert(j);
            };
        })(i);
    }
};
foo();
result[0](); // 0
result[1](); // 1
result[2](); // 2


 
让内部函数在循环创建的时候立即执行,并且捕捉当前的索引值,然后记录在自己的一个本地变量里.然后利用返回函数的方法,重写内部函数,让下一次调用的时候,返回本地变量的值 

java

</pre><pre code_snippet_id="1560752" snippet_file_name="blog_20160121_4_4788078" name="code" class="java">interface Action 
{ 
    void Run(); 
} 

public class ShareClosure { 

    List<Action> list = new ArrayList<Action>(); 
    int i;
    public void Input() 
    { 
        for(i=0;i<10;i++) 
        { 
            list.add(new Action() {    
                @Override 
                public void Run() { 
                    System.out.println(i); 
                } 
            }); 
        } 
    } 
    
    public void Output() 
    { 
        for(Action a : list){a.Run();} 
    } 
    
    public static void main(String[] args) { 
        ShareClosure sc = new ShareClosure(); 
        sc.Input(); 
        sc.Output(); 

    } 

} 
输出:全部为10


<<Java编程思想>> 

  是一个匿名的代码块,可以接受参数,并返回一个返回值,也可以引用和使用在它 

周围的,可见域中定义的变量。-- Groovy ['ɡru:vi] 

  是一个表达式,它具有自由变量及邦定这些变量的上下文环境。 

  闭包允许你将一些行为封装,将它像一个对象一样传来递去,而且它依然能够访问 

到原来第一次声明时的上下文。 

  是指拥有多个变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这 

些变量也是该表达式的一部分。 

  闭包是可以包含自由(未绑定)变量的代码块;这些变量不是在这个代码块或者任 

何全局上下文中定义的,而是在定义代码块的环境中定义。 

  在这些定义中都有一些关键字:变量、函数、上下文等,闭包在回调函数、函数式 

编程、Lambda表达式中有重要的应用


interface Action 
{ 
    void Run(); 
} 

public class ShareClosure { 

    List<Action> list = new ArrayList<Action>(); 
    
    public void Input() 
    { 
        for(int i=0;i<10;i++) 
        { 
            final int copy = i; 
            list.add(new Action() {    
                @Override 
                public void Run() { 
                    System.out.println(copy); 
                } 
            }); 
        } 
    } 
    
    public void Output() 
    { 
        for(Action a : list){a.Run();} 
    } 
    
    public static void main(String[] args) { 
        ShareClosure sc = new ShareClosure(); 
        sc.Input(); 
        sc.Output(); 

    } 

} 
输出: 0-9



这两种代码是作用域不同引起的与堆栈管理有关




这个例子创建一个接口列表List<Action> ,先向列表中创建 i 个匿名内部类new 

Action(),然后通过for遍历读出。 

因为 i 变量在各个匿名内部类中使用,这里产生了闭包共享,java编译器会强制要求 

传入匿名内部类中的变量添加final 

关键字,所以这里final int copy = i;需要做一个内存拷贝,否则编译不过。(在c#中 

没有强制要求会导致列有被遍历时 

始终会取 i 最大值,这是因为延迟执行引起的) 






                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值