对Java中匿名类的一些思考

2009-12-04
对Java中匿名类的一些思考
关键字: 对java中匿名类的一些思考
引言
Java中的匿名类是比较有意思的一种编程方式,在swing中关于监听器的注册时,经常可见到这样的代码:

Java代码
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);}
}
});
Java代码
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);}
}
});

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这个菜单项,需要一个动作监听器,如果用常规写法,大概如此:

Java代码
class XListener implements ActionListener{
public void actionPerformed(ActionEvent e){
//action here
}
}
XListener l = new XListener();
iexit.addActionListener(l);
Java代码
class XListener implements ActionListener{
public void actionPerformed(ActionEvent e){
//action here
}
}
XListener l = new XListener();
iexit.addActionListener(l);

class XListener implements ActionListener{
public void actionPerformed(ActionEvent e){
//action here
}
}
XListener l = new XListener();
iexit.addActionListener(l);
虽然完成了同样的工作,但是代码量明显比刚才要多。

实例
在javascript,或者其他函数式编程语言中,常常可以见到诸如此类的写法:

Js代码
$("#element").click(function(){
//do something
});

$("div.type").each(function(index){
//do something else with the index
});
Js代码
$("#element").click(function(){
//do something
});

$("div.type").each(function(index){
//do something else with the index
});

$("#element").click(function(){
//do something
});

$("div.type").each(function(index){
//do something else with the index
}); 将一个匿名函数传递给另一个函数,实现一些列定制的动作,正好工作中有个地方要用到类似的东东,就用java的匿名类实现了一套类似的机制:

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;
}
});
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;
}
});

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值来对最终结果做过滤:

Java代码
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);
}
Java代码
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);
}

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):

Java代码
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();
}
Java代码
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();
}

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,为另一个接口,同样会被很多的匿名类使用到:

Java代码
package org.free.fplist;

public interface Action {
public Object doAction(Object item);
}
Java代码
package org.free.fplist;

public interface Action {
public Object doAction(Object item);
}

package org.free.fplist;

public interface Action {
public Object doAction(Object item);
}


好了,我们现在来看一个FPable的实现FPList,FPList继承了LinkedList,并且实现了FPable,可以对其中的数据进行过滤(前提是传入一个过滤器 ),或者对其中的元素进行映射(传入一个动作 ),FPList会自动的将过滤器和动作作用到List中的每一个元素。



Java代码
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));
}
}
}
Java代码
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));
}
}
}

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就提供这样的能力。



Java代码
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;
}
});

}
}
Java代码
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;
}
});

}
}

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 : Apple, co
index : 0, content : 50
index : 1, content : 100
index : 2, content : 150
index : 3, content : 500
abruzzi
jet.lee


上边的例子显示,匿名类在接口 中的方法不多的时候,整个匿名类整体作为一个对象传递给另外一个方法,可以很好的做到可定制性。比如第三个例子,使用Person bean的时候,可以定制多个过滤条件,依次将原始列表过滤成一个符合要求的列表。



另,文章中用到了比较多的函数式编程的概念,虽然java原生不支持,但是函数式编程作为一种思想,肯定可以在命令式的程序设计中有所体现。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值