- 浏览: 445391 次
- 性别:
- 来自: 西安
文章分类
最新评论
-
进退取舍:
谢谢,这个用上了!!
Java 一个线程池的示例 -
pb_water:
感谢楼主,打算买楼主的书,支持一下,楼主功德无量
JavaScript内核系列第0版整理稿下载 -
lancezhcj:
有图会直观的多呢,再摸索摸索
有限自动机与建模 -
hsmsyy:
这里应该是原创了吧,楼主我觉得闭包的作用:实现面向对象。有待商 ...
JavaScript内核系列 第7章 闭包 -
wll52:
在应用退出之前,需要释放连接 con.disconnect() ...
使用smack与GTalk通信
引言
Java中的匿名类是比较有意思的一种编程方式,在swing中关于监听器的注册时,经常可见到这样的代码:
iexit.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { int y = JOptionPane.showConfirmDialog( null, "Confirm exit", "Confirm Exit Dialog", JOptionPane.YES_NO_OPTION); if(y == JOptionPane.YES_OPTION){System.exit(0);} } });
通常使用匿名类的场景是,临时的创建一个类,实现指定的接口 ,使得调用者可以通过接口的方法来实现一定的操作。比如上边这个例子中,exit这个菜单项,需要一个动作监听器,如果用常规写法,大概如此:
class XListener implements ActionListener{ public void actionPerformed(ActionEvent e){ //action here } } XListener l = new XListener(); iexit.addActionListener(l);
虽然完成了同样的工作,但是代码量明显比刚才要多。
实例
在javascript,或者其他函数式编程语言中,常常可以见到诸如此类的写法:
$("#element").click(function(){ //do something }); $("div.type").each(function(index){ //do something else with the index });
将一个匿名函数传递给另一个函数,实现一些列定制的动作,正好工作中有个地方要用到类似的东东,就用java的匿名类实现了一套类似的机制:
Integer[] is = new Integer[]{ 4,13,65,64,2,4,5,9,10,25,20,32,30 }; //用数组构造一个integer 的 list FPList<Integer> p = new FPList<Integer>(is); p.append(100);//再添加一个元素 //做一次过滤,只有偶数被留下来 FPList<Integer> even = p.filter(new Filter(){ public boolean isLegal(Object item) { int x = ((Integer)item).intValue(); return x % 2 == 0 ? true : false; } }).filter(new Filter(){//再做一次过滤,10的倍数被留下来 public boolean isLegal(Object item){ int x = ((Integer)item).intValue(); return x % 10 == 0 ? true : false; } });
这样可以将很多的条件AND到一起,对数据做条件过滤。
设计与实现
首先,需要定义一个接口(这是匿名类的基础),在这个例子中,我定义了一个过滤器接口,其中只有一个方法,即isLegal(Object item), 这个方法接受一个Obejct参数,返回一个boolean值,调用者根据这个boolean值来对最终结果做过滤:
package org.free.fplist; /** * defined what condition should be used in <code>FilterableList.filter()</code> * * @author juntao.qiu@gmail.com * */ public interface Filter { /** * this is a condition definition, pass a object in, and then * a <code>true</code> or <code>false</code> will be returned. * @param item * @return */ boolean isLegal(Object item); }
另外,我们需要一个接口,用来表示一个链表具有被过滤的能力(FPable):
package org.free.fplist; /** * This is the interface defined Function-programmable support * * @author juntao.qiu@gmail.com * */ public interface FPable<E> { /** * append a new element to list, and then return <code>this</code> object * * @param e element you want to insert into * @return */ FPable<E> append(E e); /** * do a filter by the given rule, the <code>Filter</code> * object passed in is defined as a interface, and you need * to implement the condition. * * @param f * @return */ FPable<E> filter(Filter f); /** * mapping the action to each item of <code>function-programming-list</code> * and will not affect the original list * * @param act the Action will used to mapping * @return */ FPable<E> mapping(Action act); /** * distinct the <code>FilterableList</code>, keep one same elements only, and * does not affect the List itself. * * @return */ FPable<E> distinct(); /** * for debug only, print the <code>index</code> and <code>content</code> * of each item of a list. */ void print(); }
附加的,我需要对这个链表有函数映射 (map)的支持,上面这个接口中的Action,为另一个接口,同样会被很多的匿名类使用到:
package org.free.fplist; public interface Action { public Object doAction(Object item); }
好了,我们现在来看一个FPable的实现FPList,FPList继承了LinkedList,并且实现了FPable,可以对其中的数据进行过滤(前提是传入一个过滤器 ),或者对其中的元素进行映射(传入一个动作 ),FPList会自动的将过滤器和动作作用到List中的每一个元素。
package org.free.fplist; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.Set; public class FPList<E> extends LinkedList<E> implements FPable<E>{ private static final long serialVersionUID = 348375840291148300L; public FPList(){ } /** * construct a fp-list by given array. * * @param es */ public FPList(E[] es){ for(int i = 0;i < es.length;i++){ add(es[i]); } } public FPList<E> filter(Filter f){ FPList<E> filtered = new FPList<E>(); for(int i = 0; i < size();i++){ E o = get(i); if(f.isLegal(o)){ filtered.add(o); } } return filtered; } public FPList<E> append(E e){ add(e); return this; } public FPList<E> distinct(){ FPList<E> filtered = this; Set<E> set = new HashSet<E>(); for(int i = 0; i < filtered.size();i++){ set.add(filtered.get(i)); } filtered.clear(); Iterator<E> it = set.iterator(); while(it.hasNext()){ filtered.add(it.next()); } return filtered; } public FPList<E> mapping(Action act){ FPList<E> mapped = this; for(int i = 0;i < size();i++){ mapped.add(i, (E)act.doAction(get(i))); mapped.remove(i+1); } return mapped; } public void print(){ for(int i = 0;i < size();i++){ System.err.println("index : "+i+", content : "+get(i)); } } }
使用匿名类
匿名类的使用是比较方便的,为了代码更简洁,我使用了jQuery中的链机制,其实,大家平时使用的StringBuffer就提供这样的能力。
package org.free.fplist; public class Main { public static void main(String[] args){ String[] as = new String[]{ "Apple", "Borland", "Cisco", "Dell", "Epson", "Flick", "Google" }; FPList<String> k = new FPList<String>(as); k.distinct().filter(new Filter(){ public boolean isLegal(Object item) { return ((String)item).indexOf("e") >= 0 ? true : false; } }).filter(new Filter(){ public boolean isLegal(Object item) { return ((String)item).indexOf("p") >= 0 ? true : false; } }).mapping(new Action(){ public Object doAction(Object item) { return ((String)item)+", co"; } }).print(); Integer[] is = new Integer[]{ 4,13,65,64,2,4,5,9,10,25,20,32,30 }; FPList<Integer> p = new FPList<Integer>(is); p.append(100); FPList<Integer> even = p.filter(new Filter(){ public boolean isLegal(Object item) { int x = ((Integer)item).intValue(); return x % 2 == 0 ? true : false; } }).filter(new Filter(){ public boolean isLegal(Object item){ int x = ((Integer)item).intValue(); return x % 10 == 0 ? true : false; } }); even.mapping(new Action(){ public Object doAction(Object item) { return ((Integer)item).intValue()*10; } }).mapping(new Action(){ public Object doAction(Object item){ return ((Integer)item).intValue()/2; } }).print(); Person[] person = new Person[]{ new Person("abruzzi", 25, "male"), new Person("smith", 25, "female"), new Person("json", 26, "female"), new Person("jet.lee", 25, "male") }; FPList<Person> fp = new FPList<Person>(person); fp.filter(new Filter(){ public boolean isLegal(Object item) { Person p = (Person)item; return p.getAge() == 25 ? true : false; } }).filter(new Filter(){ public boolean isLegal(Object item) { Person p = (Person)item; return p.getSex().equals("male") ? true : false; } }).mapping(new Action(){ public Object doAction(Object item) { System.err.println(((Person)item).getName()); return null; } }); } }
main的运行结果如下:
index : 0, content : 50
index : 1, content : 100
index : 2, content : 150
index : 3, content : 500
abruzzi
jet.lee
上边的例子显示,匿名类在接口 中的方法不多的时候,整个匿名类整体作为一个对象传递给另外一个方法,可以很好的做到可定制性。比如第三个例子,使用Person bean的时候,可以定制多个过滤条件,依次将原始列表过滤成一个符合要求的列表。
另,文章中用到了比较多的函数式编程的概念,虽然java原生不支持,但是函数式编程作为一种思想,肯定可以在命令式的程序设计中有所体现。
评论
第一部分关于paradigm的,写的不错
呵呵,不要教条主义,也不要用静态的眼光看事物。将别的比较好的语言风格融入java有何不可?java 7不也引入闭包吗,你说闭包在易读,易改方面,占了哪条?
你为什么一定要纯粹的面向对象呢?谁说java又一定要纯粹的面向对象呢?
一直觉得spring, hibernate, struts是可有可无的东西,无非就是某些人少些点吗。偷懒的接口而已。
一直觉得汽车是可有可无的东西,无非就是某些人少走些路,偷懒的接口而已。
一直觉得spring, hibernate, struts是可有可无的东西,无非就是某些人少些点吗。偷懒的接口而已。
用这种方式解决问题,好像是传说中的命令模式。
缺点就是复用性差,基本不考虑复用(所以干脆连名字都省了)。
所以这个是属于开发层面的东西,也没啥特别好吹捧的。
饿 我到是有时遇到要多继承时用内部类~ 谁叫java不比c++呢
不过我那样设计是有毛病的~!~
缺点就是复用性差,基本不考虑复用(所以干脆连名字都省了)。
所以这个是属于开发层面的东西,也没啥特别好吹捧的。
大家不就是开发人员吗?所以讨论开发层面的东西很自然,没有吹捧的意思,呵呵。匿名类就是在不需要复用的时候使用的,所以文中的接口Filter和Action都是非常简单的接口。
如果Swing中的一个Action,如果在menu和toolbar中都用到的话,肯定会写成
XAction x = new XAction(),然后分别绑在menuitem和toolbar上。
可能我的表达需要好好练练,我想表达的是,将匿名类作为“一个可以做某种运算的东西(且只做某种运算)”传递给一个集合(或者叫列表),从而完成对一个集合的运算。感觉这个跟LISP的操作方式很有些相似,所以作为一个java中的fp的思考。
缺点就是复用性差,基本不考虑复用(所以干脆连名字都省了)。
所以这个是属于开发层面的东西,也没啥特别好吹捧的。
问题并不是所有的东西都需要复用,如果总是为根本不会复用的东西创建一个类,就显得过于罗嗦了。
缺点就是复用性差,基本不考虑复用(所以干脆连名字都省了)。
所以这个是属于开发层面的东西,也没啥特别好吹捧的。
也对,昨天晚上还有些愤愤的,后来想想,这些内容在经验更丰富,思考更深入的人眼中,又何尝不是入门级的东西呢?不过辛辛苦苦整理出来点东西,被人“轻视”,有点愤愤,也是人之常情,呵呵。
前天开会的时候,突然想到将函数式语言中的“算子”这个概念,跟java中的这个匿名类有点相似,于是散会后就速速几下,昨天又加入了些jQuery的链式操作,觉得这中代码的写法比较有意思,就分享一下。
本意是解释下函数式的编程思想在java中的应用,并不是专门讲匿名类的,帖名可能不够贴切,不过也不至于投我新手吧?
发表评论
-
JavaScript内核系列 第15章 服务器端的JavaScript
2012-02-12 21:39 2214第15章已经在icodeit上发布,这一章分为上/下两篇,请朋 ... -
使用vim开发python及graphviz绘图
2011-12-23 14:49 6341基本需求 使用vim中的autocmd命令可以很容易的将正在 ... -
Java脚本技术应用实例
2011-01-22 11:24 4093前言 一直以来都很喜欢可以自由扩展的软件,这一点应该已经在很 ... -
可编程计算器(phoc)的设计与实现
2011-01-17 11:34 1863前言 借助JavaScript脚本 ... -
函数式编程(javascirpt)
2009-04-18 22:18 1216前言 Javascript,有人称 ... -
C和指针
2009-05-21 23:15 1061前言 指针是C的灵魂,正是指针使得C存在了这么多年,而且将长 ... -
C和指针(续)
2009-05-25 23:41 1317前言 上一篇《C和指针》可能对关于C和指针的有些内容没有说透 ... -
有限自动机与建模
2009-06-06 10:48 1649前言 在学校学程序设计语言的时候,能接触到的所有例子没有一个 ... -
事件和监听器
2009-06-21 22:06 1370前言 事件监听器是经 ... -
基于总线的消息服务(BBMS)的设计与实现
2009-07-25 22:19 1311前言 异步事件的通知机制在比较有规模的软件设计中必然会有涉及 ... -
JavaScript内核系列 第9章 函数式的Javascript
2010-05-13 19:20 3714第九章 函数式的Javascript 要说Ja ... -
JavaScript内核系列 第8章 面向对象的JavaScript(下)
2010-05-06 09:40 3593接上篇:JavaScript内核系列 第8章 面向对象的Jav ... -
JavaScript内核系列 第8章 面向对象的JavaScript(上)
2010-05-06 09:26 2848第八章 面向对象的 Javascript ... -
JavaScript内核系列 第7章 闭包
2010-05-04 08:48 3776第七章 闭包 闭包向来给包括JavaScript程序 ... -
JavaScript内核系列 第6章 正则表达式
2010-04-27 19:44 3945第六章 正则表达式 正则表达式是对字符串的结构 ... -
JavaScript内核系列 第5章 数组
2010-04-24 15:17 4375第五章 数组 JavaScript的数组也是一个比较 ... -
Swing小应用(Todo-List)之三
2010-04-22 20:47 2066前言 去年9月份开发的那个小工具sTodo,只是做到了能用, ... -
JavaScript内核系列 第4章 函数
2010-04-18 17:31 4964第四章 函数 函数,在C语言之类的过程式语言中 ... -
JavaScript内核系列 第3章 对象与JSON
2010-04-12 09:12 6021第三章 对象与JSON JavaScript对象与传 ... -
JavaScript内核系列 第2章 基本概念
2010-04-03 19:44 5522第二章 基本概念 ...
相关推荐
说到底,所有的组件都继承了java.awt.Component类,而handleEvent()就在java.awt.Component类中。 然而,这种模型也存在缺点: - 事件只能由产生这个事件的组件或包含这个组件的容器处理。这个限制违反了面向对象...
匿名内部类编译时,会单独生成一个class文件,该类持有外部类的引用,传入的参数都会自动复制一份。那么传入的参数 与 内部类实际使用的参数就不是相同的一个参数了, 为了避免出现问题,所以规定匿名内部类使用的...
第5章讲解了Android源码中常用的类,如sp、wp、RefBase、Thread类、同步类、Java中的Handler类以及Looper类。这些类都是Android中最常用和最基本的,只有掌握这些类的知识,才 能在分析后续的代码时游刃有余。 ...
3、理解和掌握匿名类的用法。 4、初步了解JDK8新特性和lambda表达式。 二、实验内容和主要步骤 ★专题:继承基础和面向抽象编程★ 1.继承基础实验 2.Object类使用 3.抽象类和抽象方法 4.继承机制实现的多态 ★专题...
2.4.8 JNI中的异常处理 2.5 本章小结 第3章 深入理解init 3.1 概述 3.2 init分析 3.2.1 解析配置文件 3.2.2 解析service 3.2.3 init控制service 3.2.4 属性服务 3.3 本章小结 第4章 深入理解zygote 4.1 概述 4.2 ...
【思考题】 1. 发送广播消息的3中方法是什么? 1) onSendStaticBroadcast(View v); 2) onSendDynamicBroadcast(View v); 3) onSendStickyBroadcast(View v)。 得分(百分制) ----------------------- Android...
Java函数式编程 第一法则:在学习任何新...匿名内部类vs Lambda表达式 默认方法 静态方法() 预定义的功能接口 一个论点已预先确定 谓词 功能 消费者 供应商 预定义的两个论点 双谓词 双功能 双消费 额外的预定义 I
22.1 在Scala代码中使用Java名称 430 22.2 Java泛型与Scala泛型 430 22.3 JavaBean的性质 432 22.4 AnyVal类型与Java原生类型 433 22.5 Java代码中的Scala名称 433 22.6 本章回顾与下一章提要 434 ...
以至于正当Microsoft尽力在Visual J++基础上拓展Java功能,并使之与Windows操作系统紧密结合在一起的时候,Sun公司对Microsoft提出了法律诉讼,控告Microsoft违反了许可证协议中的条款,最终的结果是Microsoft公司...
2.4.8 JNI中的异常处理 / 32 2.5 本章小结 / 32 第3章 深入理解init / 33 3.1 概述 / 34 3.2 init分析 / 34 3.2.1 解析配置文件 / 38 3.2.2 解析service / 42 3.2.3 init控制service / 48 3.2.4 属性服务 / 52 3.3 ...
不再需要匿名线程,不必在一个Activity中启动线程,也不必去思考关于如果用户打开了一个新的活动,完成后会发生什么。 您是否担心onProgressUpdate()中的空指针? 如果用户在线程运行时启动新的活动,会发生什么...
1.1 重新思考Web应用····· 2 1.1.1 应用系统的发展史············· 2 1.1.2 传统Web应用的优势和缺点··············· 4 1.2 重新设计Web应用····· 5 1.2.1 RIA应用·····...
4.4.2exit(3) 在C++ 中不是线程安全的.. . . . . . . . . . . . . . . . 94 4.5善用__thread 关键字.. . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 4.6多线程与IO . . . . . . . . . . . . . . . . ....