闭包最早定义为一种包含<环境成分>和<控制成分>的实体.
解释一:闭包是引用了自由变量的函数,这个被引用的变量将和这个函数一同存在。
解释二:闭包是函数和相关引用环境组成的实体。
注:<自由变量>:除了局部变量的其他变量
简单理解:闭包能够 将一个方法 作为 一个变量 去存储,这个方法有能力去访问所在类的自由变量。
Java中闭包实现
关键点:
如何用变量去存储方法?
java中能够保存方法的变量指的就是普通的对象
如何让这个普通对象能够访问所在类的自由变量?
纯天然的解决办法是:内部类。内部类能够访问外部类的所有属性及方法。
隐藏具体实现是内部类的作用之一,如何保证隐藏具体实现的同时还能将闭包传递到外部使用?
让内部类实现通用接口,然后将内部类对象向上转型为接口类型。
上述解决办法就是Java最常用的闭包实现办法(内部类+接口)
下面提供一个简单的实现
1 public class Milk { 2 3 public final static String name = "纯牛奶";//名称 4 5 private static int num = 16;//数量 6 7 public Milk() 8 { 9 System.out.println(name+":16/每箱"); 10 } 11 12 /** 13 * 闭包 14 * @return 返回一个喝牛奶的动作 15 */ 16 public Active HaveMeals() 17 { 18 return new Active() 19 { 20 public void drink() 21 { 22 if(num == 0) 23 { 24 System.out.println("木有了,都被你丫喝完了."); 25 return; 26 } 27 num--; 28 System.out.println("喝掉一瓶牛奶"); 29 } 30 }; 31 } 32 33 /** 34 * 获取剩余数量 35 */ 36 public void currentNum() 37 { 38 System.out.println(name+"剩余:"+num); 39 } 40 } 41 42 /** 43 * 通用接口 44 */ 45 interface Active 46 { 47 void drink(); 48 }
使用上述实现
1 public class Person { 2 3 public static void main(String[] args) { 4 //买一箱牛奶 5 Milk m = new Milk(); 6 7 Active haveMeals = m.HaveMeals(); 8 9 //没事喝一瓶 10 haveMeals.drink(); 11 //有事喝一瓶 12 haveMeals.drink(); 13 14 //看看还剩多少? 15 m.currentNum(); 16 } 17 18 } 19
运行结果
纯牛奶:16/每箱 喝掉一瓶牛奶 喝掉一瓶牛奶 纯牛奶剩余:14
上述例子中,通过调用Active的方法实现对Milk私有变量num进行修改。
总结
1.实际项目中没怎么用过闭包,因此不能对他的好坏进行评论。
2.建议合理的使用闭包,不完全不使用,也不能滥用。
3.特别注意:闭包会导致资源不被回收,如上例,在main方法中将m设为null,使用haveMeals继续调用drink方法仍然会喝掉一瓶牛奶,说明Milk对象并没有被释放掉。