Java 库的建立方法及其实例(5)

2008-05-24 05:34:39.0     推荐:0    收藏:0    评论:0     来源:天新网

Java 库的建立方法及其实例(5)


接下来,我们来看看Pattern类的内容。这里有两种方法,一种是直接阅读源代码,另外一种是先用 工具分析一下Pattern类的内容。这里,我采用第二种方法,用javap来看类的内容。


[games]$javap -classpath .. -private jregex.Pattern


Compiled from jregex/Pattern.java


public class jregex.Pattern extends java.lang.Object implements java.io.Serializable, jregex.REFlags {


java.lang.String stringRepr;


jregex.Term root;


jregex.Term root0;


int memregs;


int counters;


int lookaheads;


java.util.Hashtable namedGroupMap;


private jregex.Pattern() throws jregex.PatternSyntaxException;


public jregex.Pattern(java.lang.String) throws jregex.PatternSyntaxException;


public jregex.Pattern(java.lang.String,java.lang.String) throws jregex.PatternSyntaxException;


public jregex.Pattern(java.lang.String,int) throws jregex.PatternSyntaxException;


private void compile(java.lang.String, int) throws jregex.PatternSyntaxException;


public int groupCount();


public java.lang.Integer groupId(java.lang.String);


public jregex.Matcher matcher();


public jregex.Matcher matcher(java.lang.String);


public jregex.Matcher matcher(char[], int, int);


public jregex.Matcher matcher(jregex.MatchResult, int);


public jregex.Matcher matcher(jregex.MatchResult, java.lang.String);


public jregex.Matcher matcher(java.io.Reader, int) throws java.io.IOException;


public jregex.Replacer replacer(java.lang.String);


public jregex.Replacer replacer(jregex.Substitution);


public jregex.RETokenizer tokenizer(java.lang.String);


public jregex.RETokenizer tokenizer(char[], int, int);


public jregex.RETokenizer tokenizer(java.io.Reader, int) throws java.io.IOException;


public java.lang.String toString();


public java.lang.String toString_d();


static int parseFlags(java.lang.String) throws jregex.PatternSyntaxException;


static int parseFlags(char[], int, int) throws jregex.PatternSyntaxException;


private static int getFlag(char) throws jregex.PatternSyntaxException;


}




其中,要关心private和protected成员,因为在使用类的时候,我们只要关心public成员就行了,但 是,要阅读源代码,明白类的构成,就必须注意private和protected成员。


private Pattern() throws PatternSyntaxException{}


public Pattern(String regex) throws PatternSyntaxException{


this(regex,DEFAULT);


}


public Pattern(String regex,String flags) throws PatternSyntaxException{


stringRepr=regex;


compile(regex,parseFlags(flags));


}


public Pattern(String regex, int flags) throws PatternSyntaxException{


stringRepr=regex;


compile(regex,flags);


}




可以看出,构造函数中,有一个缺省的构造函数是private。而第二个调用了最后一个构造函数,用 this()。第三个和最后一个都是用了一个函数compile来完成构造正则表达式的任务。在上面javap的 输出我们也可以看到,compile是一个private函数。


来看看它的说明:


private void compile(String regex,int flags) throws PatternSyntaxException{


Term.makeTree(regex,flags,this);


}


具体到Term类,超出了本文的范围,它采用了hashtable等方法,构造了一个正则表达式,并返回。 而我们关心的是库的结构。从这里我们可以明白一点:构造函数往往需要调用另外一个构造函数来 完成,而不需要把同样的代码在各个构造函数中都实现。同时,也可以采用另外一个private函数来 完成构造函数的功能,而只要在构造函数中调用它就行了。


从Matcher API说明文档中,我们可以看到,有两种通过Pattern实例构造Matcher实例的方法,而在 javap的输出中可以看到,有几种不同的matcher函数。


public Matcher matcher(){


return new Matcher(this);


}


public Matcher matcher(String s){


Matcher m=new Matcher(this);


m.setTarget(s);


return m;


}


public Matcher matcher(char[] data,int start,int end){


Matcher m=new Matcher(this);


m.setTarget(data,start,end);


return m;


}


public Matcher matcher(MatchResult res,int groupId){


Matcher m=new Matcher(this);


if(res instanceof Matcher){


m.setTarget((Matcher)res,groupId);


}


else{


m.setTarget(res.targetChars(),res.start(groupId)+res.targetStart(),res.length(groupId));


}


return m;


}


public Matcher matcher(Reader text,int length)throws IOException{


Matcher m=new Matcher(this);


m.setTarget(text,length);


return m;


}


以上都是用来实现第一种返回matcher的方法。可以看到,这几种实现都是通过new Matcher实例, 以this(即Pattern实例)为参数,然后根据参数不同调用Matcher.setTarget()方法。


public Matcher matcher(MatchResult res,String groupName){


Integer id=res.pattern().groupId(groupName);


if(id==null) throw new IllegalArgumentException("group not found:"+groupName);


int group=id.intValue();


return matcher(res,group);


}


这是第二种返回matcher的方法。


从这里我们可以发现一种比较好的方法:当你需要两个互相关联的类,一个类的实例需要构造另一 个类的实例,可以在第一个类中用一个public方法,方法实现为调用第二个类的构造函数,并可以 用构造出来的实例调用其他方法,根据第一个类的实例的数据来设置第二个类的实例。


同样的,也有Replacer, 和Tokenizer的构造方法。


public Replacer replacer(String expr){


return new Replacer(this,expr);


}




/**


* Returns a replacer will substitute all occurences of a pattern


* through applying a user-defined substitution model.


* @param model a Substitution object which is in charge for match substitution


* @see Replacer


*/


public Replacer replacer(Substitution model){


return new Replacer(this,model);


}


public RETokenizer tokenizer(String text){


return new RETokenizer(this,text);


}




/**


* Tokenizes a specified region by an occurences of the pattern.


* Note that a series of adjacent matches are regarded as a single separator.


* The same as new RETokenizer(Pattern,char[],int,int);


* @see RETokenizer


* @see RETokenizer#RETokenizer(jregex.Pattern,char[],int,int)


*/


public RETokenizer tokenizer(char[] data,int off,int len){


return new RETokenizer(this,data,off,len);


}




/**


* Tokenizes a specified region by an occurences of the pattern.


* Note that a series of adjacent matches are regarded as a single separator.


* The same as new RETokenizer(Pattern,Reader,int);


* @see RETokenizer


* @see RETokenizer#RETokenizer(jregex.Pattern,java.io.Reader,int)


*/


public RETokenizer tokenizer(Reader in,int length) throws IOException{


return new RETokenizer(this,in,length);


}




回忆一下,我在本文的开头,曾经提到过:"一个好的库必须是一个紧凑的关系紧密的整体,而不 是一个分散的关系松散的对象的集合。"从API说明文档所显示的这个库的树形结构,并不能看出这 些类之间的联系。而从源代码的角度,我们则可以清楚地看到这一点。在这一部分的讨论中,我们 也明白了两点:


1、如何编写重载构造函数


2、在一个类的实例中返回另外一个类的实例 (未完待续)


您可以针对本文进行:[评论]  [收藏]  [推荐]   [查看原文链接]  
  • 共有0条评论  点击查看更多评论
  • 网友评论仅供网友表达个人看法,并不表明e800同意其观点或证实其描述
我想发表评论:
用户名密码
  • 匿名发表
    验证码: