??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲视频一区调教,久久久久亚洲AV无码专区网站 ,久久久久亚洲av成人无码电影http://www.tkk7.com/dyerac/category/13594.htmldyerac 的天天天?/description>zh-cnTue, 14 Aug 2007 16:19:02 GMTTue, 14 Aug 2007 16:19:02 GMT60手动创徏一个新Classhttp://www.tkk7.com/dyerac/archive/2007/08/13/136473.htmldyerac in java...dyerac in java...Mon, 13 Aug 2007 10:52:00 GMThttp://www.tkk7.com/dyerac/archive/2007/08/13/136473.htmlhttp://www.tkk7.com/dyerac/comments/136473.htmlhttp://www.tkk7.com/dyerac/archive/2007/08/13/136473.html#Feedback0http://www.tkk7.com/dyerac/comments/commentRss/136473.htmlhttp://www.tkk7.com/dyerac/services/trackbacks/136473.html
public class NewMain {
    public static void main(String[] args) {
        new Object();
    }
}

用javap反编译上面的代码Q我们可以得C面的指oQ这里省Mjavac暗中创徏的构造函数?br>
public class NewMain extends java.lang.Object{
    ...
public static void main(java.lang.String[]);
  Code:
   0:   new     #3; //class java/lang/Object
   3:   invokespecial   #8; //Method java/lang/Object."<init>":()V
   6:   return
}

从这D代码中Q我们可以清晰的看出创徏对象QnewQ和调用构造函敎ͼinvokespecialQ两个过E。关于这个问题,我在?a target=_blank>对象的生?/font>》中曄q行q讨论?br>
既然javac一个new的动作被解释Z条指令,那在JVM的层面上Q我们当然就可以它们分开。下面是一D|什么实际用途的代码Q只是证明这个观点可行性?br>
public class NewGenerator {
    public static void main(String[] args) throws Exception {
        String className = "New";
        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
        cw.visit(Opcodes.V1_2, Opcodes.ACC_PUBLIC, className, null, "java/lang/Object", null);
        Method m = Method.getMethod("void main (String[])");
        GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, m, null, null, cw);
        mg.newInstance(Type.getType(Object.class));
        Label label = mg.newLabel();
        mg.ifNonNull(label);
        mg.mark(label);
        mg.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
        mg.push("new object is not null");
        mg.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println(java.lang.String)"));
        mg.pop();
        mg.returnValue();
        mg.endMethod();
        cw.visitEnd();

        OutputStream os = null;
        try {
            os = new FileOutputStream(className + ".class");
            os.write(cw.toByteArray());
        } finally {
            if (os != null) {
                os.close();
            }
        }
    }
}

q段代码生成的类是能够运行的Q有兴趣的可以自p一下。这D代码的作用是newZ个对象之后,如果q个对象非空的话Q就会生一个输出:
    new object is not null

当然Q如果尝试用q个对象做一些其它的操作Q会有错误等待着我们Q因个对象ƈ不是一个完整的对象。在JVM规范中有相关的解释:new指oq不能完整创建出一个新的对象,直到Ҏ初始化的对象调用了实例初始化Ҏ才会完成实例的创建。这D代码也正好W合?a target=_blank>对象的生?/font>》中的解释,它只是负责做出申请内存。当Ӟ在JVM中,它的实际工作要略多一些,如果q个对象的类没有加蝲Q就会加载相应的cR?br>

]]>
动态代?Dynamic ProxyQJava Servlet http://www.tkk7.com/dyerac/archive/2007/07/24/132051.htmldyerac in java...dyerac in java...Tue, 24 Jul 2007 07:10:00 GMThttp://www.tkk7.com/dyerac/archive/2007/07/24/132051.htmlhttp://www.tkk7.com/dyerac/comments/132051.htmlhttp://www.tkk7.com/dyerac/archive/2007/07/24/132051.html#Feedback0http://www.tkk7.com/dyerac/comments/commentRss/132051.htmlhttp://www.tkk7.com/dyerac/services/trackbacks/132051.html基本上了解了动态代理的机制
差写个代码实验一?br>

------------------------------------------------------------------------------------------------------------------------


从JDK1.3开始,Java引入了动态代理的概念。动态代理(Dynamic ProxyQ可以帮助你减少代码行数Q真正提高代码的可复用度。例如,你不必ؓ所有的cȝҎ里面都写上相同的Log代码行,取而代之的是实用类的动态代理类。当Ӟq种便利是有条g的。本文简单介lJava动态代理的原理Qƈ实现一个被代理的Servlet创徏Q和调用的过E?
 
1Q?/span>代理模式QProxy PatternQ?/div>
在JDK1.3以前Q代理模式就已流行,所以得代理模式是生成一个和cȝ同接口的代理c,用户通过使用代理cL装某个实现cR如?Q其目的是加强实现类的某个方法的功能Q而不必改变原有的源代码?/div>

2Q?/span>动态代理(Dynamic ProxyQ?/div>
随着Proxy的流行,Sun把它U_到JDK1.3实现了Java的动态代理。动态代理和普通的代理模式的区别,是动态代理中的代理类是由java.lang.reflect.Proxycdq行期时Ҏ接口定义Q采用Java反射功能动态生成的。和java.lang.reflect.InvocationHandlerl合Q可以加强现有类的方法实现。如?Q图中的自定义Handler实现InvocationHandler接口Q自定义Handler实例化时Q将实现cM入自定义Handler对象。自定义Handler需要实现invokeҎQ该Ҏ可以使用Java反射调用实现cȝ实现的方法,同时当然可以实现其他功能Q例如在调用实现cL法前后加入Log。而ProxycL据Handler和需要代理的接口动态生成一个接口实现类的对象。当用户调用q个动态生成的实现cLQ实际上是调用了自定义Handler的invokeҎ?/div>
  

3Q动态代理Servlet
              虽然Web Application Server的品很多,但Servlet的处理原理是怼的:动态加载ServletQ调用Servlet的initҎQ只被调用一ơ)Qƈ保存到Servlet容器QServlet使用Ӟ调用Servlet的serviceҎ。本文动态代理Servlet接口Q其init和service被调用时会在控制台打出方法调用前后信息?/div>
首先实现2个ServletQDefaultServlet和UserServlet
 
package org.colimas.servlet;
 
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
 
public class DefaultServlet extends HttpServlet implements Servlet {
              public void init() throws ServletException {
                            super.init();
                            System.out.println(DefaultServlet.class.getName()+":Running init");
              }
 
              public String getServletInfo() {
                            return DefaultServlet.class.getName();
              }
}
 
package org.colimas.servlet;
 
import java.io.IOException;
 
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
 
public class UserServlet extends HttpServlet implements Servlet {
 
              private static final long serialVersionUID = -7016554795165038652L;
             
              public void init() throws ServletException {
                            super.init();
                            System.out.println(UserServlet.class.getName()+":Running init");
              }
              protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                                         
                            System.out.println(UserServlet.class.getName()+":Do UserSErvlet Get");
              }
              public String getServletInfo() {
                            return UserServlet.class.getName();
              }            
             
 
}
 
然后实现InvocationHandler
package org.colimas.webapp;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
 
import javax.servlet.Servlet;
 
public class ServletHandler implements InvocationHandler {
 
              private Servlet obj;
             
              public ServletHandler(Servlet obj){
                            this.obj=obj;
              }
              public Object invoke(Object arg0, Method arg1, Object[] arg2)
                                          throws Throwable {
                           
                            if(arg1.getName().compareTo("init")==0) //调用init?/div>
                            {
                                          System.out.println(obj.getServletInfo()+":Init servlet starting..."); //增加控制台输出?/div>
                                          arg1.invoke(obj,arg2); //调用initҎ
                                          System.out.println(obj.getServletInfo()+":Init servlet ending..."); //增加控制台输出?/div>
                            }else if(arg1.getName().compareTo("service")==0){ //调用service?/div>
                                          System.out.println(obj.getServletInfo()+":service starting..."); //增加控制台输出?/div>
 
                                          arg1.invoke(obj,arg2); //调用serviceҎ?/div>
                                          System.out.println(obj.getServletInfo()+":service ending..."); //增加控制台输出?/div>
                           
                            }
                            return null;
              }
 
}
 
实现Servlet的调?/div>
package org.colimas.webapp;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
 
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
 
public class ServletWrapperImp {
   
    private Class servletClass;
    private ServletConfig config;
    private String _servletname;
    private Servlet _theServlet;
              private ServletContext context;
    public ServletWrapperImp(ServletConfig config){
           this.config=config;
           this._servletname=this.config.getServletName();
           this.context=this.config.getServletContext();
    }
   
    public Servlet getServlet() throws ServletException{
 
                              destroy();
                              try {
                                            WebAppClassLoader loader=new WebAppClassLoader(this.getClass().getClassLoader()); //自定义class loader
                                            String name=getServletName(); //从ServletConfig中获得Servlet Name
                                            synchronized (context) {
                                                          Servlet theServlet=context.getServlet(name); //在ServletContext中查找Servlet
                                                          if(theServlet==null){         //如果ServletContext没有?span>              
                                                                        servletClass = loader.loadClass(name); //由Class loader 加蝲Servlet class?/div>
                                                              theServlet = (Servlet) servletClass.newInstance(); //Servlet实例化?/div>
                                                              WebAppContext.addServlet(name,theServlet); //Servlet实例存入ServletContext?/div>
                                                                        InvocationHandler handler=new ServletHandler(theServlet); //自定义ServletHandlerQ参见ServletHandlercR?/div>
                                                                        _theServlet=(Servlet)Proxy.newProxyInstance(theServlet.getClass().getClassLoader(),
                                                                                   new Class[]{Servlet.class},handler); //代理cd例化?/div>
                                                                        _theServlet.init(config); //Servlet代理对象调用initҎ。参见ServletHandler的invokeҎ?/div>
                                                                       
                                                          }else{ //ServletContext里已存在?/div>
                                                                        InvocationHandler handler=new ServletHandler(theServlet); //自定义ServletHandlerQ参见ServletHandlercR?/div>
                                                                        _theServlet=(Servlet)Proxy.newProxyInstance(theServlet.getClass().getClassLoader(),
                                                                                   new Class[]{Servlet.class},handler);                 //代理Servlet接口Q动态生成代理类Qƈ实例化?span>                                  
                                                          }
                                            }
                                            return _theServlet; //q回Servlet代理对象
                              } catch( ClassNotFoundException ex1 ) {
                                
                              } catch( InstantiationException ex ) {
                                 
                              }catch(IllegalAccessException ex2){
                                           
                              }
                      return null;
    }
    public void destroy() {
        if (_theServlet != null) {
                      _theServlet.destroy();
        }
    }   
   
    protected String getServletName(){
           return _servletname;
    }
}
 
其中的ServletConfig保存Servlet相关信息。ServletContext保存所有的Servlet对象。WebAppClassLoader定义class loader,参见http://blog.csdn.net/tyrone1979/archive/2006/09/03/1164262.aspx?/div>
 
最后编写测试类MainQ该cL?0个用戯问ServletQ?问DefaultServletQ?问UserServlet?/div>
package org.colimas.main;
 
import java.io.IOException;
 
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
 
import org.colimas.webapp.HttpServletRequestWrapper;
import org.colimas.webapp.HttpServletResponseWrapper;
import org.colimas.webapp.ServletConfigImpl;
import org.colimas.webapp.ServletWrapper;
import org.colimas.webapp.ServletWrapperImp;
import org.colimas.webapp.WebAppContext;
 
public class Main {
 
              private ThreadGroup _threadGroup;
              private Thread[] _threads;
              String defaultServletName="org.colimas.servlet.DefaultServlet";
              String userServletName="org.colimas.servlet.UserServlet";
              WebAppContext context=WebAppContext.newInstance();     
             
              public void doStart(){
             
                            _threadGroup=new ThreadGroup("SERVLETS");
                            int i=0;
                            _threads=new ServletThread[10]; //模拟10位用戗?/div>
                            for(i=0;i<5;i++){
                                          _threads[i]=new ServletThread(_threadGroup,new Integer(i).toString(),
                                                                      defaultServletName);
                                          _threads[i].start();
                            }
                            for(i=5;i<10;i++){
                                          _threads[i]=new ServletThread(_threadGroup,new Integer(i).toString(),
                                                                      userServletName);
                                          _threads[i].start();
                            }                          
                           
              }
              /**
               * @param args
               */
              public static void main(String[] args) {
                            Main _main=new Main();
                            _main.doStart();
                           
              }
              //模拟用户U程
              private class ServletThread extends Thread{
                           
                            private String servletName;
                           
                            public ServletThread(ThreadGroup group,String threadname,String servletname){
                                          super(group,threadname);
                                          servletName=servletname;
                            }
                            //调用Servlet的service.
                            public void run() { //用户调用Servlet
                                          ServletConfig config=new ServletConfigImpl(servletName,context); //调用的Servlet信息?/div>
                                          ServletWrapperImp wrapper=new ServletWrapperImp(config);
                                          try {
                                                        Servlet defaultServlet=wrapper.getServlet(); //获得Servlet对象Q实际是Servlet的代理对?/div>
                                                        defaultServlet.service(new HttpServletRequestWrapper(),
                                                                                    new HttpServletResponseWrapper()); 调用代理对象的serviceҎQ参见ServletHandler的invokeҎ?/div>
                                          } catch (ServletException e) {
                                                                                                                e.printStackTrace();
                                          } catch(IOException e){
                                                       
                                          }
                            }
                           
              }
}
HttpServletRequestWrapper和HttpServletResponseWrapper实现HttpServletRequestQ和HttpServletResponse?/div>
试l果如下
org.colimas.servlet.DefaultServlet:Init servlet starting...
org.colimas.servlet.DefaultServlet:Running init
org.colimas.servlet.DefaultServlet:Init servlet ending...
org.colimas.servlet.UserServlet:Init servlet starting...
org.colimas.servlet.UserServlet:Running init
org.colimas.servlet.UserServlet:Init servlet ending...
org.colimas.servlet.DefaultServlet:service starting...
org.colimas.servlet.DefaultServlet:service ending...
org.colimas.servlet.DefaultServlet:service starting...
org.colimas.servlet.DefaultServlet:service ending...
org.colimas.servlet.UserServlet:service starting...
org.colimas.servlet.UserServlet:Do UserSErvlet Get
org.colimas.servlet.UserServlet:service ending...
org.colimas.servlet.UserServlet:service starting...
org.colimas.servlet.UserServlet:Do UserSErvlet Get
org.colimas.servlet.UserServlet:service ending...
org.colimas.servlet.UserServlet:service starting...
org.colimas.servlet.UserServlet:Do UserSErvlet Get
org.colimas.servlet.UserServlet:service ending...
org.colimas.servlet.UserServlet:service starting...
org.colimas.servlet.DefaultServlet:service starting...
org.colimas.servlet.UserServlet:service starting...
org.colimas.servlet.DefaultServlet:service starting...
org.colimas.servlet.DefaultServlet:service starting...
org.colimas.servlet.UserServlet:Do UserSErvlet Get
org.colimas.servlet.DefaultServlet:service ending...
org.colimas.servlet.UserServlet:Do UserSErvlet Get
org.colimas.servlet.DefaultServlet:service ending...
org.colimas.servlet.DefaultServlet:service ending...
org.colimas.servlet.UserServlet:service ending...
org.colimas.servlet.UserServlet:service ending...
 
2个ServletW一ơLoad时初始化Q被调用initQ之后保存到ServletContext中。第二次直接从ServletContext获得Q执行service。红字表CZ理类里增加的输出l果?/div>
 
