??xml version="1.0" encoding="utf-8" standalone="yes"?>午夜电影一区,亚洲色在线视频,久久免费一区http://www.aygfsteel.com/shooper/category/10941.htmlBeginning Javazh-cnFri, 02 Mar 2007 06:31:39 GMTFri, 02 Mar 2007 06:31:39 GMT60初识Java内部c?/title><link>http://www.aygfsteel.com/shooper/articles/45315.html</link><dc:creator>Shooper.Java</dc:creator><author>Shooper.Java</author><pubDate>Tue, 09 May 2006 16:04:00 GMT</pubDate><guid>http://www.aygfsteel.com/shooper/articles/45315.html</guid><wfw:comment>http://www.aygfsteel.com/shooper/comments/45315.html</wfw:comment><comments>http://www.aygfsteel.com/shooper/articles/45315.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/shooper/comments/commentRss/45315.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/shooper/services/trackbacks/45315.html</trackback:ping><description><![CDATA[ <div id="wmqeeuq" class="clear"> </div> <div id="wmqeeuq" class="item-body"> <div id="wmqeeuq" class="item-content"> <p>    提vJava内部c(Inner ClassQ可能很多h不太熟悉Q实际上cM的概念在C++里也有,那就是嵌套类QNested ClassQ,关于q两者的区别与联p,在下文中会有Ҏ。内部类从表面上看,是在类中又定义了一个类Q下文会看到Q内部类可以在很多地方定义)Q而实际上q没有那么简单,乍看上去内部cM乎有些多余,它的用处对于初学者来说可能ƈ不是那么显著Q但是随着对它的深入了解,你会发现Java的设计者在内部cn上的是用心良苦。学会用内部类Q是掌握Java高~程的一部分Q它可以让你更优雅地设计你的E序l构。下面从以下几个斚w来介l:</p> <p>    <strong>W一ơ见?/strong></p> <p>public interface Contents {</p> <p>    int value();</p> <p>}</p> <p>public interface Destination {</p> <p>    String readLabel();</p> <p>}</p> <p>public class Goods {</p> <p>    private class Content implements Contents {</p> <p>        private int i = 11;</p> <p>        public int value() { </p> <p>            return i; </p> <p>        }</p> <p>    }</p> <p>    protected class GDestination implements Destination {</p> <p>        private String label;</p> <p>        private GDestination(String whereTo) {</p> <p>            label = whereTo;</p> <p>        }</p> <p>        public String readLabel() { </p> <p>            return label; </p> <p>        }</p> <p>    }</p> <p>    public Destination dest(String s) {</p> <p>        return new GDestination(s);</p> <p>    }</p> <p>    public Contents cont() {</p> <p>        return new Content();</p> <p>    }</p> <p>}</p> <p>class TestGoods {</p> <p>    public static void main(String[] args) {</p> <p>        Goods p = new Goods();</p> <p>        Contents c = p.cont();</p> <p>        Destination d = p.dest("Beijing");</p> <p>    }</p> <p>}</p> <p>    在这个例子里cContent和GDestination被定义在了类Goods内部Qƈ且分别有着protected和private修饰W来控制讉KU别。Content代表着Goods的内容,而GDestination代表着Goods的目的地。它们分别实C两个接口Content和Destination。在后面的mainҎ里,直接?Contents c和Destination dq行操作Q你甚至q这两个内部cȝ名字都没有看见!q样Q内部类的第一个好处就体现出来了――隐藏你不想让别人知道的操作Q也卛_装性?</p> <p>    同时Q我们也发现了在外部cM用范围之外得到内部类对象的第一个方法,那就是利用其外部cȝҎ创徏q返回。上例中的cont()和dest()Ҏ是q么做的。那么还有没有别的方法呢Q当然有Q其语法格式如下Q?/p> <p>    outerObject=new outerClass(Constructor Parameters);</p> <p>    outerClass.innerClass innerObject=outerObject.new InnerClass(Constructor Parameters);</p> <p>    注意在创建非静态内部类对象Ӟ一定要先创v相应的外部类对象。至于原因,也就引出了我们下一个话题―?/p> <p>    <strong>非静态内部类对象有着指向其外部类对象的引?/strong></p> <p>    对刚才的例子E作修改Q?/p> <p>public class Goods {</p> <p>    private valueRate=2;</p> <p>    private class Content implements Contents {</p> <p>        private int i = 11*valueRate;</p> <p>        public int value() { </p> <p>            return i; </p> <p>        }</p> <p>    }</p> <p>    protected class GDestination implements Destination {</p> <p>        private String label;</p> <p>        private GDestination(String whereTo) {</p> <p>            label = whereTo;</p> <p>        }</p> <p>        public String readLabel() { </p> <p>            return label; </p> <p>        }</p> <p>    }</p> <p>    public Destination dest(String s) {</p> <p>        return new GDestination(s);</p> <p>    }</p> <p>    public Contents cont() {</p> <p>        return new Content();</p> <p>    }</p> <p>}</p> <p>    修改的部分用蓝色昄了。在q里我们lGoodscd加了一个private成员变量valueRateQ意义是货物的h值系敎ͼ在内部类Content的方法value()计算价值时把它乘上。我们发玎ͼvalue()可以讉KvalueRateQ这也是内部cȝW二个好处――一个内部类对象可以讉K创徏它的外部cd象的内容Q甚臛_括私有变量!q是一个非常有用的Ҏ,为我们在设计时提供了更多的思\和捷径。要惛_现这个功能,内部cd象就必须有指向外部类对象的引用。Java~译器在创徏内部cd象时Q隐式的把其外部cd象的引用也传了进dƈ一直保存着。这样就使得内部cd象始l可以访问其外部cd象,同时q也是ؓ什么在外部cM用范围之外向要创建内部类对象必须先创建其外部cd象的原因?/p> <p>    有h会问Q如果内部类里的一个成员变量与外部cȝ一个成员变量同名,也即外部cȝ同名成员变量被屏蔽了Q怎么办?没事QJava里用如下格式表达外部cȝ引用Q?/p> <p>outerClass.this</p> <p>    有了它,我们׃怕这U屏蔽的情况了?/p> <p>    <strong>静态内部类</strong></p> <p>    和普通的cMP内部cM可以有静态的。不q和非静态内部类相比Q区别就在于静态内部类没有了指向外部的引用。这实际上和C++中的嵌套cd相像了,Java内部cMC++嵌套cL大的不同在于是否有指向外部的引用这一点上Q当然从设计的角度以及以它一些细节来讲还有区别?/p> <p>    除此之外Q在M非静态内部类中,都不能有静态数据,静态方法或者又一个静态内部类Q内部类的嵌套可以不止一层)。不q静态内部类中却可以拥有q一切。这也算是两者的W二个区别吧?/p> <p>    <strong>局部内部类 </strong></p> <p>    是的QJava内部cM可以是局部的Q它可以定义在一个方法甚至一个代码块之内?/p> <p>public class Goods1 {</p> <p>     public Destination dest(String s) {</p> <p>          class GDestination implements Destination {</p> <p>               private String label;</p> <p>               private GDestination(String whereTo) {</p> <p>                    label = whereTo;</p> <p>               }</p> <p>               public String readLabel() { return label; }</p> <p>          }</p> <p>          return new GDestination(s);</p> <p>     }</p> <p>     public static void main(String[] args) {</p> <p>          Goods1 g= new Goods1();</p> <p>          Destination d = g.dest("Beijing");</p> <p>     }</p> <p>}</p> <p>    上面是q样一个例子。在Ҏdest中我们定义了一个内部类Q最后由q个Ҏq回q个内部cȝ对象。如果我们在用一个内部类的时候仅需要创建它的一个对象ƈ创给外部Q就可以q样做。当Ӟ定义在方法中的内部类可以使设计多样化Q用途绝不仅仅在q一炏V?/p> <p>    下面有一个更怪的例子Q?/p> <p>public class Goods2{</p> <p>     private void internalTracking(boolean b) {</p> <p>          if(b) {</p> <p>               class TrackingSlip {</p> <p>                    private String id;</p> <p>                    TrackingSlip(String s) {</p> <p>                         id = s;</p> <p>                    }</p> <p>                    String getSlip() { return id; }</p> <p>               }</p> <p>               TrackingSlip ts = new TrackingSlip("slip");</p> <p>               String s = ts.getSlip();</p> <p>          } </p> <p>     }</p> <p>     public void track() { internalTracking(true); }</p> <p>     public static void main(String[] args) {</p> <p>          Goods2 g= new Goods2();</p> <p>          g.track();</p> <p>     }</p> <p>}</p> <p>    你不能在if之外创徏q个内部cȝ对象Q因已经出了它的作用域。不q在~译的时候,内部cTrackingSlip和其他类一样同时被~译Q只不过它由它自q作用域,出了这个范围就无效Q除此之外它和其他内部类q没有区别?/p> <p>   <strong> 匿名内部c?</strong></p> <p>    java的匿名内部类的语法规则看上去有些古怪,不过如同匿名数组一P当你只需要创Z个类的对象而且用不上它的名字时Q用内部类可以使代码看上去z清楚。它的语法规则是q样的:</p> <p>    new interfacename(){......}; ?new superclassname(){......};</p> <p>    下面接着前面l箋举例子:</p> <p>public class Goods3 {</p> <p>     public Contents cont(){</p> <p>          return new Contents(){</p> <p>               private int i = 11;</p> <p>               public int value() { </p> <p>                    return i; </p> <p>               }</p> <p>          };</p> <p>     }</p> <p>}</p> <p>    q里Ҏcont()使用匿名内部cȝ接返回了一个实C接口Contents的类的对象,看上ȝ十分简z?/p> <p>    在java的事件处理的匿名适配器中Q匿名内部类被大量的使用。例如在惛_闭窗口时加上q样一句代码:</p> <p>frame.addWindowListener(new WindowAdapter(){</p> <p>     public void windowClosing(WindowEvent e){</p> <p>          System.exit(0); </p> <p>     }</p> <p>});</p> <p>    有一炚w要注意的是,匿名内部cȝ于没有名字,所以它没有构造函敎ͼ但是如果q个匿名内部cȝ承了一个只含有带参数构造函数的父类Q创建它的时候必d上这些参敎ͼq在实现的过E中使用super关键字调用相应的内容Q。如果你惌初始化它的成员变量,有下面几U方法:</p> <p>    1.如果是在一个方法的匿名内部c,可以利用q个Ҏ传进你想要的参数Q不q记住,q些参数必须被声明ؓfinal?</p> <p>    2.匿名内部类攚w成有名字的局部内部类Q这样它可以拥有构造函C?</p> <p>    3.在这个匿名内部类中用初始化代码块?</p> <p>    <strong>Z么需要内部类Q?/strong></p> <p>    java内部cL什么好处?Z么需要内部类Q?/p> <p>    首先举一个简单的例子Q如果你惛_C个接口,但是q个接口中的一个方法和你构想的q个cM的一个方法的名称Q参数相同,你应该怎么办?q时候,你可以徏一个内部类实现q个接口。由于内部类对外部类的所有内定w是可讉K的,所以这样做可以完成所有你直接实现q个接口的功能?/p> <p>    不过你可能要质疑Q更改一下方法的不就行了吗?</p> <p>    的确Q以此作计内部类的理由,实在没有说服力?/p> <p>    真正的原因是q样的,java中的内部cd接口加在一P可以的解军_被C++E序员抱怨java中存在的一个问题――没有多l承。实际上QC++的多l承设计h很复杂,而java通过内部cd上接口,可以很好的实现多l承的效果?br /></p> </div> </div> <img src ="http://www.aygfsteel.com/shooper/aggbug/45315.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/shooper/" target="_blank">Shooper.Java</a> 2006-05-10 00:04 <a href="http://www.aygfsteel.com/shooper/articles/45315.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ThreadLocal的设计与使用 http://www.aygfsteel.com/shooper/articles/45314.htmlShooper.JavaShooper.JavaTue, 09 May 2006 16:02:00 GMThttp://www.aygfsteel.com/shooper/articles/45314.htmlhttp://www.aygfsteel.com/shooper/comments/45314.htmlhttp://www.aygfsteel.com/shooper/articles/45314.html#Feedback0http://www.aygfsteel.com/shooper/comments/commentRss/45314.htmlhttp://www.aygfsteel.com/shooper/services/trackbacks/45314.html

  早在Java 1.2推出之时QJavaq_中就引入了一个新的支持:java.lang.ThreadLocalQ给我们在编写多U程E序时提供了一U新的选择。用这个工L可以很简z地~写Z的多线E程序,虽然ThreadLocal非常有用Q但是似乎现在了解它、用它的朋友还不多?

  ThreadLocal是什?/strong>

  ThreadLocal是什么呢Q其实ThreadLocalq是一个线E的本地实现版本Q它q不是一个ThreadQ而是thread local variableQ线E局部变量)。也许把它命名ؓThreadLocalVar更加合适。线E局部变量(ThreadLocalQ其实的功用非常单,是为每一个用该变量的线E都提供一个变量值的副本Q是每一个线E都可以独立地改变自q副本Q而不会和其它U程的副本冲H。从U程的角度看Q就好像每一个线E都完全拥有该变量。线E局部变量ƈ不是Java的新发明Q在其它的一些语a~译器实玎ͼ如IBM XL FORTRANQ中Q它在语a的层ơ提供了直接的支持。因为Java中没有提供在语言层次的直接支持,而是提供了一个ThreadLocal的类来提供支持,所以,在Java中编写线E局部变量的代码相对比较W拙Q这也许是线E局部变量没有在Java中得到很好的普及的一个原因吧?/p>

  ThreadLocal的设?/strong>

  首先看看ThreadLocal的接口:

  Object get() ; // q回当前U程的线E局部变量副?br />    protected Object initialValue(); // q回该线E局部变量的当前U程的初始?br />    void set(Object value); // 讄当前U程的线E局部变量副本的?/p>

  ThreadLocal?个方法,其中值得注意的是initialValue()Q该Ҏ是一个protected的方法,昄是ؓ了子c重写而特意实现的。该Ҏq回当前U程在该U程局部变量的初始|q个Ҏ是一个gq调用方法,在一个线E第1ơ调用get()或者set(Object)时才执行Qƈ且仅执行1ơ。ThreadLocal中的实实现直接q回一个nullQ?/p>

protected Object initialValue() { return null; }

  ThreadLocal是如何做Cؓ每一个线E维护变量的副本的呢Q其实实现的思\很简单,在ThreadLocalcM有一个MapQ用于存储每一个线E的变量的副本。比如下面的CZ实现Q?/p>

public class ThreadLocal
{
 private Map values = Collections.synchronizedMap(new HashMap());
 public Object get()
 {
  Thread curThread = Thread.currentThread();
  Object o = values.get(curThread);
  if (o == null && !values.containsKey(curThread))
  {
   o = initialValue();
   values.put(curThread, o);
  }
  return o;
 }

 public void set(Object newValue)
 {
  values.put(Thread.currentThread(), newValue);
 }

 public Object initialValue()
 {
  return null;
 }
}

  当然Q这q不是一个工业强度的实现Q但JDK中的ThreadLocal的实现M思\也类g此?/p>

  ThreadLocal的?/strong>

  如果希望U程局部变量初始化其它|那么需要自己实现ThreadLocal的子cdƈ重写该方法,通常使用一个内部匿名类对ThreadLocalq行子类化,比如下面的例子,SerialNumcMؓ每一个类分配一个序P

public class SerialNum
{
 // The next serial number to be assigned

 private static int nextSerialNum = 0;
 private static ThreadLocal serialNum = new ThreadLocal()
 {
  protected synchronized Object initialValue()
  {
   return new Integer(nextSerialNum++);
  }
 };

 public static int get()
 {
  return ((Integer) (serialNum.get())).intValue();
 }
}

  SerialNumcȝ使用非常地单,因ؓget()Ҏ是static的,所以在需要获取当前线E的序号Ӟ单地调用Q?/p>

int serial = SerialNum.get();

  卛_?/p>

  在线E是zd的ƈ且ThreadLocal对象是可讉K的时Q该U程持有一个到该线E局部变量副本的隐含引用Q当该线E运行结束后Q该U程拥有的所以线E局部变量的副本都将失效Qƈ{待垃圾攉器收集?/p>

  ThreadLocal与其它同步机制的比较

  ThreadLocal和其它同步机制相比有什么优势呢QThreadLocal和其它所有的同步机制都是Z解决多线E中的对同一变量的访问冲H,在普通的同步机制中,是通过对象加锁来实现多个线E对同一变量的安全访问的。这时该变量是多个线E共享的Q用这U同步机刉要很l致地分析在什么时候对变量q行dQ什么时候需要锁定某个对象,什么时候释放该对象的锁{等很多。所有这些都是因为多个线E共享了资源造成的。ThreadLocal׃另一个角度来解决多线E的q发讉KQThreadLocal会ؓ每一个线E维护一个和该线E绑定的变量的副本,从而隔M多个U程的数据,每一个线E都拥有自己的变量副本,从而也没有必要对该变量进行同步了。ThreadLocal提供了线E安全的׃n对象Q在~写多线E代码时Q可以把不安全的整个变量装qThreadLocalQ或者把该对象的特定于线E的状态封装进ThreadLocal?/p>

  ׃ThreadLocal中可以持有Q何类型的对象Q所以用ThreadLocal get当前U程的值是需要进行强制类型{换。但随着新的Java版本Q?.5Q将模版的引入,新的支持模版参数的ThreadLocal<T>cd从中受益。也可以减少强制cd转换Qƈ一些错误检查提前到了编译期Q将一定程度地化ThreadLocal的用?/p>

  ȝ

  当然ThreadLocalq不能替代同步机Ӟ两者面向的问题领域不同。同步机制是Z同步多个U程对相同资源的q发讉KQ是Z多个U程之间q行通信的有效方式;而ThreadLocal是隔d个线E的数据׃nQ从Ҏ上就不在多个U程之间׃n资源Q变量)Q这样当然不需要对多个U程q行同步了。所以,如果你需要进行多个线E之间进行通信Q则使用同步机制Q如果需要隔d个线E之间的׃n冲突Q可以用ThreadLocalQ这极大地化你的程序,使程序更加易诅R简z?/p>



Shooper.Java 2006-05-10 00:02 发表评论
]]>
վ֩ģ壺 | ʯȪ| կ| | ̩| | տ| | | | Ϫ| | ͼ| | | | | ԭ| | | | ʯׯ| ƽ| ƽ| | ÷| ɽ| ˮ| Ĭ| | | | ʡ| | | ɽ| | | Ϸ| ij| |