﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-Shooper.Java-文章分类-Java-api</title><link>http://www.blogjava.net/shooper/category/10941.html</link><description>Beginning Java</description><language>zh-cn</language><lastBuildDate>Fri, 02 Mar 2007 06:31:39 GMT</lastBuildDate><pubDate>Fri, 02 Mar 2007 06:31:39 GMT</pubDate><ttl>60</ttl><item><title>初识Java内部类</title><link>http://www.blogjava.net/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.blogjava.net/shooper/articles/45315.html</guid><wfw:comment>http://www.blogjava.net/shooper/comments/45315.html</wfw:comment><comments>http://www.blogjava.net/shooper/articles/45315.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shooper/comments/commentRss/45315.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shooper/services/trackbacks/45315.html</trackback:ping><description><![CDATA[
		<div class="clear">
		</div>
		<div class="item-body">
				<div class="item-content">
						<p>    提起Java内部类（Inner Class）可能很多人不太熟悉，实际上类似的概念在C++里也有，那就是嵌套类（Nested Class），关于这两者的区别与联系，在下文中会有对比。内部类从表面上看，就是在类中又定义了一个类（下文会看到，内部类可以在很多地方定义），而实际上并没有那么简单，乍看上去内部类似乎有些多余，它的用处对于初学者来说可能并不是那么显著，但是随着对它的深入了解，你会发现Java的设计者在内部类身上的确是用心良苦。学会使用内部类，是掌握Java高级编程的一部分，它可以让你更优雅地设计你的程序结构。下面从以下几个方面来介绍：</p>
						<p>    <strong>第一次见面</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>    在这个例子里类Content和GDestination被定义在了类Goods内部，并且分别有着protected和private修饰符来控制访问级别。Content代表着Goods的内容，而GDestination代表着Goods的目的地。它们分别实现了两个接口Content和Destination。在后面的main方法里，直接用 Contents c和Destination d进行操作，你甚至连这两个内部类的名字都没有看见！这样，内部类的第一个好处就体现出来了――隐藏你不想让别人知道的操作，也即封装性。 </p>
						<p>    同时，我们也发现了在外部类作用范围之外得到内部类对象的第一个方法，那就是利用其外部类的方法创建并返回。上例中的cont()和dest()方法就是这么做的。那么还有没有别的方法呢？当然有，其语法格式如下：</p>
						<p>    outerObject=new outerClass(Constructor Parameters);</p>
						<p>    outerClass.innerClass innerObject=outerObject.new InnerClass(Constructor Parameters);</p>
						<p>    注意在创建非静态内部类对象时，一定要先创建起相应的外部类对象。至于原因，也就引出了我们下一个话题――</p>
						<p>    <strong>非静态内部类对象有着指向其外部类对象的引用</strong></p>
						<p>    对刚才的例子稍作修改：</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>    修改的部分用蓝色显示了。在这里我们给Goods类增加了一个private成员变量valueRate，意义是货物的价值系数，在内部类Content的方法value()计算价值时把它乘上。我们发现，value()可以访问valueRate，这也是内部类的第二个好处――一个内部类对象可以访问创建它的外部类对象的内容，甚至包括私有变量！这是一个非常有用的特性，为我们在设计时提供了更多的思路和捷径。要想实现这个功能，内部类对象就必须有指向外部类对象的引用。Java编译器在创建内部类对象时，隐式的把其外部类对象的引用也传了进去并一直保存着。这样就使得内部类对象始终可以访问其外部类对象，同时这也是为什么在外部类作用范围之外向要创建内部类对象必须先创建其外部类对象的原因。</p>
						<p>    有人会问，如果内部类里的一个成员变量与外部类的一个成员变量同名，也即外部类的同名成员变量被屏蔽了，怎么办？没事，Java里用如下格式表达外部类的引用：</p>
						<p>outerClass.this</p>
						<p>    有了它，我们就不怕这种屏蔽的情况了。</p>
						<p>    <strong>静态内部类</strong></p>
						<p>    和普通的类一样，内部类也可以有静态的。不过和非静态内部类相比，区别就在于静态内部类没有了指向外部的引用。这实际上和C++中的嵌套类很相像了，Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用这一点上，当然从设计的角度以及以它一些细节来讲还有区别。</p>
						<p>    除此之外，在任何非静态内部类中，都不能有静态数据，静态方法或者又一个静态内部类（内部类的嵌套可以不止一层）。不过静态内部类中却可以拥有这一切。这也算是两者的第二个区别吧。</p>
						<p>    <strong>局部内部类 </strong></p>
						<p>    是的，Java内部类也可以是局部的，它可以定义在一个方法甚至一个代码块之内。</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>    上面就是这样一个例子。在方法dest中我们定义了一个内部类，最后由这个方法返回这个内部类的对象。如果我们在用一个内部类的时候仅需要创建它的一个对象并创给外部，就可以这样做。当然，定义在方法中的内部类可以使设计多样化，用途绝不仅仅在这一点。</p>
						<p>    下面有一个更怪的例子：</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之外创建这个内部类的对象，因为这已经超出了它的作用域。不过在编译的时候，内部类TrackingSlip和其他类一样同时被编译，只不过它由它自己的作用域，超出了这个范围就无效，除此之外它和其他内部类并没有区别。</p>
						<p>   <strong> 匿名内部类 </strong></p>
						<p>    java的匿名内部类的语法规则看上去有些古怪，不过如同匿名数组一样，当你只需要创建一个类的对象而且用不上它的名字时，使用内部类可以使代码看上去简洁清楚。它的语法规则是这样的：</p>
						<p>    new interfacename(){......}; 或 new superclassname(){......};</p>
						<p>    下面接着前面继续举例子：</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>    这里方法cont()使用匿名内部类直接返回了一个实现了接口Contents的类的对象，看上去的确十分简洁。</p>
						<p>    在java的事件处理的匿名适配器中，匿名内部类被大量的使用。例如在想关闭窗口时加上这样一句代码：</p>
						<p>frame.addWindowListener(new WindowAdapter(){</p>
						<p>     public void windowClosing(WindowEvent e){</p>
						<p>          System.exit(0); </p>
						<p>     }</p>
						<p>});</p>
						<p>    有一点需要注意的是，匿名内部类由于没有名字，所以它没有构造函数（但是如果这个匿名内部类继承了一个只含有带参数构造函数的父类，创建它的时候必须带上这些参数，并在实现的过程中使用super关键字调用相应的内容）。如果你想要初始化它的成员变量，有下面几种方法：</p>
						<p>    1.如果是在一个方法的匿名内部类，可以利用这个方法传进你想要的参数，不过记住，这些参数必须被声明为final。 </p>
						<p>    2.将匿名内部类改造成有名字的局部内部类，这样它就可以拥有构造函数了。 </p>
						<p>    3.在这个匿名内部类中使用初始化代码块。 </p>
						<p>    <strong>为什么需要内部类？</strong></p>
						<p>    java内部类有什么好处？为什么需要内部类？</p>
						<p>    首先举一个简单的例子，如果你想实现一个接口，但是这个接口中的一个方法和你构想的这个类中的一个方法的名称，参数相同，你应该怎么办？这时候，你可以建一个内部类实现这个接口。由于内部类对外部类的所有内容都是可访问的，所以这样做可以完成所有你直接实现这个接口的功能。</p>
						<p>    不过你可能要质疑，更改一下方法的不就行了吗？</p>
						<p>    的确，以此作为设计内部类的理由，实在没有说服力。</p>
						<p>    真正的原因是这样的，java中的内部类和接口加在一起，可以的解决常被C++程序员抱怨java中存在的一个问题――没有多继承。实际上，C++的多继承设计起来很复杂，而java通过内部类加上接口，可以很好的实现多继承的效果。<br /></p>
				</div>
		</div>