4Q动态代理的限制
              JDK的动态代理ƈ不能随心所Ʋ的代理所有的cRProxy.newProxyInstanceҎ的第二个参数只能是接口数l, 也就是Proxy只能代理接口?/div>

 



]]>动态代?包装器模?/title><link>http://www.tkk7.com/dyerac/archive/2007/07/24/132037.html</link><dc:creator>dyerac in java...</dc:creator><author>dyerac in java...</author><pubDate>Tue, 24 Jul 2007 06:03:00 GMT</pubDate><guid>http://www.tkk7.com/dyerac/archive/2007/07/24/132037.html</guid><wfw:comment>http://www.tkk7.com/dyerac/comments/132037.html</wfw:comment><comments>http://www.tkk7.com/dyerac/archive/2007/07/24/132037.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/dyerac/comments/commentRss/132037.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/dyerac/services/trackbacks/132037.html</trackback:ping><description><![CDATA[<p>转的q篇文章虽然是讲动态代理的<br>但是其中涉及CDecorator模式 也是一个学习的亮点<br><br><br><br><br>-----------------------------------------------------------------------------------------------------<br>记忆是衍生自Lisp,Python,和Perl{过E性语a的一U设计模式,它可以对前次的计结果进行记忆?nbsp;一个实C记忆功能的函? 带有昑ּ的cache, 所? 已经计算q的l果p直接从cache中获? 而不用每ơ都q行计算.<br>记忆能显著的提升大计量代码的效? 而且是一U可重用的方?<br>本文阐述了在Java中用这一模式的方?q提供了一个可以提供上q功能的"记忆c?:<br>     Foo foo = (Foo) Memoizer.memoize(new FooImpl());<br>     q里,Foo是一个接?它含有的Ҏ是需要记忆的.FooImpl是Foo的一个实?foo是Foo的一个引?Ҏ与FooImpl基本相同,区别在于Fooq回的?会被~存h.单个记忆cȝ优点在于ZQ何类d记忆功能是很单的:定义一个包含需要记忆的Ҏ的接?然后调用memoize来实C个实?<br><br>    Z理解记忆cL怎么实现?我们分几步来解?首先,我解释一下ؓ何缓存能够在需要它的类中实?然后,我测试一下如何ؓ一个特定的cL加缓存包装器.最?我解释一下如何才能得一个缓存包装器能够通用于Q意的c?<br><br><strong>为大计算量的E序d~存</strong><br>    作ؓ一个大计算量程序的例子,我们考虑PiBinaryDigitsCalculatorq个例子-计算二进制数据pi.仅有的publicҎcalculateBinaryDigit带有一个参?整数n,代表需要精到的位?例如,1000000,会q回数点后的一百万?通过byteD?每位?或?.(法可以参? <a target=_blank><font color=#002c99><u>http://www.cecm.sfu.ca/~pborwein/PAPERS/P123.pdf</u></font></a>)<br><br><code>public class PiBinaryDigitsCalculator {<br>  /**<br>   * Returns the coefficient of 2^n in the binary<br>   * expansion of pi.<br>   * @param n the binary digit of pi to calculate.<br>   * @throws ValidityCheckFailedException if the validity<br>   * check fails, this means the implementation is buggy<br>   * or n is too large for sufficient precision to be<br>   * retained.<br>   */<br>  public byte calculateBinaryDigit(final int n) {<br>      return runBBPAlgorithm(n);<br>  }<br>    <br>  private byte runBBPAlgorithm(final int n) {<br>      // Lengthy routine goes here ...<br>  }<br><br>}</code><br>    最单直接的Ҏ来缓存返回值可以通过修改q个cL实现:d一个Map来保存之前计得到的?如下:<br><code>import java.util.HashMap;<br><br>public class PiBinaryDigitsCalculator {<br><br>  private HashMap cache = new HashMap();<br><br>  public synchronized byte calculateBinaryDigit(<br>  final int n) {<br><br>      final Integer N = new Integer(n);<br>      Byte B = (Byte) cache.get(N);<br>      if (B == null) {<br>          byte b = runBBPAlgorithm(n);<br>          cache.put(N, new Byte(b));<br>          return b;<br>      } else {<br>          return B.bytevalue();<br>      }<br>  }<br><br>  private byte runBBPAlgorithm(final int n) {<br>      // Lengthy routine goes here ...<br>  }<br>}</code><br> <br>    calculateBinaryDigitҎ首先会检查HashMap里面是否~存了这个关键字-参数n,如果扑ֈ?q接返回这个?否则,׃q行q个冗长的计?q将l果保存到缓存里?在添加进HashMap的时?在原始类型和对象之间q要q行小的{?<br>    管q个Ҏ是可行的,但是有几个缺?首先,q行~存的代码和正常的算法代码不是显著分开?一个类,不仅负责q行计算,也要负责q行l护~存数据.q样,要进行一些测试就会显得很困难.比如,不能写一个测试程序来试q个法持箋地返回相同的?因ؓ,从第二次开?l果都是直接从cache中获得了.<br>    其次,当缓存代码不再需?U除它会变得困难,因ؓ它和法块地代码是紧密结合在一L.所?要想知道~存是否带来了很高的效率提升也是很困隄,因ؓ不能写一个测试程序是和缓存数据分开?当你改进了你的算?~存有可能失?但是q个时候你q不知道.<br>    W三,~存代码不能被重?管代码遵从了一个普通的模式,但是都是在一个类- PiBinaryDigitsCalculator里面.<br><br>    前面两个问题都可以通过构造一个缓存包装器来解?<br><br><strong style="COLOR: #993366">~存包装?/strong><br>    通过使用Decorator模式,要分开计算代码和缓存代码是很容易的.首先,定义一个接?里面定义基本的方?<br>     <code>public interface BinaryDigitsCalculator {<br><br>  public byte calculateBinaryDigit(final int n);<br>}</code><br>    <br><br>    <span style="COLOR: #ff0000">然后定义两个实现,分别负责两个d:</span><br><code>public class PiBinaryDigitsCalculator<br>  implements BinaryDigitsCalculator {<br><br>  public byte calculateBinaryDigit(final int n) {<br>      return runBBPAlgorithm(n);<br>  }<br><br>  private byte runBBPAlgorithm(final int n) {<br>      // Lengthy routine goes here ...<br>  }<br><br>}<br><br>import java.util.HashMap;<br><br>public class CachingBinaryDigitsCalculator implements<br>BinaryDigitsCalculator {<br><br>  private BinaryDigitsCalculator binaryDigitsCalculator;<br>  private HashMap cache = new HashMap();<br><br>  public CachingBinaryDigitsCalculator(<br>  BinaryDigitsCalculator calculator) {<br>      this.binaryDigitsCalculator = calculator;<br>  }<br><br>  public synchronized byte calculateBinaryDigit(int n) {<br>      final Integer N = new Integer(n);<br>      Byte B = (Byte) cache.get(N);<br>      if (B == null) {<br>          byte b =<br>            binaryDigitsCalculator.calculateBinaryDigit(n);<br>          cache.put(N, new Byte(b));<br>          return b;<br>      } else {<br>          return B.bytevalue();<br>      }<br>  }<br>}</code><br>    <br>    q是很之前的实现PiBinaryDigitsCalculator的一U简单的refactored版本. CachingBinaryDigitsCalculator包装了BinaryDigitsCalculator句柄,q增加了~存,供calculateBinaryDigit的方法调? q种Ҏ提高了代码的可读性与可维护? 用户不能直接使用BinaryDigitsCalculator接口来实现算?所?如果需要关闭缓存块,是很容易实现的.<br>    q有,合适的试E序很容易写出来.比如,我们写一个假的BinaryDigitsCalculator实现,每次calculateBinaryDigit被调?赋予相同的参?q回不同的? q样,我们p试~存是否工作?因ؓ如果每次都返回相同的?则证明缓存是正常工作? q种试在之前那U简单的实现是不可能?<br><br>q是很之前的实现PiBinaryDigitsCalculator的一U简单的refactored版本. CachingBinaryDigitsCalculator包装了BinaryDigitsCalculator句柄,q增加了~存,供calculateBinaryDigit的方法调? q种Ҏ提高了代码的可读性与可维护? 用户不能直接使用BinaryDigitsCalculator接口来实现算?所?如果需要关闭缓存块,是很容易实现的.<br><br>    q有,合适的试E序很容易写出来.比如,我们写一个假的BinaryDigitsCalculator实现,每次calculateBinaryDigit被调?赋予相同的参?q回不同的? q样,我们p试~存是否工作?因ؓ如果每次都返回相同的?则证明缓存是正常工作? q种试在之前那U简单的实现是不可能的?br>通过动态代理类来创Z个通用的缓存包装器\r<br><br>    上面W二U方法仅有的~点是~存包装器不能重?每次我们希望d一个缓存给某个c?我们p写一个特D的~存包装器给目标接口.q是一个很?Ҏ出错的过E?<br><br>    Jdk1.3开始支持动态代理类: 特别的类能够在运行期军_实现哪个接口-通常的模式都?在运行期卛_定实现哪个接?通过q个,我们有可能实C个通用的缓存包装器,我们U它为Memoizer,在运行期军_实现哪个接口.q样, CachingBinaryDigitsCalculator是不再需要的.它是q样被调用的:<br><br>BinaryDigitsCalculator calculator =<br>new CachingBinaryDigitsCalculator(<br>new PiBinaryDigitsCalculator()<br>);  <br><br>    可以通过Memoizer来重写如?<br><br>BinaryDigitsCalculator calculator =<br>(BinaryDigitsCalculator) Memoizer.memoize(<br>new PiBinaryDigitsCalculator()<br>);<br><br>Memoizer的代码如?<br></p> <div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: #0000ff">package</span><span style="COLOR: #000000"> demo.proxy;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top><br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.lang.reflect.InvocationHandler;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.lang.reflect.InvocationTargetException;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.lang.reflect.Method;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.lang.reflect.Proxy;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.Arrays;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.Collections;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.HashMap;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.List;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.util.Map;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/None.gif" align=top><br><img id=Codehighlighter1_361_1538_Open_Image onclick="this.style.display='none'; Codehighlighter1_361_1538_Open_Text.style.display='none'; Codehighlighter1_361_1538_Closed_Image.style.display='inline'; Codehighlighter1_361_1538_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_361_1538_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_361_1538_Closed_Text.style.display='none'; Codehighlighter1_361_1538_Open_Image.style.display='inline'; Codehighlighter1_361_1538_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> Memorizer </span><span style="COLOR: #0000ff">implements</span><span style="COLOR: #000000"> InvocationHandler </span><span id=Codehighlighter1_361_1538_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_361_1538_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_409_543_Open_Image onclick="this.style.display='none'; Codehighlighter1_409_543_Open_Text.style.display='none'; Codehighlighter1_409_543_Closed_Image.style.display='inline'; Codehighlighter1_409_543_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_409_543_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_409_543_Closed_Text.style.display='none'; Codehighlighter1_409_543_Open_Image.style.display='inline'; Codehighlighter1_409_543_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">static</span><span style="COLOR: #000000"> Object memorize(Object object) </span><span id=Codehighlighter1_409_543_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_409_543_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> Proxy.newProxyInstance(object.getClass().getClassLoader(),<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>                object.getClass().getInterfaces(), </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Memorizer(object));<br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> Object object;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> Map caches </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> HashMap();<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_643_670_Open_Image onclick="this.style.display='none'; Codehighlighter1_643_670_Open_Text.style.display='none'; Codehighlighter1_643_670_Closed_Image.style.display='inline'; Codehighlighter1_643_670_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_643_670_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_643_670_Closed_Text.style.display='none'; Codehighlighter1_643_670_Open_Image.style.display='inline'; Codehighlighter1_643_670_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> Memorizer(Object object) </span><span id=Codehighlighter1_643_670_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_643_670_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>        </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.object </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> object;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> Object invoke(Object proxy, Method method, Object[] args)<br><img id=Codehighlighter1_759_1125_Open_Image onclick="this.style.display='none'; Codehighlighter1_759_1125_Open_Text.style.display='none'; Codehighlighter1_759_1125_Closed_Image.style.display='inline'; Codehighlighter1_759_1125_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_759_1125_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_759_1125_Closed_Text.style.display='none'; Codehighlighter1_759_1125_Open_Image.style.display='inline'; Codehighlighter1_759_1125_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>            </span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> Throwable </span><span id=Codehighlighter1_759_1125_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_759_1125_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000"> Don't cache void methods</span><span style="COLOR: #008000"><br><img id=Codehighlighter1_839_875_Open_Image onclick="this.style.display='none'; Codehighlighter1_839_875_Open_Text.style.display='none'; Codehighlighter1_839_875_Closed_Image.style.display='inline'; Codehighlighter1_839_875_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_839_875_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_839_875_Closed_Text.style.display='none'; Codehighlighter1_839_875_Open_Image.style.display='inline'; Codehighlighter1_839_875_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (method.getReturnType().equals(Void.TYPE)) </span><span id=Codehighlighter1_839_875_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_839_875_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> invoke(method, args);<br><img id=Codehighlighter1_882_1122_Open_Image onclick="this.style.display='none'; Codehighlighter1_882_1122_Open_Text.style.display='none'; Codehighlighter1_882_1122_Closed_Image.style.display='inline'; Codehighlighter1_882_1122_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_882_1122_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_882_1122_Closed_Text.style.display='none'; Codehighlighter1_882_1122_Open_Image.style.display='inline'; Codehighlighter1_882_1122_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>        }</span></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span id=Codehighlighter1_882_1122_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_882_1122_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            Map cache </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> getCache(method);<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            List key </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> Arrays.asList(args);<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            Object value </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> cache.get(key);<br><img id=Codehighlighter1_1035_1101_Open_Image onclick="this.style.display='none'; Codehighlighter1_1035_1101_Open_Text.style.display='none'; Codehighlighter1_1035_1101_Closed_Image.style.display='inline'; Codehighlighter1_1035_1101_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1035_1101_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1035_1101_Closed_Text.style.display='none'; Codehighlighter1_1035_1101_Open_Image.style.display='inline'; Codehighlighter1_1035_1101_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>            </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (value </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">&&</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">!</span><span style="COLOR: #000000">cache.containsKey(key)) </span><span id=Codehighlighter1_1035_1101_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_1035_1101_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>                value </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> invoke(method, args);<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>                cache.put(key, value);<br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>            }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> value;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>        }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_1198_1327_Open_Image onclick="this.style.display='none'; Codehighlighter1_1198_1327_Open_Text.style.display='none'; Codehighlighter1_1198_1327_Closed_Image.style.display='inline'; Codehighlighter1_1198_1327_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1198_1327_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1198_1327_Closed_Text.style.display='none'; Codehighlighter1_1198_1327_Open_Image.style.display='inline'; Codehighlighter1_1198_1327_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> Object invoke(Method method, Object[] args) </span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> Throwable </span><span id=Codehighlighter1_1198_1327_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_1198_1327_Open_Text><span style="COLOR: #000000">{<br><img id=Codehighlighter1_1206_1249_Open_Image onclick="this.style.display='none'; Codehighlighter1_1206_1249_Open_Text.style.display='none'; Codehighlighter1_1206_1249_Closed_Image.style.display='inline'; Codehighlighter1_1206_1249_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1206_1249_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1206_1249_Closed_Text.style.display='none'; Codehighlighter1_1206_1249_Open_Image.style.display='inline'; Codehighlighter1_1206_1249_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>        </span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"> </span><span id=Codehighlighter1_1206_1249_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_1206_1249_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> method.invoke(object, args);<br><img id=Codehighlighter1_1287_1324_Open_Image onclick="this.style.display='none'; Codehighlighter1_1287_1324_Open_Text.style.display='none'; Codehighlighter1_1287_1324_Closed_Image.style.display='inline'; Codehighlighter1_1287_1324_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1287_1324_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1287_1324_Closed_Text.style.display='none'; Codehighlighter1_1287_1324_Open_Image.style.display='inline'; Codehighlighter1_1287_1324_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>        }</span></span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">catch</span><span style="COLOR: #000000"> (InvocationTargetException e) </span><span id=Codehighlighter1_1287_1324_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_1287_1324_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            </span><span style="COLOR: #0000ff">throw</span><span style="COLOR: #000000"> e.getTargetException();<br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>        }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img id=Codehighlighter1_1375_1536_Open_Image onclick="this.style.display='none'; Codehighlighter1_1375_1536_Open_Text.style.display='none'; Codehighlighter1_1375_1536_Closed_Image.style.display='inline'; Codehighlighter1_1375_1536_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1375_1536_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1375_1536_Closed_Text.style.display='none'; Codehighlighter1_1375_1536_Open_Image.style.display='inline'; Codehighlighter1_1375_1536_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">synchronized</span><span style="COLOR: #000000"> Map getCache(Method m) </span><span id=Codehighlighter1_1375_1536_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_1375_1536_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>        Map cache </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (Map) caches.get(m);<br><img id=Codehighlighter1_1433_1517_Open_Image onclick="this.style.display='none'; Codehighlighter1_1433_1517_Open_Text.style.display='none'; Codehighlighter1_1433_1517_Closed_Image.style.display='inline'; Codehighlighter1_1433_1517_Closed_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_1433_1517_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1433_1517_Closed_Text.style.display='none'; Codehighlighter1_1433_1517_Open_Image.style.display='inline'; Codehighlighter1_1433_1517_Open_Text.style.display='inline';" src="http://www.tkk7.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (cache </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">) </span><span id=Codehighlighter1_1433_1517_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><img src="http://www.tkk7.com/Images/dot.gif"></span><span id=Codehighlighter1_1433_1517_Open_Text><span style="COLOR: #000000">{<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            cache </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> Collections.synchronizedMap(</span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> HashMap());<br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>            caches.put(m, cache);<br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>        }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/InBlock.gif" align=top>        </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> cache;<br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>    }</span></span><span style="COLOR: #000000"><br><img src="http://www.tkk7.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span><span style="COLOR: #000000"> </span></div> <p><br><br>当调用静态方法memoize的时?会创徏一个新的代理实?也就是一个java.lang.reflect.proxy的实?实现了一个接口集.q个接口集由object.getClass().getInterfaces()来决?每个代理实例包含一个java.lang.reflect.InvocationHandler实例来处理这个代理实例调用的相关Ҏ.在我们的例子?Memoizer是一个InvocationHandler实例.</p> <p>    当一个方法在代理实例里被调用,比如, calculateBinaryDigit,那么, Memoizer实例里的invokeҎ׃被调?相关信息会传linvokeҎ,以决定proxy实例调用了哪个方?包含参数信息.在我们的例子?传入Memoizer的java.lang.Method参数是calculateBinaryDigit,而参C息则是pi需要精的位数-整数n.在这个基?Memoizer能够q一步进行缓存操作的.</p> <p>    在例子里(caches是一个Hashmap,cache是一个map)里用到的Key,主要是传入的Ҏ信息:Method对象和参数对? Z实现的简单与通用?Memoizer有一个关于cache的HashMap caches,每个method是一个key,对应的valueZ个cache.然后把参C息{化成一个List对象,作ؓcache的Key.使用List是很方便?同时也可以保证equals()Ҏ,所以能够保证当且仅当参C息完全相同的时候这个List才相{?</p> <p>    一旦一个cache的Key被创?那么,计算之前都会先查找这个cache,如果扑ֈ,则返回cache里的?否则,如果带有q些参数的这个方法没有被调用q?那么,则会通过invoke来调用这个method.在我们的例子? 实例PiBinaryDigitsCalculator 里的calculateBinaryDigitҎ会通过invoke被调?而且计算l果会被存在cache?<br>何时使用Memoizer</p> <p>    作ؓ一条通用的规?Memoizer能够在Q何需要传l的cache的时候?比如上面提到的例? 特别?接口里每个需要用记忆功能的method需要满下面几条条?</p> <p>    1. q个method的返回值最好不要每ơ调用都会改变\r</p> <p>    2. q个method不要有副效应</p> <p>    3. q个method的参数是定?非mutable?</p> <p>    昄,如果每次调用q个methodq回值都不同,那么cache毫无用处了.同样也是很重要的一Ҏ,因ؓ有副效应的method不会被重?所以这个method不能有副效应(method自动更新某些状?.当然,voidҎ除外.</p> <p>    同样,memorize一个带有未?mutable)参数的method是很危险?因ؓ,要把q些参数储存到hashmap里会是很危险的一件事.ҎMap的定?当这个Map里的key发生改变,Map是不知道?所?当你执行了一ơ这个method之后,相关信息dq了Map,然后参数发生变异(mutate),W二ơ调用的时?׃得到错误的结?</p> <p>    性能</p> <p>    使用cache的主要目的就是ؓ了提升你的程序的速度.然?reflection是众所周知的低?在jdk1.4里有所改进,通过reflection调用Ҏ是普通调用速度?/2,q个比jdk1.3要快40?.Memoizer主要依靠reflection来调用方?所?它看上去q不是一个好的途径.但是,如果使用cache能给E序速度带来的提升远高于reflection寚w度的媄?那么,使用Memoizer是值得考虑?</p> <p>    在我们对PiBinaryDigitsCalculator的测试中,试环境为jdk1.4,当n于10的时?使不使用cache速度是相当的.但是,当n增大的时?使用cache的优势就开始显C出?所?l常使用PiBinaryDigitsCalculator的用?可以考虑使用cache.</p> <p>    不幸的是,唯一试你的E序是否需要cache的途径是比较你的程序在两种情况下的q行效率.管如此,因ؓZ个程序构造一个cache包装器是很容易的一件事,U除它也是很Ҏ?下面的徏议可以作Z个参考的步骤:</p> <p>    1. 选择需要记忆操作的c\r</p> <p>    2. q行它\r</p> <p>    3. 如果效率是满意的,go to 6</p> <p>    4. dmemoizer,使用cache</p> <p>    5. 如果效率没有显著提升,Udmemoizer</p> <p>    6. 如果需?重试.</p> <p>    理论?你需要分析ؓ一个类d记忆功能Ҏ个系l的影响.只有你自己清楚是否值得d.有些Ҏ,即是计量很大?但是在这个系l里很少被调?所?没必要ؓ它添加记忆功?Z保证q个,我开发了一个更有特点的Memoizer,实现了一个叫做CacheStatistics的接?你能从它得到cache的数量以及无效的cache.你可以用它作ؓ判断的一个尺?</p> <p>    扩展Memoizer</p> <p>    修改MemoizercL支持不同的cache{略是很单的.一个比较普通的cd是Least-Recently-Used(LRU)cahce,拥有固定数量的入?q个cache保入口不大于它的最大数?如果过,摒弃最旧的~存数据.也就?能够从cache里得到的是新的数?一个类可以使用LRU cache来防止一个程序长期保持一个状?你可以仅仅传递一个参数给CacheFactory里的memoizeҎ来选择你需要的cachecd.下面的例?LRU cache最多有1000个入?</p> <p>BinaryDigitsCalculator calculator =<br>(BinaryDigitsCalculator) Memoizer.memoize(<br>new PiBinaryDigitsCalculator(),<br>new LruCacheFactory(1000)<br>); </p> <p>    即是这么简?Memoizer也应该是javaE序员一个有用的工具.</p> <img src ="http://www.tkk7.com/dyerac/aggbug/132037.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/dyerac/" target="_blank">dyerac in java...</a> 2007-07-24 14:03 <a href="http://www.tkk7.com/dyerac/archive/2007/07/24/132037.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>定义自己的热?/title><link>http://www.tkk7.com/dyerac/archive/2007/07/24/132002.html</link><dc:creator>dyerac in java...</dc:creator><author>dyerac in java...</author><pubDate>Tue, 24 Jul 2007 03:06:00 GMT</pubDate><guid>http://www.tkk7.com/dyerac/archive/2007/07/24/132002.html</guid><wfw:comment>http://www.tkk7.com/dyerac/comments/132002.html</wfw:comment><comments>http://www.tkk7.com/dyerac/archive/2007/07/24/132002.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/dyerac/comments/commentRss/132002.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/dyerac/services/trackbacks/132002.html</trackback:ping><description><![CDATA[<p>* 一个用KeyStroke自定义快捷键的示?br> * <br>*/<br>public class MnemonicT extends JFrame {<br> private int count = 0;</p> <p> private JButton button;</p> <p> public MnemonicT() {<br>  super("Mnemonic Test");<br>  JPanel panel = new JPanel();<br>  panel.setPreferredSize(new Dimension(320, 240));<br>  panel.setLayout(new FlowLayout());</p> <p>  button = new JButton(new AbstractAction("ClickTimes:" + count) {<br>   public void actionPerformed(ActionEvent e) {<br>    button.setText("ClickTimes:" + (++count));<br>   }<br>  });<br>  panel.add(button);<br>  add(panel);</p> <p>  InputMap im = button.getInputMap(JButton.WHEN_IN_FOCUSED_WINDOW);<br>  im.put(KeyStroke.getKeyStroke("control A"), "buttonAction"); // 按CTRL+A<br>  button.getActionMap().put("buttonAction", button.getAction());<br>  pack();<br>  setDefaultCloseOperation(EXIT_ON_CLOSE);<br> }</p> <p> public static void main(String[] args) {<br>  SwingUtilities.invokeLater(new Runnable() {<br>   public void run() {<br>    new MnemonicT().setVisible(true);<br>   }<br>  });<br> }<br>}</p> <img src ="http://www.tkk7.com/dyerac/aggbug/132002.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/dyerac/" target="_blank">dyerac in java...</a> 2007-07-24 11:06 <a href="http://www.tkk7.com/dyerac/archive/2007/07/24/132002.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>QztQannotation relationshttp://www.tkk7.com/dyerac/archive/2007/07/22/131760.htmldyerac in java...dyerac in java...Sun, 22 Jul 2007 14:42:00 GMThttp://www.tkk7.com/dyerac/archive/2007/07/22/131760.htmlhttp://www.tkk7.com/dyerac/comments/131760.htmlhttp://www.tkk7.com/dyerac/archive/2007/07/22/131760.html#Feedback0http://www.tkk7.com/dyerac/comments/commentRss/131760.htmlhttp://www.tkk7.com/dyerac/services/trackbacks/131760.html阅读全文

]]>
Editplus配置http://www.tkk7.com/dyerac/archive/2007/07/17/130884.htmldyerac in java...dyerac in java...Tue, 17 Jul 2007 08:48:00 GMThttp://www.tkk7.com/dyerac/archive/2007/07/17/130884.htmlhttp://www.tkk7.com/dyerac/comments/130884.htmlhttp://www.tkk7.com/dyerac/archive/2007/07/17/130884.html#Feedback0http://www.tkk7.com/dyerac/comments/commentRss/130884.htmlhttp://www.tkk7.com/dyerac/services/trackbacks/130884.html1. 以sqlZQ需要sql.stx(语法)  sql.acpQauto completementQ放到editplus目录下即?br>2. 另外修改settings.ini{几个ini文gQ主要是针对acp文gQ?br>3. q启动editplus用tool工具导入stx文g q设|高亮染色方案(alertQ我只发C导入 没找到手工修改的?nbsp;
    法)
4. 创徏template.sql文g q修改template.ini 注意 也要修改ini中显C的模板数目Q而非仅仅dQ?br>5. that's all

]]>
Ant十五大应??http://www.tkk7.com/dyerac/archive/2006/12/05/85591.htmldyerac in java...dyerac in java...Tue, 05 Dec 2006 07:38:00 GMThttp://www.tkk7.com/dyerac/archive/2006/12/05/85591.htmlhttp://www.tkk7.com/dyerac/comments/85591.htmlhttp://www.tkk7.com/dyerac/archive/2006/12/05/85591.html#Feedback0http://www.tkk7.com/dyerac/comments/commentRss/85591.htmlhttp://www.tkk7.com/dyerac/services/trackbacks/85591.html阅读全文

]]>
自己做的多功能计器Q嘿?/title><link>http://www.tkk7.com/dyerac/archive/2006/11/24/dollyCal.html</link><dc:creator>dyerac in java...</dc:creator><author>dyerac in java...</author><pubDate>Fri, 24 Nov 2006 10:24:00 GMT</pubDate><guid>http://www.tkk7.com/dyerac/archive/2006/11/24/dollyCal.html</guid><wfw:comment>http://www.tkk7.com/dyerac/comments/83344.html</wfw:comment><comments>http://www.tkk7.com/dyerac/archive/2006/11/24/dollyCal.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.tkk7.com/dyerac/comments/commentRss/83344.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/dyerac/services/trackbacks/83344.html</trackback:ping><description><![CDATA[     摘要: 有感于windows自带计算器的不好?最q心血来潮按自己需求开发了一个多功能计算器。其核心的一部分来自于网上的学习资料Q因此我也不敢私藏代码,Ҏ出来和大家分享心得?<br> 计算器功能如下: <br> 1.支持q行时更换界面皮肤,水印和按钮Ş状等外观昄?<br> 2.支持sin, cos, tan, cot, arcsin, arccos, arctan, arccot, !, log, ln, +, -, *, /, %, 乘方{基本运,支持q箋q算q? <br> 自带PIQE的精倹{?<br> 3.支持表达式计,支持讄变量Q可以轻杄实现公式q算?<br> 4.无限的结果保存,完全对用户透明Q用户可以轻杄存储和读取先前的操作l果. <br> 5.能够分析用户操作其是表辑ּ中的语法错误Q提醒用戯不是返回错误结果?nbsp; <a href='http://www.tkk7.com/dyerac/archive/2006/11/24/dollyCal.html'>阅读全文</a><img src ="http://www.tkk7.com/dyerac/aggbug/83344.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/dyerac/" target="_blank">dyerac in java...</a> 2006-11-24 18:24 <a href="http://www.tkk7.com/dyerac/archive/2006/11/24/dollyCal.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>B/S实现q程配置SVNhttp://www.tkk7.com/dyerac/archive/2006/10/21/76578.htmldyerac in java...dyerac in java...Sat, 21 Oct 2006 14:30:00 GMThttp://www.tkk7.com/dyerac/archive/2006/10/21/76578.htmlhttp://www.tkk7.com/dyerac/comments/76578.htmlhttp://www.tkk7.com/dyerac/archive/2006/10/21/76578.html#Feedback4http://www.tkk7.com/dyerac/comments/commentRss/76578.htmlhttp://www.tkk7.com/dyerac/services/trackbacks/76578.html现在提供的功能有Q?
为项目创建svn仓库Q修改svn账户密码Q修改svn权限配置{?nbsp; 阅读全文

]]>
Collection学习W记http://www.tkk7.com/dyerac/archive/2006/07/30/60899.htmldyerac in java...dyerac in java...Sun, 30 Jul 2006 14:34:00 GMThttp://www.tkk7.com/dyerac/archive/2006/07/30/60899.htmlhttp://www.tkk7.com/dyerac/comments/60899.htmlhttp://www.tkk7.com/dyerac/archive/2006/07/30/60899.html#Feedback0http://www.tkk7.com/dyerac/comments/commentRss/60899.htmlhttp://www.tkk7.com/dyerac/services/trackbacks/60899.html
1.ArrayList实际上应该是数组实现,所以不方便做大量的删除和添?但是很有效与get(),set()Ҏ
   LinkedList是基于链表实?所以不应该用作随机讉K,但是add(),remove()Ҏ很适用