<img src ="http://www.blogjava.net/shooper/aggbug/45315.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shooper/" target="_blank">Shooper.Java</a> 2006-05-10 00:04 <a href="http://www.blogjava.net/shooper/articles/45315.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ThreadLocal的设计与使用  </title><link>http://www.blogjava.net/shooper/articles/45314.html</link><dc:creator>Shooper.Java</dc:creator><author>Shooper.Java</author><pubDate>Tue, 09 May 2006 16:02:00 GMT</pubDate><guid>http://www.blogjava.net/shooper/articles/45314.html</guid><wfw:comment>http://www.blogjava.net/shooper/comments/45314.html</wfw:comment><comments>http://www.blogjava.net/shooper/articles/45314.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/shooper/comments/commentRss/45314.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/shooper/services/trackbacks/45314.html</trackback:ping><description><![CDATA[
		<table cellspacing="0" cellpadding="0" align="center" border="0">
				<tbody>
						<tr>
								<td>
										<table cellspacing="0" cellpadding="0" align="center" border="0">
												<tbody>
														<tr>
																<td valign="top">
																		<span>
																				<p>　　早在Java 1.2推出之时，Java平台中就引入了一个新的支持：java.lang.ThreadLocal，给我们在编写多线程程序时提供了一种新的选择。使用这个工具类可以很简洁地编写出优美的多线程程序，虽然ThreadLocal非常有用，但是似乎现在了解它、使用它的朋友还不多。 </p>
																				<p>　　<strong>ThreadLocal是什么</strong></p>
																				<p>　　ThreadLocal是什么呢？其实ThreadLocal并非是一个线程的本地实现版本，它并不是一个Thread，而是thread local variable（线程局部变量）。也许把它命名为ThreadLocalVar更加合适。线程局部变量（ThreadLocal）其实的功用非常简单，就是为每一个使用该变量的线程都提供一个变量值的副本，是每一个线程都可以独立地改变自己的副本，而不会和其它线程的副本冲突。从线程的角度看，就好像每一个线程都完全拥有该变量。线程局部变量并不是Java的新发明，在其它的一些语言编译器实现（如IBM XL FORTRAN）中，它在语言的层次提供了直接的支持。因为Java中没有提供在语言层次的直接支持，而是提供了一个ThreadLocal的类来提供支持，所以，在Java中编写线程局部变量的代码相对比较笨拙，这也许是线程局部变量没有在Java中得到很好的普及的一个原因吧。</p>
																				<p>　　<strong>ThreadLocal的设计</strong></p>
																				<p>　　首先看看ThreadLocal的接口：</p>
																				<p>　　Object get() ; // 返回当前线程的线程局部变量副本<br />    protected Object initialValue(); // 返回该线程局部变量的当前线程的初始值<br />    void set(Object value); // 设置当前线程的线程局部变量副本的值</p>
																				<p>　　ThreadLocal有3个方法，其中值得注意的是initialValue()，该方法是一个protected的方法，显然是为了子类重写而特意实现的。该方法返回当前线程在该线程局部变量的初始值，这个方法是一个延迟调用方法，在一个线程第1次调用get()或者set(Object)时才执行，并且仅执行1次。ThreadLocal中的确实实现直接返回一个null：</p>
																				<p>protected Object initialValue() { return null; } </p>
																				<p>　　ThreadLocal是如何做到为每一个线程维护变量的副本的呢？其实实现的思路很简单，在ThreadLocal类中有一个Map，用于存储每一个线程的变量的副本。比如下面的示例实现：</p>
																				<p>public class ThreadLocal<br />{<br />　private Map values = Collections.synchronizedMap(new HashMap());<br />　public Object get()<br />　{<br />　　Thread curThread = Thread.currentThread(); <br />　　Object o = values.get(curThread); <br />　　if (o == null &amp;&amp; !values.containsKey(curThread))<br />　　{<br />　　　o = initialValue();<br />　　　values.put(curThread, o); <br />　　}<br />　　return o; <br />　}</p>
																				<p>　public void set(Object newValue)<br />　{<br />　　values.put(Thread.currentThread(), newValue);<br />　}</p>
																				<p>　public Object initialValue()<br />　{<br />　　return null; <br />　}<br />} </p>
																				<p>　　当然，这并不是一个工业强度的实现，但JDK中的ThreadLocal的实现总体思路也类似于此。</p>
																				<p>　　<strong>ThreadLocal的使用</strong></p>
																				<p>　　如果希望线程局部变量初始化其它值，那么需要自己实现ThreadLocal的子类并重写该方法，通常使用一个内部匿名类对ThreadLocal进行子类化，比如下面的例子，SerialNum类为每一个类分配一个序号：</p>
																				<p>public class SerialNum <br />{<br />　// The next serial number to be assigned</p>
																				<p>　private static int nextSerialNum = 0; <br />　private static ThreadLocal serialNum = new ThreadLocal() <br />　{<br />　　protected synchronized Object initialValue() <br />　　{<br />　　　return new Integer(nextSerialNum++);<br />　　}<br />　};</p>
																				<p>　public static int get() <br />　{<br />　　return ((Integer) (serialNum.get())).intValue(); <br />　}<br />} </p>
																				<p>　　SerialNum类的使用将非常地简单，因为get()方法是static的，所以在需要获取当前线程的序号时，简单地调用：</p>
																				<p>int serial = SerialNum.get(); </p>
																				<p>　　即可。</p>
																				<p>　　在线程是活动的并且ThreadLocal对象是可访问的时，该线程就持有一个到该线程局部变量副本的隐含引用，当该线程运行结束后，该线程拥有的所以线程局部变量的副本都将失效，并等待垃圾收集器收集。</p>
																				<p>　　<strong>ThreadLocal与其它同步机制的比较</strong></p>
																				<p>　　ThreadLocal和其它同步机制相比有什么优势呢？ThreadLocal和其它所有的同步机制都是为了解决多线程中的对同一变量的访问冲突，在普通的同步机制中，是通过对象加锁来实现多个线程对同一变量的安全访问的。这时该变量是多个线程共享的，使用这种同步机制需要很细致地分析在什么时候对变量进行读写，什么时候需要锁定某个对象，什么时候释放该对象的锁等等很多。所有这些都是因为多个线程共享了资源造成的。ThreadLocal就从另一个角度来解决多线程的并发访问，ThreadLocal会为每一个线程维护一个和该线程绑定的变量的副本，从而隔离了多个线程的数据，每一个线程都拥有自己的变量副本，从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象，在编写多线程代码时，可以把不安全的整个变量封装进ThreadLocal，或者把该对象的特定于线程的状态封装进ThreadLocal。</p>
																				<p>　　由于ThreadLocal中可以持有任何类型的对象，所以使用ThreadLocal get当前线程的值是需要进行强制类型转换。但随着新的Java版本（1.5）将模版的引入，新的支持模版参数的ThreadLocal&lt;T&gt;类将从中受益。也可以减少强制类型转换，并将一些错误检查提前到了编译期，将一定程度地简化ThreadLocal的使用。</p>
																				<p>　　总结</p>
																				<p>　　当然ThreadLocal并不能替代同步机制，两者面向的问题领域不同。同步机制是为了同步多个线程对相同资源的并发访问，是为了多个线程之间进行通信的有效方式；而ThreadLocal是隔离多个线程的数据共享，从根本上就不在多个线程之间共享资源（变量），这样当然不需要对多个线程进行同步了。所以，如果你需要进行多个线程之间进行通信，则使用同步机制；如果需要隔离多个线程之间的共享冲突，可以使用ThreadLocal，这将极大地简化你的程序，使程序更加易读、简洁。</p>
																		</span>
																</td>
														</tr>
												</tbody>
										</table>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/shooper/aggbug/45314.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/shooper/" target="_blank">Shooper.Java</a> 2006-05-10 00:02 <a href="http://www.blogjava.net/shooper/articles/45314.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>