2.add(),remove()Ҏ会破坏集合的l构,所以在用两个线E访问时会出现同步问?但是set()(改变之前讉K的?不会.

3.vector和arraylist都是Z数组实现?它们的区别在?vector是同步的,会消耗更多的资源,所以不需要同步时,最好用arraylist
  同样的例子还有Hashtable(同步)和HashMap

4.集合的某些操作会有boolean的返回?该DC是否改变了集合的结?比如add).由此可以判断操作是否成功

5.HashSet不能存放相同的元? 而且是无序存攄. TreeSet提供了排序的Ҏ,可以让元素自w实现Comparable接口,或?为TreeSet制定Ҏ的排序类Comparator

6. PriorityQueue提供了高效的得到最元素的Ҏ,q有助于实现d调度器类似的功能

7.Map的keySet, entrySet, values可以讉K和删除键值或者键?但是不能增加.增加的话必须直接调用Map的方?同样,Map中相同的元素只能有一个键?br />
8.WeakHashMap可以把map中不再需要的元素由gc回收

9.LinkedHashSet和LinkedHashMap提供了排序的Ҏ,但是q个排序是可以控制的,accessOrder为true时是按照讉K的顺序进行的,为false时是按照你的输入序

10.IdientityHashMap通过内存地址计算hascode,因此可以拥有相同的元?因ؓ它中间的比较是通过"=="而不是equals

11.CollectionscL供了一pd操作Collection接口的方法和法, 比如二分查找, 排序{等(h意Collections和Collection的区?

12.视图技?
    q是集合框架一出色的技? 对于现有集合的操? 比如说选取子集, p集合产生Ҏ集合{等,实际上都没有创徏新的集合,而是在原有集合上创徏视图,该视图是实现了Collection接口的特D实现类,用户对这些类的调用实际上q是对被其包裹的原有集合的调? 视图实际上vC的代理的作用
   因此,视图的问题在于通过视图你有时无法调用接口的所有方?比如List.asList(Array a)可以把数l包Ҏ列表,但实际上,我们的操作还是直接传C数组之中.因此,对于q样的列? 所有的更改l构的方?如add, remove)都不被支?(代测?

]]>
用Look And Feel打造绚丽的界面外观Q?/title><link>http://www.tkk7.com/dyerac/archive/2006/04/03/38986.html</link><dc:creator>dyerac in java...</dc:creator><author>dyerac in java...</author><pubDate>Mon, 03 Apr 2006 10:18:00 GMT</pubDate><guid>http://www.tkk7.com/dyerac/archive/2006/04/03/38986.html</guid><wfw:comment>http://www.tkk7.com/dyerac/comments/38986.html</wfw:comment><comments>http://www.tkk7.com/dyerac/archive/2006/04/03/38986.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.tkk7.com/dyerac/comments/commentRss/38986.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/dyerac/services/trackbacks/38986.html</trackback:ping><description><![CDATA[     摘要: 虽然我们知道Q一个桌面应用程序的好坏Q和它的性能Q功能有着很大关系Q?<br>然而,对于大多数坐在电脑前的用戯言Q他们的标准往往? l丽的外?<br>MVC设计下的的SWING自然没有忽视q一?通过对UIManager的设|?和第三方的类?<br>我们可以很容易的改变应用E序的外?<br>  <a href='http://www.tkk7.com/dyerac/archive/2006/04/03/38986.html'>阅读全文</a><img src ="http://www.tkk7.com/dyerac/aggbug/38986.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/dyerac/" target="_blank">dyerac in java...</a> 2006-04-03 18:18 <a href="http://www.tkk7.com/dyerac/archive/2006/04/03/38986.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用java打造Q意Ş状窗口和透明H口http://www.tkk7.com/dyerac/archive/2006/04/03/38984.htmldyerac in java...dyerac in java...Mon, 03 Apr 2006 10:15:00 GMThttp://www.tkk7.com/dyerac/archive/2006/04/03/38984.htmlhttp://www.tkk7.com/dyerac/comments/38984.htmlhttp://www.tkk7.com/dyerac/archive/2006/04/03/38984.html#Feedback6http://www.tkk7.com/dyerac/comments/commentRss/38984.htmlhttp://www.tkk7.com/dyerac/services/trackbacks/38984.html阅读全文

]]>
վ֩ģ壺 ޾Ʒm߹ۿ| ޹þþۺ| 91avƵ| wwwһwww| þþþavëƬ| һƵѹۿ| A޾VƷ| Ʒҹѹۿվ| ŷձ| ƷƬѿ| ޹Ʒһһҳ| aëƬaëƬ| AVվ| òƵѿ| ޾Ʒһ23Ŀ| ձƵһ߹ۿ| Ʒ޾Ʒ| ˸徫Ʒ| ҹӰ| ݺۺɫ| ³˿Ƭһ | ҰƵ߹1| ޸͵һ| Ůվ߹ۿƵѵ| Ʒþ㽶߿ۿ| þóѵӰ| ˽ۺϾþ| ֻˬƵѿ| Ƶվ߿| 91޾Ʒר| ŮëƬƵ| ƷAVһ| A޾VƷɫ| Ļȫ| ҹƷһ鶹| avҹƬƷӰ| պĻƵ| Ʒ޸жƪ | δʮ18ֹվ| ˮĻӰ| va߹ۿ|