<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type='text/xsl' href='http://babaozhou.spaces.live.com/mmm2008-07-24_12.50/rsspretty.aspx?rssquery=en-US;http%3a%2f%2fbabaozhou.spaces.live.com%2fcategory%2fJava%2ffeed.rss' version='1.0'?><rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:msn="http://schemas.microsoft.com/msn/spaces/2005/rss" xmlns:live="http://schemas.microsoft.com/live/spaces/2006/rss" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:cf="http://www.microsoft.com/schemas/rss/core/2005" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>瞎扯淡: Java</title><description /><link>http://babaozhou.spaces.live.com/?_c11_BlogPart_BlogPart=blogview&amp;_c=BlogPart&amp;partqs=catJava</link><language>en-US</language><pubDate>Thu, 28 Aug 2008 04:49:04 GMT</pubDate><lastBuildDate>Thu, 28 Aug 2008 04:49:04 GMT</lastBuildDate><generator>Microsoft Spaces v1.1</generator><docs>http://www.rssboard.org/rss-specification</docs><ttl>60</ttl><cf:parentRSS>http://babaozhou.spaces.live.com/blog/feed.rss</cf:parentRSS><live:type>blogcategory</live:type><live:identity><live:id>4841837938742446725</live:id><live:alias>babaozhou</live:alias></live:identity><cf:listinfo><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="typelabel" label="Type" /><cf:group ns="http://schemas.microsoft.com/live/spaces/2006/rss" element="tag" label="Tag" /><cf:group element="category" label="Category" /><cf:sort element="pubDate" label="Date" data-type="date" default="true" /><cf:sort element="title" label="Title" data-type="string" /><cf:sort ns="http://purl.org/rss/1.0/modules/slash/" element="comments" label="Comments" data-type="number" /></cf:listinfo><item><title>IOC模式的思考和疑问</title><link>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1303.entry</link><description>&lt;div&gt;&lt;font face=Arial size=2&gt;IOC，是现在很火的设计模式，就像当年的Factory和Singleton模式一样。IOC模式为我们提供了真正（？）的松散耦合，但是松散耦合真的这么酷吗？紧耦合真的一无是处吗？不见得。&lt;br&gt;首先，使用IOC模式就必然会依赖于一些IOC容器，除非你直接使用反射(-_-)，比如Spring，这对于勾结的独立性是不利的，试想，如果每次使用java.lang.String的时候都必须import org.springframework…。对于一些要求响应速度的系统而言，IOC的使用必然会降低系统性能（new 的速度肯定比Class.forName块），缓存？忘记它吧，我已经强调响应速度了。再说，IOC跟缓存和池没有必然联系呀。&lt;/font&gt;&lt;/div&gt;&lt;font face=Arial size=2&gt;
&lt;div&gt;&lt;br&gt;其次，IOC模式的大量使用会降低一些复杂模块的可读性，要知道，如果你不能写出很好的文档（多数人都是如此），那么代码就是你唯一可以与其他人沟通的语言。如果阅读代码的人不懂IOC，不会使用Spring呢，他如何理解你那些接口的实现？&lt;/div&gt;
&lt;div&gt;&lt;br&gt;第三，IOC容器的大量使用会造成额外的维护成本，很显然，你现在不仅仅需要维护你的代码，还需要维护你的applectionContext.xml，如果是WEB应用，则需要注意维护哪些Context-Param。尤其是，虽然代码中不存在耦合关系，但是耦合关系都在配置文件中，你在写出松散耦合的代码的同时也必须去写紧耦合的配置文件，对于一个大型系统而言，大量的配置文件的管理本身就必须付出高昂的代价。&lt;/div&gt;
&lt;div&gt;&lt;br&gt;最后，我认为真正意义上的松耦合是不存在的——是的，你可以“依赖”接口编程——但是毕竟还是“依赖”了。既然没有绝对的松散耦合，那么我们是否可以考虑在一定范围内使用紧耦合呢？ArrayList和Collection是紧耦合，你是否觉得不便呢，ArrayList和Iterator更是紧耦合，难道Iterator不好用吗？&lt;/div&gt;
&lt;div&gt;&lt;br&gt;考虑一下传统的工厂模式吧，它在一定程度上体现了IOC的思想，但是又没有完全的实现IOC。你可以使用工厂模式实现接口编程，但是依赖关系仍然需要在代码中体现。Hibernate是公认的优秀产品，它没有使用IOC，大量的Factory充斥其中，但是Hiberante的质量和升级速度有目共睹。也许你会说，IOC容器提供了很多底层的东西，例如缓存和对象生命周期管理等，以Spring为例，缓存倒是有，可是生命周期管理就不见得，事务管理还是需要客户介入。再说了，这些都是容器提供的，IOC模式并没有要求。之所以谈这些，主要是考虑实现一个带有缓存和“挂钩点”的工厂，这个工厂提供对象的创建和pool&amp;amp;cache管理但是不提供依赖关系管理。&lt;/div&gt;
&lt;div&gt;&lt;br&gt;那么IOC这个模式在哪里使用呢，我认为，应该在构件这个级别使用。构件应该是一个封装的很好的模块，它提供独立的、具有实际意义的功能。通过对构件的粒度的设计控制IOC使用的密度。而构件的内部，可以使用传统的工厂模式，也可以什么模式都不用^_^。只要提供清晰准确的接口，并且封装接口在构件内部的实现，那么即使使用public变量都没有关系！&lt;/div&gt;&lt;/font&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4841837938742446725&amp;page=RSS%3a+IOC%e6%a8%a1%e5%bc%8f%e7%9a%84%e6%80%9d%e8%80%83%e5%92%8c%e7%96%91%e9%97%ae&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=babaozhou.spaces.live.com&amp;amp;GT1=babaozhou"&gt;</description><comments>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1303.entry#comment</comments><guid isPermaLink="true">http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1303.entry</guid><pubDate>Sat, 14 Oct 2006 08:55:40 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://babaozhou.spaces.live.com/blog/cns!4331A9F3BEC0CA85!1303/comments/feed.rss</wfw:commentRss><wfw:comment>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1303.entry#comment</wfw:comment><dcterms:modified>2006-10-14T08:55:40Z</dcterms:modified></item><item><title>小议JTable的isCellEditable</title><link>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1228.entry</link><description>&lt;div&gt;想要自定义表格中任意行,任意列不可编辑或者可以编辑.目前我用过两种方法,其实也就是大同小异.&lt;br&gt;1. 写一个JTable的子类并且重写它的isCellEditable方法&lt;br&gt;Class MyTable extends JTable{&lt;br&gt; public boolean isCellEditable(int row,int col){&lt;br&gt;  ....&lt;br&gt; }&lt;br&gt;}&lt;br&gt;private MyTable table1,table2,table3....&lt;br&gt;2. 用内部类直接重写它的isCellEditable方法&lt;br&gt;private JTable table1;&lt;br&gt;table1=new JTable(){&lt;br&gt; public boolean isCellEditable(int row,int col){&lt;br&gt;  .....&lt;br&gt; }&lt;br&gt;};&lt;/div&gt;
&lt;div&gt;如果里面直接return true或者false,就使得整个表格所有行,列可编辑或者不可以&lt;br&gt;如果想要某个行或者列可以编辑,只需要&lt;br&gt;public boolean isCellEditable(int row,int col){&lt;br&gt; if(col==??)&lt;br&gt;  return true\false;&lt;br&gt; if(row==??)&lt;br&gt;  return true\false;&lt;br&gt; return true\false;&lt;br&gt;}&lt;br&gt;&amp;quot;\&amp;quot; 代表或者..实现的人自己根据需求定&lt;/div&gt;
&lt;div&gt;如果想要别人用你这个,让他们来自定义,只需要用一个全局boolean变量,在方法里return它就可以了&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4841837938742446725&amp;page=RSS%3a+%e5%b0%8f%e8%ae%aeJTable%e7%9a%84isCellEditable&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=babaozhou.spaces.live.com&amp;amp;GT1=babaozhou"&gt;</description><comments>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1228.entry#comment</comments><guid isPermaLink="true">http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1228.entry</guid><pubDate>Wed, 02 Aug 2006 07:08:00 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://babaozhou.spaces.live.com/blog/cns!4331A9F3BEC0CA85!1228/comments/feed.rss</wfw:commentRss><wfw:comment>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1228.entry#comment</wfw:comment><dcterms:modified>2006-08-02T07:08:00Z</dcterms:modified></item><item><title>dom4J解析XML文件</title><link>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1226.entry</link><description>&lt;div&gt;这里的解析分为读和写.&lt;/div&gt;
&lt;div&gt;由于工作中多处用到了dom4J,对于JAVA读写XML也算有一点经验了.先记一下,免得以后忘了&lt;/div&gt;
&lt;div&gt;以下代码全部只是一个节点,而有多个attribute的&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;读XML:&lt;/div&gt;
&lt;div&gt;public class ManullyPartInfo {&lt;br&gt; private static final Logger logger = Log.getLogger(ManullyPartInfo.class);&lt;br&gt; public static final String MANULLY_PART = &amp;quot;config/temp/ManullyPartInfo.xml&amp;quot;;&lt;br&gt; private static final String PROP_CONDITION_TAG = &amp;quot;GenerateManullyPartedInformation&amp;quot;;&lt;br&gt; private static Document getDocument(String config) {&lt;br&gt;  URL fileUrl = null;&lt;br&gt;  try {&lt;br&gt;   fileUrl = new URL(&amp;quot;file:&amp;quot; + config);&lt;br&gt;  } catch (MalformedURLException e1) {&lt;br&gt;   e1.printStackTrace();&lt;br&gt;  }&lt;br&gt;  Document doc = null;&lt;br&gt;  try {&lt;br&gt;   doc = XmlUtils.getDocument(fileUrl);&lt;br&gt;   return doc;&lt;br&gt;  } catch (Exception e) {&lt;br&gt;   e.printStackTrace();&lt;br&gt;   return null;&lt;br&gt;  }&lt;br&gt; }&lt;/div&gt;
&lt;div&gt; /**&lt;br&gt;  * @description: 读取xml中每个节点的值&lt;br&gt;  * @param&lt;br&gt;  * @return value：xml中某个节点的值&lt;br&gt;  */&lt;br&gt; public static String getNodeValue(String nodeName,String config) {&lt;br&gt;  Document doc = getDocument(config);&lt;br&gt;  Element root = doc.getRootElement();&lt;br&gt;  Element node = (Element) XmlUtils.getChildNodeOf(root, nodeName);&lt;br&gt;  String value = XmlUtils.getValueOf(node);&lt;br&gt;  return value;&lt;br&gt; }&lt;/div&gt;
&lt;div&gt; /**&lt;br&gt;  * @description: 读取xml中GenerateManullyPartedInformation的值&lt;br&gt;  * @param&lt;br&gt;  * @return value：xml中GenerateManullyPartedInformation的值&lt;br&gt;  */&lt;br&gt; public static List getClassProperty(String config) {&lt;br&gt;  Document doc = getDocument(config);&lt;br&gt;  Element root = doc.getRootElement(); &lt;br&gt;  List result = new Vector();&lt;br&gt;  List&amp;lt;Element&amp;gt; children = root.elements();&lt;br&gt;  for (Element child : children) {&lt;br&gt;   String clazz = child.attribute(&amp;quot;classParted&amp;quot;).getText(); &lt;br&gt;   result.add(clazz);&lt;br&gt;  }&lt;br&gt;  return result;&lt;br&gt; }&lt;br&gt; &lt;br&gt; /**&lt;br&gt;  * &lt;br&gt;  * &amp;lt;!--方法描述...--&amp;gt;&lt;br&gt;  * 拿到该配置文件里的考试集合信息&lt;br&gt;  * @author Yang Zhicheng&lt;br&gt;  * @param config 文件路径&lt;br&gt;  * @return 考试集合信息&lt;br&gt;  */&lt;br&gt; public static List getExamSet(String config){&lt;br&gt;  Document doc = getDocument(config);&lt;br&gt;  Element root = doc.getRootElement(); &lt;br&gt;  List result = new Vector();&lt;br&gt;  List&amp;lt;Element&amp;gt; children = root.elements();&lt;br&gt;  for (Element child : children) {&lt;br&gt;   String examSet = child.attribute(&amp;quot;exam&amp;quot;).getText(); &lt;br&gt;   result.add(examSet);&lt;br&gt;  }&lt;br&gt;  return result;&lt;br&gt; }&lt;br&gt; /**&lt;br&gt;  * &lt;br&gt;  * &amp;lt;!--方法描述...--&amp;gt;&lt;br&gt;  * 用来将目标表格中的数据和源表格中的行数构造一个map&lt;br&gt;  * @author Yang Zhicheng&lt;br&gt;  * @param config: 文件所在路径&lt;br&gt;  * @return key为目标表格的数据,value为源表格中的行数的map&lt;br&gt;  */&lt;br&gt; public static Map&amp;lt;Vector&amp;lt;String&amp;gt;, Integer&amp;gt; getTransferMap(String config) {&lt;br&gt;  Map&amp;lt;Vector&amp;lt;String&amp;gt;,Integer&amp;gt; map=new LinkedHashMap&amp;lt;Vector&amp;lt;String&amp;gt;,Integer&amp;gt;();&lt;br&gt;  Document doc = getDocument(config);&lt;br&gt;  Element root = doc.getRootElement(); &lt;br&gt;  List&amp;lt;Element&amp;gt; children = root.elements();&lt;/div&gt;
&lt;div&gt;  for (Element child : children) {&lt;br&gt;   Vector vRow=new Vector();&lt;br&gt;   String clazz = child.attribute(&amp;quot;classParted&amp;quot;).getText(); &lt;br&gt;   String stuName = child.attribute(&amp;quot;stuName&amp;quot;).getText();&lt;br&gt;   String sex = child.attribute(&amp;quot;sex&amp;quot;).getText();&lt;br&gt;   String score = child.attribute(&amp;quot;score&amp;quot;).getText();&lt;br&gt;   String rowStr = child.attribute(&amp;quot;row&amp;quot;).getText();&lt;br&gt;   int row=Integer.parseInt(rowStr);&lt;br&gt;   vRow.add(clazz);&lt;br&gt;   vRow.add(stuName);&lt;br&gt;   vRow.add(sex);&lt;br&gt;   vRow.add(score);&lt;br&gt;   map.put(vRow,new Integer(row));&lt;br&gt;  }&lt;br&gt;  return map;&lt;br&gt;  &lt;br&gt; }&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;写XML&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;public class ManullyPartGenerator {&lt;br&gt; private Vector&amp;lt;String&amp;gt; idStr=new Vector&amp;lt;String&amp;gt;();&lt;br&gt; private Vector&amp;lt;String&amp;gt; classPartedStr=new Vector&amp;lt;String&amp;gt;();&lt;br&gt; private Vector&amp;lt;String&amp;gt; stuName=new Vector&amp;lt;String&amp;gt;();&lt;br&gt; private Vector&amp;lt;String&amp;gt; sex=new Vector&amp;lt;String&amp;gt;();&lt;br&gt; private Vector&amp;lt;String&amp;gt; score=new Vector&amp;lt;String&amp;gt;();&lt;br&gt; private Vector&amp;lt;Integer&amp;gt; row=new Vector&amp;lt;Integer&amp;gt;();&lt;br&gt; private Vector&amp;lt;String&amp;gt; exam=new Vector&amp;lt;String&amp;gt;();&lt;br&gt; public static String filePath;&lt;br&gt; public void generateDocument(int size,String encoding) {&lt;br&gt;  Document document = DocumentHelper.createDocument();&lt;br&gt;  Element catalogElement = document.addElement(&amp;quot;GenerateManullyPartedInformation&amp;quot;);&lt;br&gt;   for (int i = 0; i &amp;lt; size; i++) {&lt;br&gt;    Element manullyPartElement = catalogElement.addElement(&amp;quot;student&amp;quot;);&lt;br&gt;    manullyPartElement.addAttribute(&amp;quot;id&amp;quot;, getIdStr().get(i));&lt;br&gt;    manullyPartElement.addAttribute(&amp;quot;classParted&amp;quot;, getClassPartedStr().get(i));&lt;br&gt;    manullyPartElement.addAttribute(&amp;quot;stuName&amp;quot;, getStuName().get(i));&lt;br&gt;    manullyPartElement.addAttribute(&amp;quot;sex&amp;quot;, getSex().get(i));&lt;br&gt;    manullyPartElement.addAttribute(&amp;quot;score&amp;quot;, getScore().get(i));&lt;br&gt;    manullyPartElement.addAttribute(&amp;quot;row&amp;quot;, getRow().get(i).toString());&lt;br&gt;    manullyPartElement.addAttribute(&amp;quot;exam&amp;quot;, getExam().get(i));&lt;br&gt;   }&lt;/div&gt;
&lt;div&gt;  try {&lt;br&gt;   OutputFormat format = OutputFormat.createPrettyPrint();&lt;br&gt;   format.setEncoding(encoding);&lt;br&gt;   XMLWriter output = new XMLWriter(new FileWriter(new File(filePath)),format);&lt;br&gt;   output.write(document);&lt;br&gt;   output.flush();&lt;br&gt;   output.close();&lt;br&gt;  } catch (IOException e) {&lt;br&gt;   System.out.println(e.getMessage());&lt;br&gt;  }&lt;br&gt; }&lt;br&gt; public Vector&amp;lt;String&amp;gt; getClassPartedStr() {&lt;br&gt;  return classPartedStr;&lt;br&gt; }&lt;br&gt; public void setClassPartedStr(Vector&amp;lt;String&amp;gt; classPartedStr) {&lt;br&gt;  this.classPartedStr = classPartedStr;&lt;br&gt; }&lt;br&gt; public Vector&amp;lt;String&amp;gt; getIdStr() {&lt;br&gt;  return idStr;&lt;br&gt; }&lt;br&gt; public void setIdStr(Vector&amp;lt;String&amp;gt; idStr) {&lt;br&gt;  this.idStr = idStr;&lt;br&gt; }&lt;br&gt; public Vector&amp;lt;String&amp;gt; getScore() {&lt;br&gt;  return score;&lt;br&gt; }&lt;br&gt; public void setScore(Vector&amp;lt;String&amp;gt; score) {&lt;br&gt;  this.score = score;&lt;br&gt; }&lt;br&gt; public Vector&amp;lt;String&amp;gt; getSex() {&lt;br&gt;  return sex;&lt;br&gt; }&lt;br&gt; public void setSex(Vector&amp;lt;String&amp;gt; sex) {&lt;br&gt;  this.sex = sex;&lt;br&gt; }&lt;br&gt; public Vector&amp;lt;String&amp;gt; getStuName() {&lt;br&gt;  return stuName;&lt;br&gt; }&lt;br&gt; public void setStuName(Vector&amp;lt;String&amp;gt; stuName) {&lt;br&gt;  this.stuName = stuName;&lt;br&gt; }&lt;br&gt; public Vector&amp;lt;Integer&amp;gt; getRow() {&lt;br&gt;  return row;&lt;br&gt; }&lt;br&gt; public void setRow(Vector&amp;lt;Integer&amp;gt; row) {&lt;br&gt;  this.row = row;&lt;br&gt; }&lt;br&gt; public Vector&amp;lt;String&amp;gt; getExam() {&lt;br&gt;  return exam;&lt;br&gt; }&lt;br&gt; public void setExam(Vector&amp;lt;String&amp;gt; exam) {&lt;br&gt;  this.exam = exam;&lt;br&gt; }&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;该XML结构很简单,所以实现也很简单.如果要实现结构复杂的XML,看看dom4J的API,再结合上面的,应该不难&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;&lt;a href="http://dom4j.org/apidocs/index.html"&gt;http://dom4j.org/apidocs/index.html&lt;/a&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4841837938742446725&amp;page=RSS%3a+dom4J%e8%a7%a3%e6%9e%90XML%e6%96%87%e4%bb%b6&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=babaozhou.spaces.live.com&amp;amp;GT1=babaozhou"&gt;</description><comments>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1226.entry#comment</comments><guid isPermaLink="true">http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1226.entry</guid><pubDate>Tue, 01 Aug 2006 12:05:03 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://babaozhou.spaces.live.com/blog/cns!4331A9F3BEC0CA85!1226/comments/feed.rss</wfw:commentRss><wfw:comment>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1226.entry#comment</wfw:comment><dcterms:modified>2006-08-01T12:05:03Z</dcterms:modified></item><item><title>郁闷</title><link>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1224.entry</link><description>&lt;div&gt;对于性能这方面关心的很少.由于最近碰到了一个很严重影响性能的问题才会重新重视起来..&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;是关于自己写的一个控件,之间的blog已经提到了..&lt;/div&gt;
&lt;div&gt;我自己在一个模块里使用这个控件的时候,效率竟然低的吓人.可是控件本身运行的时候却感觉不到任何性能问题..很奇怪.我想应该不会跟数据库有关系,运行的时候log里并没有出现该操作再读写数据库.到底是什么原因..我很郁闷&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;matrix的高级程序区应该说算一般热,但是属于高级区中的GUI区里真是跟坟墓没有多大差别.高手都不削于GUI吗?我这个也不单纯算GUI部分了,跟性能也有很大关系..难道是我控件里的逻辑不好?我实在想不出有什么其他的逻辑方法能优化该控件了....&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;郁闷..&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4841837938742446725&amp;page=RSS%3a+%e9%83%81%e9%97%b7&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=babaozhou.spaces.live.com&amp;amp;GT1=babaozhou"&gt;</description><comments>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1224.entry#comment</comments><guid isPermaLink="true">http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1224.entry</guid><pubDate>Sat, 22 Jul 2006 13:17:25 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://babaozhou.spaces.live.com/blog/cns!4331A9F3BEC0CA85!1224/comments/feed.rss</wfw:commentRss><wfw:comment>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1224.entry#comment</wfw:comment><dcterms:modified>2006-07-22T13:17:25Z</dcterms:modified></item><item><title>JUnit</title><link>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1221.entry</link><description>&lt;div&gt;效率..效率问题太大了..&lt;/div&gt;
&lt;div&gt;Debug是好东西,但是对于大型项目,单纯靠Debug,效率有点低了.&lt;/div&gt;
&lt;div&gt;从经验来说,我也吃过很多亏&lt;/div&gt;
&lt;div&gt;经常想当然的敲一堆,运行---&amp;gt;抛异常---&amp;gt;Debug跟----&amp;gt;发现错误了----&amp;gt;改----&amp;gt;运行-----&amp;gt;抛另外的异常---&amp;gt;再Debug跟----&amp;gt;....&lt;/div&gt;
&lt;div&gt;重复,一直重复直到修改完所有异常,好.这时候不抛异常了,系统启动起来了...嗯..不错..心情挺好..&lt;/div&gt;
&lt;div&gt;按某个按钮或者运行某个功能的时候,没得到想要的结果..天,严重的逻辑错误..&lt;/div&gt;
&lt;div&gt;继续Debug.....&lt;/div&gt;
&lt;div&gt;浪费了好多时间..&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;现在开始逐渐使用JUnit来避免这种情况..写一个函数就测一个,出现不是想要的结果马上改.虽然写测试代码需要花点时间,但是总比Debug跟一大堆所花的时间少的多.特别是对我这种写的同时不喜欢加注释的.- -!!! (极坏的习惯,我也正在改),一旦写到后面,出错了,突然发现调用了前面某个地方的方法,跟进去看,该方法又调了另一个方法,再进去看,发现里面嵌套了3个循环. - -!又没有注释,看疯你&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;另外发发牢骚,能不能不要给我一大堆没有注释的代码让我去改..- -!!!!&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4841837938742446725&amp;page=RSS%3a+JUnit&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=babaozhou.spaces.live.com&amp;amp;GT1=babaozhou"&gt;</description><comments>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1221.entry#comment</comments><guid isPermaLink="true">http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1221.entry</guid><pubDate>Thu, 13 Jul 2006 13:44:34 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://babaozhou.spaces.live.com/blog/cns!4331A9F3BEC0CA85!1221/comments/feed.rss</wfw:commentRss><wfw:comment>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1221.entry#comment</wfw:comment><dcterms:modified>2006-07-13T13:44:34Z</dcterms:modified></item><item><title>内存紧张</title><link>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1220.entry</link><description>&lt;div&gt;这几天老是觉得机子很慢..奇怪了..1G的内存为什么会卡到象256一样..&lt;/div&gt;
&lt;div&gt;打开任务管理器看了下进程和PF使用率...&lt;/div&gt;
&lt;div&gt;PF使用率经常都在2G以上..无语...最高见过3.5G的&lt;/div&gt;
&lt;div&gt;仔细一看进程,javaw.exe N个...我还以为中病毒了...&lt;/div&gt;
&lt;div&gt;后来仔细一想,觉得应该是eclipse运行一段swing代码就会生成一个javaw&lt;/div&gt;
&lt;div&gt;但是想不通的是,在每个swing窗口里我都用了dispose来释放掉内存,为什么还会占用额外的内存呢??&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;不解&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4841837938742446725&amp;page=RSS%3a+%e5%86%85%e5%ad%98%e7%b4%a7%e5%bc%a0&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=babaozhou.spaces.live.com&amp;amp;GT1=babaozhou"&gt;</description><comments>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1220.entry#comment</comments><guid isPermaLink="true">http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1220.entry</guid><pubDate>Wed, 05 Jul 2006 11:35:43 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://babaozhou.spaces.live.com/blog/cns!4331A9F3BEC0CA85!1220/comments/feed.rss</wfw:commentRss><wfw:comment>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!1220.entry#comment</wfw:comment><dcterms:modified>2006-07-05T11:35:43Z</dcterms:modified></item><item><title>EJB学习笔记1</title><link>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!992.entry</link><description>&lt;div&gt;1. define and develop class ejb&lt;br&gt;2. develop remote interface (for customer)&lt;br&gt;3. develop home interface&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;there is no relationship between home, remote interface and ejb. But, u must follow the rules. E.g, if u declare a method in ejb and also in remote interface. U must make sure both of them have the same method name. U must declare at least one create() method: ejbCreate(). And many create() methods with different parmeters are permitted. In home interface, u must define the same method declaration. &lt;br&gt;ejbCreate() method returns a constant container controller object(primary key type). But, it returns the type of remote inteface in home interface.&lt;br&gt;Notice: the implement of entity bean is different. entity bean is no need ebjCreate() method if entity is loaded to database through database management or application, it ignores ejbCreate(). The return type of ejbCreate() is primary key, but if it is null type in entity bean. But if entity bean implements the constant property, the return type becomes primary key. &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;The following is EJBObject base class&lt;/div&gt;
&lt;div&gt;package javax.ejb; &lt;/div&gt;
&lt;div&gt;public interface EJBObject extends java.rmi.Remote{ &lt;/div&gt;
&lt;div&gt;public EJBHome getEJBHome() throws java.rmi.RemoteException; &lt;/div&gt;
&lt;div&gt;public Object getPrimaryKey() throws java.rmi.RemoteException; &lt;/div&gt;
&lt;div&gt;public void Remove() throws java.rmi.RemtoeException, java.rmi.RemoveException &lt;/div&gt;
&lt;div&gt;public Handle getHandle() throws java.rmi.RemoteException; &lt;/div&gt;
&lt;div&gt;boolean isIdentical (EJBObject p0) throws java.rmi.RemoteException; &lt;/div&gt;
&lt;div&gt;} &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;Remote interface&lt;br&gt;public interface atm extends javax.ejd.EJBObject{&lt;br&gt;public void transfer(String source,String target,float amount)&lt;br&gt;throws java.rmi.RemoteException,InSufficientFundsException{}&lt;br&gt;}&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;ejb home interface control the life cycle of bean. &lt;br&gt;This cycle is different between Session bean and Entity bean. So, the home interface is different.&lt;br&gt;The same as remote interface, all of methods in home interface must throw java.rmi.RemoteException.&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;public interface EJBHome extends java.rmi.Remote() { &lt;/div&gt;
&lt;div&gt;void remove(Handle handle) throws java.rmi.RemoteException,RemoveException; &lt;/div&gt;
&lt;div&gt;void remove(Object primarykey) throws java.rmi.RemoteException,RemoveException; &lt;/div&gt;
&lt;div&gt;EJBMetaData getEJBMetaData() throws RemoteException; &lt;/div&gt;
&lt;div&gt;Homehandle getHomeHandle() throws RemoteException; &lt;/div&gt;
&lt;div&gt;} &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;PS: 打中文太麻烦了..昨天太累,用英文写了&lt;br&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4841837938742446725&amp;page=RSS%3a+EJB%e5%ad%a6%e4%b9%a0%e7%ac%94%e8%ae%b01&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=babaozhou.spaces.live.com&amp;amp;GT1=babaozhou"&gt;</description><comments>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!992.entry#comment</comments><guid isPermaLink="true">http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!992.entry</guid><pubDate>Fri, 05 May 2006 16:20:55 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://babaozhou.spaces.live.com/blog/cns!4331A9F3BEC0CA85!992/comments/feed.rss</wfw:commentRss><wfw:comment>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!992.entry#comment</wfw:comment><dcterms:modified>2006-05-05T16:21:55Z</dcterms:modified></item><item><title>Practical Java 学习笔记 (Exception 4)</title><link>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!977.entry</link><description>&lt;div&gt;在constructor中使用异常&lt;br&gt;由于constructor没有返回值.一旦出错,不好处理.&lt;br&gt;有几个方法可以解决这个问题&lt;br&gt;1. 将有可能产生错误的代码全部移出constructor,各自组成函数,这些函数返回错误码.但是一旦使用的话,用户必须先调用constructor,然后调用那些错误函数,然后再处理&lt;br&gt;2. 使用internal flag.在对象内设置一个标记,表示对象是否可用.&lt;br&gt;实现第2点有两种方法.&lt;br&gt;第1: 对象调用另一个对象里的所有函数的时候,必须先调用一个函数用来标识该对象是否有效.&lt;br&gt;第2: 在对象里的所有函数内都要先调用标识是否有效的函数,如果无效,返回错误码,或者抛出异常&lt;br&gt;3. 在constructor内部使用异常.例如&lt;br&gt;import java.io.*;&lt;/div&gt;
&lt;div&gt;class constructorTest{&lt;br&gt; public constructorTest(String fileName) throws IOException,FileNotFoundException{&lt;br&gt;  FileReader fr=new FileReader(fileName);&lt;br&gt;  BufferedReader br=new BufferedReader(fr);&lt;br&gt;  String str=br.readLine();&lt;br&gt;  }&lt;br&gt; public void go(){&lt;br&gt;  System.out.println(&amp;quot;haha&amp;quot;);&lt;br&gt;  }&lt;br&gt; }&lt;/div&gt;
&lt;div&gt;import java.io.*;&lt;br&gt;class consTestConsole{&lt;br&gt; public static void main(String[] args){&lt;br&gt;  constructorTest ct=null;&lt;br&gt;  try{&lt;br&gt;   ct=new constructorTest(&amp;quot;cons.txt&amp;quot;);&lt;br&gt;   }&lt;br&gt;  catch(FileNotFoundException e){&lt;br&gt;   e.printStackTrace(System.err);&lt;br&gt;   }&lt;br&gt;  catch(IOException e){&lt;br&gt;   e.printStackTrace(System.err);&lt;br&gt;   }&lt;br&gt;  }&lt;br&gt; }&lt;br&gt;有个额外的好处: 如果constructor抛出异常,并且调用端忽略掉这个异常,变量ct也是null值.表示既然没有得到有效的建构,也就不可能被安全的运用..这时候如果使用ct的话,会得到NullPointException的异常&lt;/div&gt;
&lt;div&gt;抛出异常之前要先将对象恢复为有效状态&lt;br&gt;抛出异常是为了什么?使系统其他部分得知.保持程序运行的稳定性,使得系统维持正常运行状态.&lt;br&gt;想象一下,当你的函数抛出一个异常,之后这个函数的状态变成什么样了呢?如果系统重新调用了它,会不会产生失败的结果呢?如果再调用一旦失败,那抛出异常又有什么作用呢??&lt;br&gt;所以.你就得在抛出异常之前,考虑它是否会变成有效状态&lt;br&gt;例如&lt;br&gt;class exceptionValidTest{&lt;br&gt; private int num;&lt;br&gt; private List list;&lt;br&gt; public void go(Object o) throws Exception{&lt;br&gt;  num++;       //1&lt;br&gt;  if(list.maxNum&amp;lt;num){&lt;br&gt;   //..do something&lt;br&gt;   //could throw exception&lt;br&gt;   }&lt;br&gt;  list.add(o);     //2&lt;br&gt;  }&lt;br&gt; }&lt;br&gt;如果//1和//2之间的if语句里出现了异常.那么结果是什么呢?整个exceptionValidTest object就变成了无效状态,因为num的值不对.如果程序从异常种回复过来再次进入go(Object o)的话,可能会发生其他错误&lt;br&gt;解决方法很简单&lt;br&gt;只需要把num++放到go()函数的最后去就可以了&lt;br&gt;class exceptionValidTest{&lt;br&gt; private int num;&lt;br&gt; private List list;&lt;br&gt; public void go(Object o) throws Exception{&lt;br&gt;   if(list.maxNum&amp;lt;num){&lt;br&gt;   //..do something&lt;br&gt;   //could throw exception&lt;br&gt;   }&lt;br&gt;  list.add(o);     //2&lt;br&gt;num++;         //1&lt;br&gt;  }&lt;br&gt; }&lt;/div&gt;
&lt;div&gt;另外一个典型的例子&lt;br&gt;class customers{&lt;br&gt; private MutualFund[] mf;&lt;br&gt; public MutualFund[] getMF(){&lt;br&gt;  return mf;&lt;br&gt;  }&lt;br&gt; public void updateMutualFund(MutualFund mf) throws DatabaseException{}&lt;br&gt; public void writeReport() throws IOException{}&lt;br&gt; }&lt;/div&gt;
&lt;div&gt;class DatabaseException extends Exception{}&lt;br&gt;class MutualFund{&lt;br&gt; public void buyMoreShare(double money){}&lt;br&gt; }&lt;br&gt; &lt;br&gt;class service{&lt;br&gt; public void invest(customers c,double money) throws DatabaseException,IOException{&lt;br&gt;  MutualFund[] arr=c.getMF();&lt;br&gt;  for(int i=0;i&amp;lt;arr.length;i++){&lt;br&gt;   ((MutualFund)arr[i]).buyMoreShare(money);    //1&lt;br&gt;   c.updateMutualFund(arr[i]);                 //2&lt;br&gt;   c.writeReport();                           //3&lt;br&gt;   }&lt;br&gt;  }&lt;br&gt; }&lt;/div&gt;
&lt;div&gt;上面的例子,customers里的两个方法抛出了两种异常.然后在service里的invcst里被调用,invest()本身并不处理异常,只是将其捕获再次抛出,留个调用端处理.&lt;br&gt;初看上去,这个程序并没有任何问题.&lt;br&gt;但是仔细想下.当invest()里的循环开始以后, //2执行完后,假如因为磁盘空间满了的原因,发生异常,//3没有执行到,程序就exit了.&lt;br&gt;当处理完异常后,比如清理磁盘,再次进入该函数,发生了什么呢?&lt;br&gt;for()里的前两行已经执行过,//1买了一些股票,//2已经更新数据库.假设//1买了1000块,那么在第一次异常抛出之前,数据库里就已经多出了1000块..第2次进去后,又放1000的话,整个数组里的第一位值就是2000了,其他都是1000,这并不是这个程序所要的结果&lt;/div&gt;
&lt;div&gt;解决办法&lt;br&gt;class customers{&lt;br&gt; private MutualFund[] mf;&lt;br&gt; public MutualFund[] getMF(){&lt;br&gt;  return mf;&lt;br&gt;  }&lt;br&gt; public void updateMutualFund(MutualFund mf) throws DatabaseException{}&lt;br&gt; public void undoMutualFund(MutualFund mf) throws DatabaseException{}&lt;br&gt; public void writeReport() throws IOException{}&lt;br&gt; }&lt;/div&gt;
&lt;div&gt;class DatabaseException extends Exception{}&lt;br&gt;class MutualFund{&lt;br&gt; public void buyMoreShare(double money){}&lt;br&gt; public void sellMoreShare(double money){}&lt;br&gt; }&lt;br&gt; &lt;br&gt;class service{&lt;br&gt; public void invest(customers c,double money) throws DatabaseException,IOException{&lt;br&gt;  MutualFund[] arr=c.getMF();&lt;br&gt;  for(int i=0;i&amp;lt;arr.length;i++){&lt;br&gt;   ((MutualFund)arr[i]).buyMoreShare(money);&lt;br&gt;   try{&lt;br&gt;    c.updateMutualFund(arr[i]);&lt;br&gt;   }&lt;br&gt;   catch(DatabaseException e){&lt;br&gt;    ((MutualFund)arr[i]).sellMoreMoney(money);&lt;br&gt;    throw e;&lt;br&gt;    }&lt;br&gt;   try{&lt;br&gt;    c.writeReport();&lt;br&gt;   }&lt;br&gt;   catch(IOException e){&lt;br&gt;    ((MutualFund)arr[i]).sellMoreMoney(money);&lt;br&gt;    c.undoMutualFund(arr[i]);&lt;br&gt;    throw e;&lt;br&gt;    }&lt;br&gt;   }&lt;br&gt;  }&lt;br&gt; }&lt;br&gt;在customer和MutualFund里各添加了一个方法,就是说买了就卖了,更新了就取消了&lt;br&gt;意思是在invest里,只要更新的时候发生异常,就把之前买的钱卖了&lt;br&gt;更新完以后,//3发生异常,就把更新的信息取消了.&lt;br&gt;这样就能使系统在下一次进入该函数时,不会有意想不到的结果了..&lt;br&gt;NOTICE: 如果sellMoreMoney()和undoMutualFund()再发生异常,还是会出现错误.可见要想保持对象时刻处于正确,有效的状态,是多么的困难&lt;br&gt;启示: 类似于所谓的transcation.必须有个commit and rollback.如果有一部分无法正确完成,就要取消掉整个过程&lt;br&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4841837938742446725&amp;page=RSS%3a+Practical+Java+%e5%ad%a6%e4%b9%a0%e7%ac%94%e8%ae%b0+(Exception+4)&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=babaozhou.spaces.live.com&amp;amp;GT1=babaozhou"&gt;</description><comments>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!977.entry#comment</comments><guid isPermaLink="true">http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!977.entry</guid><pubDate>Tue, 02 May 2006 04:29:48 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://babaozhou.spaces.live.com/blog/cns!4331A9F3BEC0CA85!977/comments/feed.rss</wfw:commentRss><wfw:comment>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!977.entry#comment</wfw:comment><dcterms:modified>2006-05-02T04:29:48Z</dcterms:modified></item><item><title>Practical Java 学习笔记 (Exception 3)</title><link>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!975.entry</link><description>&lt;div&gt;关于throws&lt;br&gt;当你使用throws的时候,写上所有有可能抛出的exception是个好习惯,如果你象下面这样&lt;br&gt;class multiTest{&lt;br&gt; public void go(int x) throws exception1{&lt;br&gt;  if(x==1)&lt;br&gt;   throw new exception1();&lt;br&gt;  if(x==2)&lt;br&gt;   throw new exception2();&lt;br&gt;  if(x==3)&lt;br&gt;   throw new exception3();&lt;br&gt;  }&lt;br&gt; public static void main(String[] args){&lt;br&gt;  try{&lt;br&gt;   new multiTest().go(1);&lt;br&gt;  }&lt;br&gt;  catch(exception1 e){&lt;br&gt;   e.printStackTrace(System.err);&lt;br&gt;   }&lt;br&gt;  }&lt;br&gt; }&lt;/div&gt;
&lt;div&gt;class exception1 extends Exception{}&lt;br&gt;class exception2 extends exception1{}&lt;br&gt;class exception3 extends exception2{}&lt;/div&gt;
&lt;div&gt;仅仅只写了base exception的话..OK..FINE,编译没有错误.但是这却使函数调用者陷入了&amp;quot;满头大汗的推断该函数可能产生哪些异常的&amp;quot;窘境&lt;/div&gt;
&lt;div&gt;&lt;br&gt;关于override函数&lt;br&gt;如果重写的函数抛出的异常与被重写的不一样,就象下面这样&lt;br&gt;import java.io.*;&lt;br&gt;class overrideTest{&lt;br&gt; public void go() throws FileNotFoundException{&lt;br&gt;  throw new FileNotFoundException();&lt;br&gt;  }&lt;br&gt; }&lt;/div&gt;
&lt;div&gt;class derived extends overrideTest{&lt;br&gt; public void go() throws IOException{&lt;br&gt;  throw new IOException();&lt;br&gt;  }&lt;br&gt; }&lt;br&gt;结果就是编译错误.因为后者抛出了另一个没有在被重写函数里定义的异常&lt;br&gt;对于重写的函数&lt;br&gt;1. 不抛出异常&lt;br&gt;2. 抛出跟被重写函数一样的异常&lt;br&gt;3. 抛出被重写函数异常的派生异常&lt;/div&gt;
&lt;div&gt;&lt;br&gt;关于finally&lt;br&gt;finally可以用来防止资源泄漏..比如&lt;br&gt;import java.net.*;&lt;br&gt;import java.io.*;&lt;br&gt;class withoutFinally{&lt;br&gt; public void go() throws IOException{&lt;br&gt;  ServerSocket ss=new ServerSocket(0);&lt;br&gt;  try{&lt;br&gt;   Socket s=ss.accept();&lt;br&gt;  }&lt;br&gt;  catch(IOException e){&lt;br&gt;   e.printStackTrace(System.err);&lt;br&gt;   }&lt;br&gt;  finally{&lt;br&gt;   ss.close();&lt;br&gt;   }&lt;br&gt;  }&lt;br&gt; }&lt;/div&gt;
&lt;div&gt;如果你不使用finally&lt;br&gt;仅仅只写ss.close()的话,当发生了异常的时候,ss.close()就不会被执行.你只有在catch()中再次调用ss.close(),如果可能产生很多异常的话,你需要在每个catch()里写&lt;/div&gt;
&lt;div&gt;ss.close();&lt;br&gt;这应该算是finally得优点..那么当然它也有缺点..看下面&lt;/div&gt;
&lt;div&gt;尽量不要在try中使用return ,break, continue&lt;br&gt;例子:&lt;br&gt;class returnTest{&lt;br&gt; public int go(){&lt;br&gt;  try{&lt;br&gt;   return 1; &lt;br&gt;   }&lt;br&gt;  catch(Exception e){&lt;br&gt;   return 2;&lt;br&gt;   }&lt;br&gt;  }&lt;br&gt; public int go2(){&lt;br&gt;  try{&lt;br&gt;   return 3;&lt;br&gt;   }&lt;br&gt;  finally{&lt;br&gt;   return 4;&lt;br&gt;   }&lt;br&gt;  }&lt;br&gt; public static void main(String[] args){&lt;br&gt;  returnTest rt=new returnTest();&lt;br&gt;  System.out.println(rt.go());&lt;br&gt;  System.out.println(rt.go2());&lt;br&gt;  }&lt;br&gt; }&lt;br&gt;输出结果:&lt;br&gt;1&lt;br&gt;4&lt;/div&gt;
&lt;div&gt;显示go()里的catch()没有机会执行,但是go2()里的,try返回的3被finally的4覆盖了..&lt;br&gt;所以: 尽量不要在try中使用return,continue,break这种,一旦有了finally,它们并不会跳出整个函数,而是跳出try,进入finally.如果不能避免的话,要保证finally里的代码不会&lt;/div&gt;
&lt;div&gt;更改try中的值&lt;/div&gt;
&lt;div&gt;&lt;br&gt;NOTICE: &lt;br&gt;1.不要将try/catch放在循环中.这样会使执行效率降低&lt;br&gt;2.不要使用异常来控制流程.比如&lt;br&gt;class flowControl{&lt;br&gt;pubic void go() throws Exception{&lt;br&gt;try{&lt;br&gt;while(true){&lt;br&gt;if(some loop terminating condition)&lt;br&gt;throw new Exception();&lt;br&gt;}&lt;br&gt;}&lt;br&gt;catch(Exception e){}&lt;br&gt;}&lt;br&gt;}&lt;/div&gt;
&lt;div&gt;上面的例子使用了抛出一个异常来中止循环.这是个不好的习惯.它会使代码性能低下,含义模糊,难以维护&lt;br&gt;3.不要滥用异常.&lt;br&gt;比如例子1&lt;br&gt;int data;&lt;br&gt;MyInputStream mis=new MyInputStream(&amp;quot;11.txt&amp;quot;);&lt;br&gt;data=mis.getData();&lt;br&gt;while(data!=0){&lt;br&gt;//....do something;&lt;br&gt;data=mis.getData();&lt;br&gt;}&lt;br&gt;例子2&lt;br&gt;int data;&lt;br&gt;MyInputStream mis=new MyInputStream(&amp;quot;11.txt&amp;quot;);&lt;br&gt;try{&lt;br&gt;while(true){&lt;br&gt;data=mis.getData();&lt;br&gt;//.. do something&lt;br&gt;}&lt;br&gt;catch(NoMoreDataException e){}&lt;/div&gt;
&lt;div&gt;两个例子一比较.前面那个更为直观.&lt;br&gt;并不是所有错误的地方都要使用异常,异常仅仅是给那些无法预料的错误.注意一下,异常的抛出是throw new Exception();它创建了一个新的对象.这样看来,成本并不低.它会使你&lt;/div&gt;
&lt;div&gt;的程序效率变低&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4841837938742446725&amp;page=RSS%3a+Practical+Java+%e5%ad%a6%e4%b9%a0%e7%ac%94%e8%ae%b0+(Exception+3)&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=babaozhou.spaces.live.com&amp;amp;GT1=babaozhou"&gt;</description><comments>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!975.entry#comment</comments><guid isPermaLink="true">http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!975.entry</guid><pubDate>Mon, 01 May 2006 07:56:36 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://babaozhou.spaces.live.com/blog/cns!4331A9F3BEC0CA85!975/comments/feed.rss</wfw:commentRss><wfw:comment>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!975.entry#comment</wfw:comment><dcterms:modified>2006-05-01T07:56:36Z</dcterms:modified></item><item><title>Practical Java 学习笔记 (Exception 2)</title><link>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!971.entry</link><description>&lt;div&gt;需要注意的是&lt;br&gt;你有可能遮掩exception.当你在catch or finally里又抛出一个exception的时候&lt;br&gt;比如将上面的代码改为&lt;br&gt;class logTest{&lt;br&gt; public void go(){&lt;br&gt;             int arr[]=new int[3];&lt;/div&gt;
&lt;div&gt;  try{&lt;br&gt;   System.out.println(arr[10]);&lt;br&gt;   }&lt;br&gt;  catch(ArrayIndexOutOfBoundsException e){&lt;br&gt;   System.out.println(arr[11]);&lt;br&gt;  // e.printStackTrace(System.err);&lt;br&gt;   } &lt;br&gt;  }&lt;br&gt; public static void main(String[] args){&lt;br&gt;  new logTest().go();&lt;br&gt;  }&lt;br&gt; }&lt;br&gt;在打印出来的exception信息中,就变成了System.out.println(arr[11]);这一行的exception&lt;/div&gt;
&lt;div&gt;另外书上的例子更具有典型性&lt;/div&gt;
&lt;div&gt;import java.io.*;&lt;br&gt;class throwTEst{&lt;br&gt; public void go() throws Exception{&lt;br&gt;  BufferedReader br=new BufferedReader(new InputStreamReader(System.in));&lt;br&gt;  String s;&lt;br&gt;  try{&lt;br&gt;   s=br.readLine();&lt;br&gt;   throw new Exception(&amp;quot;first&amp;quot;);&lt;br&gt;   }&lt;br&gt;  catch(Exception e){&lt;br&gt;   throw new Exception(&amp;quot;second&amp;quot;);&lt;br&gt;   }&lt;br&gt;  finally{&lt;br&gt;   throw new Exception(&amp;quot;third&amp;quot;);&lt;br&gt;   }&lt;br&gt;  }&lt;br&gt; public static void main(String[] args){&lt;br&gt;  try{&lt;br&gt;   new throwTEst().go();&lt;br&gt;   }&lt;br&gt;  catch(Exception e){&lt;br&gt;   System.out.println(e.getMessage());&lt;br&gt;   }&lt;br&gt;  }&lt;br&gt; }&lt;br&gt;输出结果&lt;br&gt;1&lt;br&gt;third&lt;/div&gt;
&lt;div&gt;我加了个IO...是因为想测试下不同exception之间会出现什么结果&lt;br&gt;总的来说..这个例子就是说明&lt;br&gt;try里抛出的exception被catch捕获,catch抛出一个新的,把try里的覆盖了,then catch又抛出一个新的,被finally的覆盖了.&lt;br&gt;最后程序不知道到底问题出在哪&lt;/div&gt;
&lt;div&gt;给个具体的例子&lt;/div&gt;
&lt;div&gt;import java.io.*;&lt;br&gt;class fileExcTest{&lt;br&gt; public static void main(String[] args){&lt;br&gt;  try{&lt;br&gt;   new fileExcTest().go();&lt;br&gt;   }&lt;br&gt;  catch(FileNotFoundException e){&lt;br&gt;   System.out.println(&amp;quot;File not found&amp;quot;);&lt;br&gt;   e.printStackTrace(System.err);&lt;br&gt;   }&lt;br&gt;  catch(IOException e){&lt;br&gt;   System.out.println(&amp;quot;IO exception&amp;quot;);&lt;br&gt;   e.printStackTrace(System.err);&lt;br&gt;   }   &lt;br&gt;  }&lt;br&gt; public void go() throws myException{&lt;br&gt;  BufferedReader br1=null,br2=null;&lt;br&gt;  FileReader fr;&lt;br&gt;  int r;&lt;br&gt;  try{&lt;br&gt;   fr=new FileReader(&amp;quot;file1.txt&amp;quot;);&lt;br&gt;   br1=new BufferedReader(fr);&lt;br&gt;   r=br1.read();&lt;br&gt;   &lt;br&gt;   fr=new FileReader(&amp;quot;file2.txt&amp;quot;);                       //1&lt;br&gt;   br2=new BufferedReader(fr);&lt;br&gt;   r=br2.read();&lt;br&gt;   }&lt;br&gt;  finally{&lt;br&gt;   if(br1!=null){&lt;br&gt;    br1.close();&lt;br&gt;   &lt;br&gt;   if(br2!=null){&lt;br&gt;    br2.close();&lt;br&gt;   }&lt;br&gt;  }&lt;br&gt; }&lt;br&gt;当go()里的//1的文件不存在的时候,就会抛出filenotfoundexception,程序跳转去finally.这时候如果br1.close()出现了IOException..那么程序将覆盖掉filenotfoundexception,而改成ioexception抛出给main().这就会造成一些信息的丢失甚至是未知的错误..&lt;/div&gt;
&lt;div&gt;修改办法.用一个vector来专门存放这些exception.建立一个新的class extends Exception.里面包含vector.然后在finally将这个自定义的exception抛出给main()就可以了..&lt;/div&gt;
&lt;div&gt;import java.util.Vector;&lt;br&gt;import java.io.*;&lt;/div&gt;
&lt;div&gt;class myException extends Exception{&lt;br&gt; Vector v;&lt;br&gt; public myException(Vector v){&lt;br&gt;  this.v=v;&lt;br&gt;  }&lt;br&gt; public Vector getExceptionVector(){&lt;br&gt;  return v;&lt;br&gt;  }&lt;br&gt; }&lt;/div&gt;
&lt;div&gt;&lt;br&gt;import java.io.*;&lt;br&gt;import java.util.Vector;&lt;br&gt;class fileExcTest{&lt;br&gt; public static void main(String[] args){&lt;br&gt;  try{&lt;br&gt;   new fileExcTest().go();&lt;br&gt;   }&lt;br&gt;  catch(myException me){&lt;br&gt;   me.printStackTrace(System.err);&lt;br&gt;   }&lt;br&gt;   &lt;br&gt;  }&lt;br&gt; public void go() throws myException{&lt;br&gt;  BufferedReader br1=null,br2=null;&lt;br&gt;  FileReader fr;&lt;br&gt;  int r;&lt;br&gt;  Vector v=new Vector();&lt;br&gt;  try{&lt;br&gt;   fr=new FileReader(&amp;quot;file1.txt&amp;quot;);&lt;br&gt;   br1=new BufferedReader(fr);&lt;br&gt;   r=br1.read();&lt;br&gt;   &lt;br&gt;   fr=new FileReader(&amp;quot;file2.txt&amp;quot;);&lt;br&gt;   br2=new BufferedReader(fr);&lt;br&gt;   r=br2.read();&lt;br&gt;   }&lt;br&gt;  catch(FileNotFoundException fnfe){&lt;br&gt;   v.add(fnfe);&lt;br&gt;   }&lt;br&gt;  catch(IOException ioe){&lt;br&gt;   v.add(ioe);&lt;br&gt;   }&lt;br&gt;  finally{&lt;br&gt;   if(br1!=null){&lt;br&gt;    try{&lt;br&gt;     br1.close();&lt;br&gt;    }&lt;br&gt;    catch(IOException ioe){&lt;br&gt;     v.add(ioe);&lt;br&gt;     }&lt;br&gt;    }&lt;br&gt;   if(br2!=null){&lt;br&gt;    try{&lt;br&gt;     br2.close();&lt;br&gt;    }&lt;br&gt;    catch(IOException ioe){&lt;br&gt;     v.add(ioe);&lt;br&gt;     }&lt;br&gt;    }&lt;br&gt;   if(v.size()!=0)&lt;br&gt;    throw new myException(v);&lt;br&gt;   }&lt;br&gt;  }&lt;br&gt; }&lt;br&gt;上面的例子可以说明: try,catch,finally可以随意嵌套.但是他们最终只会抛出一个exception给调用端.而最后这个就是唯一被调用端接受的,其他的全部都被遮住了.所以,如果调用端要知道造成失败的初始原因,exception一定不能被遮盖&lt;br&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4841837938742446725&amp;page=RSS%3a+Practical+Java+%e5%ad%a6%e4%b9%a0%e7%ac%94%e8%ae%b0+(Exception+2)&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=babaozhou.spaces.live.com&amp;amp;GT1=babaozhou"&gt;</description><comments>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!971.entry#comment</comments><guid isPermaLink="true">http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!971.entry</guid><pubDate>Sun, 30 Apr 2006 05:58:52 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://babaozhou.spaces.live.com/blog/cns!4331A9F3BEC0CA85!971/comments/feed.rss</wfw:commentRss><wfw:comment>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!971.entry#comment</wfw:comment><dcterms:modified>2006-04-30T05:58:52Z</dcterms:modified></item><item><title>Practical Java 学习笔记 (Exception 1)</title><link>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!969.entry</link><description>&lt;p&gt;当程序产生exception的时候&lt;br&gt;1. catch and control&lt;br&gt;2. catch and throw,该exception会被传回给调用端&lt;br&gt;3. catch and throw a new exception,该exception会被传回给调用端,new exception里必须包含原exception的相关信息,才能确保信息不被丢失&lt;br&gt;4. 不捕捉这个exception,听任它传回给调用端
&lt;p&gt;&lt;br&gt;class logTest{&lt;br&gt; public void go(){&lt;br&gt;  try{&lt;br&gt;   int arr[]=new int[3];&lt;br&gt;   System.out.println(arr[10]);&lt;br&gt;   }&lt;br&gt;  catch(ArrayIndexOutOfBoundsException e){&lt;br&gt;  // System.out.println(e.toString());&lt;br&gt;   e.printStackTrace(System.err);&lt;br&gt;   } &lt;br&gt;  }&lt;br&gt; public static void main(String[] args){&lt;br&gt;  new logTest().go();&lt;br&gt;  }&lt;br&gt; }
&lt;p&gt;至少在catch里要有&lt;br&gt;  // System.out.println(e.toString());&lt;br&gt;   e.printStackTrace(System.err);&lt;br&gt;如果什么不都加的话,就像catch(ArrayIndexOutOfBoundsException e){}&lt;br&gt;程序只是把exception吞了,而没有做任何处理,这可能会引起更多的麻烦.可能稍后会失败,出现难调试的情形
&lt;p&gt;以上代码输出结果&lt;br&gt;java.lang.ArrayIndexOutOfBoundsException&lt;br&gt;        at logTest.go(logTest.java:5)&lt;br&gt;        at logTest.main(logTest.java:13)
&lt;p&gt;当然最好的做法还是就地解决掉它们&lt;br&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4841837938742446725&amp;page=RSS%3a+Practical+Java+%e5%ad%a6%e4%b9%a0%e7%ac%94%e8%ae%b0+(Exception+1)&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=babaozhou.spaces.live.com&amp;amp;GT1=babaozhou"&gt;</description><comments>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!969.entry#comment</comments><guid isPermaLink="true">http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!969.entry</guid><pubDate>Sat, 29 Apr 2006 16:23:32 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://babaozhou.spaces.live.com/blog/cns!4331A9F3BEC0CA85!969/comments/feed.rss</wfw:commentRss><wfw:comment>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!969.entry#comment</wfw:comment><dcterms:modified>2006-04-29T16:32:13Z</dcterms:modified></item><item><title>接口能作为返回类型吗?</title><link>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!955.entry</link><description>&lt;div&gt;答案: 能&lt;/div&gt;
&lt;div&gt;接口是不能作为对象的,那么为什么接口能作为返回类型呢?&lt;/div&gt;
&lt;div&gt;其实只要返回实现了该接口的类的对象就可以了&lt;/div&gt;
&lt;div&gt;例子:&lt;/div&gt;
&lt;div&gt;import java.util.ArrayList;&lt;br&gt;import java.util.LinkedList;&lt;br&gt;import java.util.List;&lt;br&gt;&lt;br&gt;public class Test&lt;br&gt;{&lt;br&gt;    public List amethod()&lt;br&gt;    {&lt;br&gt;        List list = new ArrayList();&lt;br&gt;        &lt;br&gt;        list.add(&amp;quot;arraylist&amp;quot;);&lt;br&gt;        return list;&lt;br&gt;        &lt;br&gt;    }&lt;br&gt;    &lt;br&gt;    public List bmethod()&lt;br&gt;    {&lt;br&gt;        List list = new LinkedList();&lt;br&gt;        list.add(&amp;quot;linkedlist&amp;quot;);&lt;br&gt;        return list;&lt;br&gt;    }&lt;br&gt;    &lt;br&gt;    public void dealList(List list)&lt;br&gt;    {&lt;br&gt;        System.out.println(list.getClass());&lt;br&gt;        &lt;br&gt;        System.out.println(list.get(0));&lt;br&gt;        &lt;br&gt;    }&lt;br&gt;&lt;br&gt;    &lt;br&gt;    public static void main(String[] args)&lt;br&gt;    {&lt;br&gt;        Test t = new Test();&lt;br&gt;        &lt;br&gt;        t.dealList(t.amethod());&lt;br&gt;        t.dealList(t.bmethod());&lt;br&gt;        &lt;br&gt;    }&lt;br&gt;}&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;java中List是一个接口而ArrayList和LinkedList都是List的实现。在不同的情况下你可能应用到一个接口的不同实现。比如：ArrayList比较适合随机访问，LinkedList适合添加删除数据。&lt;br&gt;很多情况下我们只针对List进行操作就可以了（比如list.get(i)）而不用理会List的具体实现是什么。&lt;br&gt;public void dealList(List list)就是这样一个方法，这个方法认识List，所以传入的是LinkedList还是ArrayList都没有关系，都是统一的调用方法。&lt;br&gt;&lt;br&gt;这里用的是List的例子。其它接口包括自定义的接口也都大同小异。&lt;br&gt;所谓返回接口是指将方法的返回类型定义为接口，而实现方法时返回的是实现这个接口的实体对象。&lt;br&gt;&lt;br&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4841837938742446725&amp;page=RSS%3a+%e6%8e%a5%e5%8f%a3%e8%83%bd%e4%bd%9c%e4%b8%ba%e8%bf%94%e5%9b%9e%e7%b1%bb%e5%9e%8b%e5%90%97%3f&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=babaozhou.spaces.live.com&amp;amp;GT1=babaozhou"&gt;</description><comments>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!955.entry#comment</comments><guid isPermaLink="true">http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!955.entry</guid><pubDate>Sat, 15 Apr 2006 10:09:02 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://babaozhou.spaces.live.com/blog/cns!4331A9F3BEC0CA85!955/comments/feed.rss</wfw:commentRss><wfw:comment>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!955.entry#comment</wfw:comment><dcterms:modified>2006-04-29T12:01:25Z</dcterms:modified></item><item><title>JAVA中很容易混淆的地方</title><link>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!954.entry</link><description>&lt;div&gt;&lt;strong&gt;问题一：&lt;/strong&gt;&lt;span style="color:red"&gt;我声明了什么！&lt;/span&gt;&lt;br&gt;&lt;br&gt;String s = &amp;quot;Hello world!&amp;quot;;&lt;br&gt;&lt;br&gt;许多人都做过这样的事情，但是，我们到底声明了什么？回答通常是：一个String，内容是“Hello world!”。这样模糊的回答通常是概念不清的根源。如果要准确的回答，一半的人大概会回答错误。&lt;br&gt;这个语句&lt;font color="#ff0000"&gt;声明的是一个指向对象的引用，名为“s”，可以指向类型为String的任何对象，目前指向&amp;quot;Hello world!&amp;quot;&lt;/font&gt;这个String类型的对象。这就是真正发生的事情。我们并没有声明一个String对象，我们只是声明了一个只能指向String对象的引用变量。所以，如果在刚才那句语句后面，如果再运行一句：&lt;br&gt;&lt;br&gt;String string = s;&lt;br&gt;&lt;br&gt;我们是声明了另外一个只能指向String对象的引用，名为string，并没有第二个对象产生，string还是指向原来那个对象，也就是，和s指向同一个对象。&lt;br&gt;(类4于C++中最容易混淆也是谈虎色变的指针)&lt;/div&gt;
&lt;div&gt;&lt;br&gt;&lt;b&gt;问题二：&lt;/b&gt;&lt;span style="color:red"&gt;&amp;quot;==&amp;quot;和equals方法究竟有什么区别？&lt;/span&gt;&lt;br&gt;&lt;br&gt;==操作符专门用来比较变量的值是否相等。比较好理解的一点是：&lt;br&gt;int a=10;&lt;br&gt;int b=10;&lt;br&gt;则a==b将是true。&lt;br&gt;但不好理解的地方是：&lt;br&gt;String a=new String(&amp;quot;foo&amp;quot;);&lt;br&gt;String b=new String(&amp;quot;foo&amp;quot;);&lt;br&gt;则a==b将返回false。&lt;br&gt;&lt;br&gt;根据前一帖说过，对象变量其实是一个引用，它们的值是指向对象所在的内存地址，而不是对象本身。a和b都使用了new操作符，意味着将在内存中产生两个内容为&amp;quot;foo&amp;quot;的字符串，既然是“两个”，它们自然位于不同的内存地址。a和b的值其实是两个不同的内存地址的值，所以使用&amp;quot;==&amp;quot;操作符，结果会是false。诚然，a和b所指的对象，它们的内容都是&amp;quot;foo&amp;quot;，应该是“相等”，但是&lt;font color="#ff00ff"&gt;==操作符并不涉及到对象内容的比较&lt;/font&gt;。&lt;br&gt;对象内容的比较，正是equals方法做的事。&lt;br&gt;&lt;br&gt;看一下Object对象的equals方法是如何实现的：&lt;br&gt;boolean equals(Object o){&lt;br&gt;&lt;br&gt;return this==o;&lt;br&gt;&lt;br&gt;}&lt;br&gt;Object对象默认使用了==操作符。所以如果你自创的类没有覆盖equals方法，那你的类使用equals和使用==会得到同样的结果。同样也可以看出，Object的equals方法没有达到equals方法应该达到的目标：比较两个对象内容是否相等。因为答案应该由类的创建者决定，所以Object把这个任务留给了类的创建者。&lt;br&gt;&lt;br&gt;看一下一个极端的类：&lt;br&gt;Class Monster{&lt;br&gt;private String content;&lt;br&gt;...&lt;br&gt;boolean equals(Object another){ return true;}&lt;br&gt;&lt;br&gt;}&lt;br&gt;我覆盖了equals方法。这个实现会导致无论Monster实例内容如何，它们之间的比较永远返回true。&lt;br&gt;&lt;br&gt;所以当你是用equals方法判断对象的内容是否相等，请不要想当然。因为可能你认为相等，而这个类的作者不这样认为，而类的equals方法的实现是由他掌握的。&lt;font color="#ff9900"&gt;如果你需要使用equals方法，或者使用任何基于散列码的集合（HashSet,HashMap,HashTable），请察看一下java doc以确认这个类的equals逻辑是如何实现的。&lt;br&gt;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;对于该问题,我用几行测试代码就能很清晰的表现出来&lt;/div&gt;
&lt;div&gt;class stringTest{&lt;br&gt; static String a=&amp;quot;abc&amp;quot;;&lt;br&gt; static String b=new String(&amp;quot;abc&amp;quot;);&lt;/div&gt;
&lt;div&gt; public static void main(String[] args){&lt;br&gt;  if(a==b)&lt;br&gt;   System.out.println(&amp;quot;a==b&amp;quot;);&lt;br&gt;  else&lt;br&gt;   System.out.println(&amp;quot;a!=b&amp;quot;);&lt;br&gt;  }&lt;br&gt; }&lt;/div&gt;
&lt;div&gt;printout: a!=b&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;如果改成if(a.equals(b))&lt;/div&gt;
&lt;div&gt;printout: a==b&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;如果将string b的声明改为 static String b=&amp;quot;abc&amp;quot;;&lt;/div&gt;
&lt;div&gt;那么下面不论示if(a==b)还是if(a.equals(b)),printout都将是a==b&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;原因:&lt;/div&gt;
&lt;div&gt;在程序运行的时候,会先创建一个&lt;font color="#ff6600"&gt;字符串缓冲池,&lt;/font&gt;当string s=一个值的时候,程序就会在该池中找是否有相同的字符串,如果有,就assign给s.注意: &lt;font color="#ff00ff"&gt;该缓冲池并不是指的内存&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;而new string的意思是,创建一个新的字符串,该值驻留在&lt;font color="#ff0000"&gt;内存&lt;/font&gt;中&lt;/div&gt;
&lt;div&gt;所以,即使a和b的内容一样,但是他们的位置不一样..当然用equals回得到相等的结果,而用==就会得到两者不相等得结果&lt;/div&gt;
&lt;div&gt;&lt;br&gt;&lt;b&gt;问题三：&lt;/b&gt;&lt;span style="color:red"&gt;String到底变了没有？&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;font color="#800000"&gt;没有&lt;/font&gt;。因为String被设计成不可变(immutable)类，所以它的所有对象都是不可变对象。请看下列代码：&lt;br&gt;&lt;br&gt;String s = &amp;quot;Hello&amp;quot;;&lt;br&gt;s = s + &amp;quot; world!&amp;quot;;&lt;br&gt;&lt;br&gt;s所指向的对象是否改变了呢？从本系列第一篇的结论很容易导出这个结论。我们来看看发生了什么事情。在这段代码中，s原先指向一个String对象，内容是&amp;quot;Hello&amp;quot;，然后我们对s进行了+操作，那么s所指向的那个对象是否发生了改变呢？答案是没有。这时，s不指向原来那个对象了，而指向了另一个String对象，内容为&amp;quot;Hello world!&amp;quot;，原来那个对象还存在于内存之中，只是s这个引用变量不再指向它了。&lt;br&gt;通过上面的说明，我们很容易导出另一个结论，如果经常对字符串进行各种各样的修改，或者说，不可预见的修改，那么&lt;font color="#800080"&gt;使用String来代表字符串的话会引起很大的内存开销&lt;/font&gt;。因为String对象建立之后不能再改变，所以对于每一个不同的字符串，都需要一个String对象来表示。这时，应该考虑使用StringBuffer类，它允许修改，而不是每个不同的字符串都要生成一个新的对象。并且，这两种类的对象转换十分容易。&lt;br&gt;同时，我们还可以知道，如果要使用内容相同的字符串，不必每次都new一个String。例如我们要在构造器中对一个名叫s的String引用变量进行初始化，把它设置为初始值，应当这样做：&lt;br&gt;public class Demo {&lt;br&gt;  private String s;&lt;br&gt;  ...&lt;br&gt;  public Demo {&lt;br&gt;    s = &amp;quot;Initial Value&amp;quot;;&lt;br&gt;  }&lt;br&gt;  ...&lt;br&gt;}&lt;br&gt;而非&lt;br&gt;s = new String(&amp;quot;Initial Value&amp;quot;);&lt;br&gt;后者每次都会调用构造器，生成新对象，性能低下且内存开销大，并且没有意义，因为String对象不可改变，所以对于内容相同的字符串，只要一个String对象来表示就可以了。也就说，多次调用上面的构造器创建多个对象，他们的String类型属性s都指向同一个对象。&lt;br&gt;上面的结论还基于这样一个事实：对于字符串常量，如果内容相同，Java认为它们代表同一个String对象。而用关键字new调用构造器，总是会创建一个新的对象，无论内容是否相同。&lt;br&gt;至于为什么要把String类设计成不可变类，是它的用途决定的。其实不只String，很多Java标准类库中的类都是不可变的。在开发一个系统的时候，我们有时候也需要设计不可变类，来传递一组相关的值，这也是面向对象思想的体现。不可变类有一些优点，比如&lt;font color="#ff9900"&gt;因为它的对象是只读的，所以多线程并发访问也不会有任何问题&lt;/font&gt;。当然也有一些缺点，比如每个不同的状态都要一个对象来代表，可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本，即StringBuffer。&lt;br&gt;&lt;br&gt;&lt;b&gt;问题四：&lt;/b&gt;&lt;span style="color:red"&gt;final关键字到底修饰了什么？&lt;/span&gt;&lt;br&gt;&lt;br&gt;final使得被修饰的变量&amp;quot;不变&amp;quot;，但是由于对象型变量的本质是“引用”，使得“不变”也有了两种含义：引用本身的不变，和引用指向的对象不变。&lt;br&gt;&lt;br&gt;引用本身的不变：&lt;br&gt;final StringBuffer a=new StringBuffer(&amp;quot;immutable&amp;quot;);&lt;br&gt;final StringBuffer b=new StringBuffer(&amp;quot;not immutable&amp;quot;);&lt;br&gt;a=b;//编译期错误&lt;br&gt;&lt;br&gt;引用指向的对象不变：&lt;br&gt;final StringBuffer a=new StringBuffer(&amp;quot;immutable&amp;quot;);&lt;br&gt;a.append(&amp;quot; broken!&amp;quot;); //编译通过&lt;br&gt;&lt;br&gt;可见，&lt;font color="#ff00ff"&gt;final只对引用的“值”(也即它所指向的那个对象的内存地址)有效，它迫使引用只能指向初始指向的那个对象&lt;/font&gt;，改变它的指向会导致编译期错误。至于它所指向的对象的变化，final是不负责的。这很类似==操作符：==操作符只负责引用的“值”相等，至于这个地址所指向的对象内容是否相等，==操作符是不管的。&lt;br&gt;&lt;br&gt;理解final问题有很重要的含义。许多程序漏洞都基于此----final只能保证引用永远指向固定对象，不能保证那个对象的状态不变。在多线程的操作中,一个对象会被多个线程共享或修改，一个线程对对象无意识的修改可能会导致另一个使用此对象的线程崩溃。一个错误的解决方法就是在此对象新建的时候把它声明为final，意图使得它“永远不变”。其实那是徒劳的。&lt;br&gt;&lt;br&gt;&lt;b&gt;问题五：&lt;/b&gt;&lt;span style="color:red"&gt;到底要怎么样初始化！&lt;/span&gt;&lt;br&gt;&lt;br&gt;本问题讨论变量的初始化，所以先来看一下Java中有哪些种类的变量。&lt;br&gt;1. 类的属性，或者叫值域&lt;br&gt;2. 方法里的局部变量&lt;br&gt;3. 方法的参数&lt;br&gt;&lt;br&gt;对于第一种变量，Java虚拟机会自动进行初始化。如果给出了初始值，则初始化为该初始值。如果没有给出，则把它初始化为该类型变量的默认初始值。&lt;br&gt;&lt;br&gt;int类型变量默认初始值为0&lt;br&gt;float类型变量默认初始值为0.0f&lt;br&gt;double类型变量默认初始值为0.0&lt;br&gt;boolean类型变量默认初始值为false&lt;br&gt;char类型变量默认初始值为0(ASCII码)&lt;br&gt;long类型变量默认初始值为0&lt;br&gt;所有对象引用类型变量默认初始值为null，即不指向任何对象。注意数组本身也是对象，所以没有初始化的数组引用在自动初始化后其值也是null。&lt;br&gt;&lt;br&gt;对于两种不同的类属性，static属性与instance属性，初始化的时机是不同的。&lt;font color="#99cc00"&gt;instance属性在创建实例的时候初始化，static属性在类加载，也就是第一次用到这个类的时候初始化&lt;/font&gt;，对于后来的实例的创建，不再次进行初始化。这个问题会在以后的系列中进行详细讨论。&lt;br&gt;&lt;br&gt;&lt;font color="#ff0000"&gt;对于第二种变量，必须明确地进行初始化&lt;/font&gt;。如果再没有初始化之前就试图使用它，编译器会抗议。如果初始化的语句在try块中或if块中，也必须要让它在第一次使用前一定能够得到赋值。也就是说，把初始化语句放在只有if块的条件判断语句中编译器也会抗议，因为执行的时候可能不符合if后面的判断条件，如此一来初始化语句就不会被执行了，这就违反了局部变量使用前必须初始化的规定。但如果在else块中也有初始化语句，就可以通过编译，因为无论如何，总有至少一条初始化语句会被执行，不会发生使用前未被初始化的事情。对于try-catch也是一样，如果只有在try块里才有初始化语句，编译部通过。如果在catch或finally里也有，则可以通过编译。总之，要保证局部变量在使用之前一定被初始化了。所以，一个好的做法是在声明他们的时候就初始化他们，如果不知道要出事化成什么值好，就用上面的默认值吧！&lt;br&gt;&lt;br&gt;其实第三种变量和第二种本质上是一样的，都是方法中的局部变量。只不过作为参数，肯定是被初始化过的，传入的值就是初始值，所以不需要初始化。&lt;br&gt;&lt;br&gt;&lt;b&gt;问题六：&lt;/b&gt;&lt;span style="color:red"&gt;instanceof是什么东东？&lt;/span&gt;&lt;br&gt;&lt;br&gt;instanceof是Java的一个二元操作符，和==，&amp;gt;，&amp;lt;是同一类东东。由于它是由字母组成的，所以也是Java的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例，返回boolean类型的数据。举个例子：&lt;br&gt;&lt;br&gt;String s = &amp;quot;I AM an Object!&amp;quot;;&lt;br&gt;boolean isObject = s instanceof Object;&lt;br&gt;&lt;br&gt;我们声明了一个String对象引用，指向一个String对象，然后用instancof来测试它所指向的对象是否是Object类的一个实例，显然，这是真的，所以返回true，也就是isObject的值为True。&lt;br&gt;instanceof有一些用处。比如我们写了一个处理账单的系统，其中有这样三个类：&lt;br&gt;&lt;br&gt;public class Bill {//省略细节}&lt;br&gt;public class PhoneBill extends Bill {//省略细节}&lt;br&gt;public class GasBill extends Bill {//省略细节}&lt;br&gt;&lt;br&gt;在处理程序里有一个方法，接受一个Bill类型的对象，计算金额。假设两种账单计算方法不同，而传入的Bill对象可能是两种中的任何一种，所以要用instanceof来判断：&lt;br&gt;&lt;br&gt;public double calculate(Bill bill) {&lt;br&gt;  if (bill instanceof PhoneBill) {&lt;br&gt;    //计算电话账单&lt;br&gt;  }&lt;br&gt;  if (bill instanceof GasBill) {&lt;br&gt;    //计算燃气账单&lt;br&gt;  }&lt;br&gt;  ...&lt;br&gt;}&lt;br&gt;这样就可以用一个方法处理两种子类。&lt;br&gt;&lt;br&gt;然而，这种做法通常被认为是没有好好利用面向对象中的多态性。其实上面的功能要求用方法重载完全可以实现，这是面向对象变成应有的做法，避免回到结构化编程模式。只要提供两个名字和返回值都相同，接受参数类型不同的方法就可以了：&lt;br&gt;&lt;br&gt;public double calculate(PhoneBill bill) {&lt;br&gt;  //计算电话账单&lt;br&gt;}&lt;br&gt;&lt;br&gt;public double calculate(GasBill bill) {&lt;br&gt;  //计算燃气账单&lt;br&gt;}&lt;br&gt;&lt;br&gt;所以，使用&lt;font color="#ff0000"&gt;instanceof在绝大多数情况下并不是推荐的做法，应当好好利用多态&lt;/font&gt;。 &lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4841837938742446725&amp;page=RSS%3a+JAVA%e4%b8%ad%e5%be%88%e5%ae%b9%e6%98%93%e6%b7%b7%e6%b7%86%e7%9a%84%e5%9c%b0%e6%96%b9&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=babaozhou.spaces.live.com&amp;amp;GT1=babaozhou"&gt;</description><comments>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!954.entry#comment</comments><guid isPermaLink="true">http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!954.entry</guid><pubDate>Tue, 11 Apr 2006 13:41:04 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://babaozhou.spaces.live.com/blog/cns!4331A9F3BEC0CA85!954/comments/feed.rss</wfw:commentRss><wfw:comment>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!954.entry#comment</wfw:comment><dcterms:modified>2006-04-29T12:14:08Z</dcterms:modified></item><item><title>JAVA中的synchonized</title><link>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!910.entry</link><description>&lt;div&gt;Synchonized..在数据传输或者网络的基础学习中就见过...同步...&lt;/div&gt;
&lt;div&gt;JAVA中的同步也差不多的概念...&lt;/div&gt;
&lt;div&gt;给线程一把&amp;quot;钥匙&amp;quot;,当多个线程进入对象时,只有拿到&amp;quot;钥匙&amp;quot;的线程才能访问该对象,其他线程都要等该线程放弃这把&amp;quot;钥匙&amp;quot;,然后去抢这把&amp;quot;钥匙&amp;quot;,谁拿到谁访问,剩下的继续等&lt;/div&gt;
&lt;div&gt;声明方法&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;public synchonized void store_in()&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;一个很容易说清楚的例子: 仓库&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;往仓库里放东西和取东西.只有仓库里有东西才能被取走&lt;/div&gt;
&lt;div&gt;如果不声明为同步..就可能会出现仓库里没东西还是在被不停&amp;quot;取走&amp;quot;....&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4841837938742446725&amp;page=RSS%3a+JAVA%e4%b8%ad%e7%9a%84synchonized&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=babaozhou.spaces.live.com&amp;amp;GT1=babaozhou"&gt;</description><comments>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!910.entry#comment</comments><guid isPermaLink="true">http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!910.entry</guid><pubDate>Sat, 11 Feb 2006 13:25:50 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://babaozhou.spaces.live.com/blog/cns!4331A9F3BEC0CA85!910/comments/feed.rss</wfw:commentRss><wfw:comment>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!910.entry#comment</wfw:comment><dcterms:modified>2006-04-29T12:24:25Z</dcterms:modified></item><item><title>Java thread</title><link>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!798.entry</link><description>&lt;div&gt;
&lt;div&gt;最近研究了下Java里thread的东西...&lt;/div&gt;
&lt;div&gt;有点头痛...&lt;/div&gt;
&lt;p align=center&gt;&lt;img src="http://tinypic.com/esrn5y.jpg"&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;去Java论坛里专门看了些强人门的解释..概念是能大致理解..&lt;/div&gt;
&lt;div&gt;但是还是用的不好..&lt;/div&gt;
&lt;div&gt;或者说用的太死..&lt;/div&gt;
&lt;div&gt;人家怎么写我就怎么写..没有创新意识&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;不知道国外那帮程序强人是怎么学的,能创新出那么多难以想到的东西..其实基础的东西大家学的都一样..&lt;/div&gt;
&lt;div&gt;又说到中国教育问题了..&lt;/div&gt;
&lt;div&gt;不想提..那帮老头老太婆一天不死,就没必要提了&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;现在又得考试了..JAVA的东西得先放放了.&lt;/div&gt;
&lt;div&gt;复习...最后一次为这种完全没有用的垃圾考试复习&lt;/div&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4841837938742446725&amp;page=RSS%3a+Java+thread&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=babaozhou.spaces.live.com&amp;amp;GT1=babaozhou"&gt;</description><comments>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!798.entry#comment</comments><guid isPermaLink="true">http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!798.entry</guid><pubDate>Fri, 21 Oct 2005 08:04:54 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://babaozhou.spaces.live.com/blog/cns!4331A9F3BEC0CA85!798/comments/feed.rss</wfw:commentRss><wfw:comment>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!798.entry#comment</wfw:comment><dcterms:modified>2006-04-29T12:31:42Z</dcterms:modified></item><item><title>Inheritance and composition</title><link>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!782.entry</link><description>&lt;div&gt;这2个都是典型OOP特点之一..&lt;/div&gt;
&lt;div&gt;但是很多人会困扰到底我该用什么,我学JAVA,C++的时候,老师都反复强调了Inheritance的重要性..但是实际上呢??除了老师那点assignment规定要用到之外..其余的我不太会用到它.更多的则是composition..&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;我是觉得如果你不清楚inheritance是否在你coding里处于一个极为重要的地位的时候,不要滥用它..一个方法就是你是否必须要用到upcasting..如果是.那么你必须用inheritance,反之就不用&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;不过inheritance依然在OOP中占有极重要的地位..个人认为重要是在那些开发library,encapsulation的时候&lt;/div&gt;
&lt;div&gt; &lt;/div&gt;
&lt;div&gt;对于一般人来说,考虑清楚是否需要upcasting,就能很清楚的知道自己该用什么了&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4841837938742446725&amp;page=RSS%3a+Inheritance+and+composition&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=babaozhou.spaces.live.com&amp;amp;GT1=babaozhou"&gt;</description><comments>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!782.entry#comment</comments><guid isPermaLink="true">http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!782.entry</guid><pubDate>Mon, 03 Oct 2005 16:19:44 GMT</pubDate><slash:comments>0</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://babaozhou.spaces.live.com/blog/cns!4331A9F3BEC0CA85!782/comments/feed.rss</wfw:commentRss><wfw:comment>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!782.entry#comment</wfw:comment><dcterms:modified>2006-04-29T12:42:49Z</dcterms:modified></item><item><title>Java的synchronized()</title><link>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!732.entry</link><description>&lt;div&gt;&lt;font color="#333333"&gt;对于线程的概念,很多人可能都是很模糊..&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font color="#333333"&gt;对于Java中的synchronized(),本身就是一个非常难于理解的概念&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font color="#333333"&gt;在JAVA论坛闲逛的时候无意中发现一篇关于synchronized()的争论&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font color="#333333"&gt;&lt;/font&gt; &lt;/div&gt;
&lt;div&gt;&lt;font color="#333333"&gt;我在这里贴出几种解释,对于刚刚接触到线程,synchronized()的JAVA学习者们一点帮助&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font color="#333333"&gt;&lt;/font&gt; &lt;/div&gt;
&lt;div&gt;&lt;font color="#333333"&gt;在java中,每个对象只有一个相应的monitor,一个mutex,而每一个monitor都可以有多个“doors”可以进入,即,同一个monitor中被守护的代码可以在不同的地方,因为同一个对象可以出现在不同的代码段,只要mutex锁定的对象是同一个, 每个入口都用Synchronized关键字表明,当一个线程通过了Synchronized关键字,它就所住了该monitor所有的door. 因此是mutex定义了monitor而不是代码.&lt;br&gt;&lt;br&gt;比如:&lt;br&gt;飞机只有一个洗手间,很多乘客都想进去,但一次只能进去一个人,其他人必须等待,此时有如下对应关系:&lt;br&gt;飞机:object &lt;br&gt;乘客:各个线程 &lt;br&gt;洗手间:monitor &lt;br&gt;洗手间门上的锁:mutex&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font color="#333333"&gt;&lt;/font&gt; &lt;/div&gt;
&lt;div&gt;&lt;font color="#333333"&gt;&lt;/font&gt; &lt;/div&gt;
&lt;div&gt;&lt;font color="#333333"&gt;有人给出的解释是 &lt;br&gt;&amp;quot;&lt;/font&gt;&lt;font color="#ff0000"&gt;当一段代码会执行得非常快,其实根本可以不需要用同步描述的,当你的代码段比较长,并且相当重要,那么就会需要了.&amp;quot;&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font color="#333333"&gt;&lt;/font&gt; &lt;/div&gt;
&lt;div&gt;&lt;font color="#333333"&gt;其实这样的理解不太正确.&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font color="#0000ff"&gt;要理解同步的本质,就要明白操作系统是如何执行程序&lt;/font&gt;&lt;font color="#0000ff"&gt;的.对于进程和线程,操作系统设计者的目的是从概念上简化编程模型,使编程&lt;/font&gt;&lt;font color="#0000ff"&gt;显得更自然,更符合思维习惯.操作系统设计者为使用进程和线程来编程提供了&lt;/font&gt;&lt;font color="#0000ff"&gt;一个假设条件,即进程和线程各自的执行流是连贯的,没有任何断续执行的现象.&lt;/font&gt;&lt;font color="#0000ff"&gt;但是实际上(以单CPU系统为例),从系统实现的底层看起来,这些进程和线程&lt;/font&gt;&lt;font color="#0000ff"&gt;的执行流是支离破碎的,并且这些破碎的执行流片断被CPU以某种方式(即操作系&lt;/font&gt;&lt;font color="#0000ff"&gt;统的调度程序)组合成一个串行的,混合在一起的执行流,以此推动操作系统不&lt;/font&gt;&lt;font color="#0000ff"&gt;断运行.问题就在这里,同步问题的根源就在于看起来连贯的执行流实际上是破&lt;/font&gt;&lt;font color="#0000ff"&gt;碎的.破碎的执行流会造成什么问题呢?比如有两个执行流A和B,A对现在需要对&lt;/font&gt;&lt;font color="#0000ff"&gt;一个数据进行操作,但是这个操作被分割成了相连的两块执行流碎片,而另外一&lt;/font&gt;&lt;font color="#0000ff"&gt;个执行流B本来需要在A完成这个数据操作之后才能取到这个数据然后进行它自己&lt;/font&gt;&lt;font color="#0000ff"&gt;的计算,可是由于A对数据本应完整的操作被分割成了相连的两部分,然后CPU在A&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font color="#0000ff"&gt;的碎片之间插入了B的取数这样一个执行流片断.这样一来,程序的行为就不符合&lt;/font&gt;&lt;font color="#0000ff"&gt;我们原本所设想的那样,程序运行的结果就会出错.同步的本质就是让CPU不要把&lt;/font&gt;&lt;font color="#0000ff"&gt;A的数据操作分割开,不让B有机会错误的横插一杠进来扰乱A,以保证正确的执行&lt;/font&gt;&lt;font color="#0000ff"&gt;顺序,这样才能得到正确的我们想要的结果.不管你看起来执行得多么快的操作,&lt;/font&gt;&lt;font color="#0000ff"&gt;都有可能被操作系统打断,从而形成碎片,导致无法预料的结果.所以,应该&lt;/font&gt;&lt;font color="#0000ff"&gt;在需要精确时序的地方使用同步,而不是根据这个操作快不快来判断.所谓需要&lt;/font&gt;&lt;font color="#0000ff"&gt;精确时序场合,其实就是数据的使用或操作的执行存在依赖性的地方,对于代码&lt;/font&gt;&lt;font color="#0000ff"&gt;来说,就是完成某项操作时对参与的进程或线程执行顺序存在依赖性的代码块.&lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font color="#333333"&gt;&lt;/font&gt; &lt;/div&gt;
&lt;div&gt;&lt;font color="#333333"&gt;记住synchronized只是阻止不同线程访问资源的(在同一个线程是无效的) &lt;/font&gt;&lt;/div&gt;
&lt;div&gt;&lt;font color="#333333"&gt;或者可以说JAVA的锁是可以重入的 
&lt;p&gt;&lt;font color="#333333"&gt;比如:&lt;/font&gt;
&lt;p&gt;&lt;font color="#333333"&gt;&lt;span style="font-weight:bold;color:#990066"&gt;class&lt;/span&gt; Test&lt;span style="color:#000000"&gt;{&lt;/span&gt; &lt;br&gt;&lt;br&gt;      &lt;span style="font-weight:bold;color:#990066"&gt;public&lt;/span&gt; synchronized &lt;span style="font-weight:bold;color:#990066"&gt;void&lt;/span&gt; A&lt;span style="color:#000000"&gt;(&lt;/span&gt;&lt;span style="color:#000000"&gt;)&lt;/span&gt;&lt;span style="color:#000000"&gt;{&lt;/span&gt; &lt;br&gt;           B&lt;span style="color:#000000"&gt;(&lt;/span&gt;&lt;span style="color:#000000"&gt;)&lt;/span&gt;; &lt;br&gt;           .... &lt;br&gt;      &lt;span style="color:#000000"&gt;}&lt;/span&gt; &lt;br&gt;&lt;br&gt;&lt;br&gt;      &lt;span style="font-weight:bold;color:#990066"&gt;public&lt;/span&gt; synchronized &lt;span style="font-weight:bold;color:#990066"&gt;void&lt;/span&gt; B&lt;span style="color:#000000"&gt;(&lt;/span&gt;&lt;span style="color:#000000"&gt;)&lt;/span&gt;&lt;span style="color:#000000"&gt;{&lt;/span&gt; &lt;br&gt;          A&lt;span style="color:#000000"&gt;(&lt;/span&gt;&lt;span style="color:#000000"&gt;)&lt;/span&gt;; &lt;br&gt;          .... &lt;br&gt;      &lt;span style="color:#000000"&gt;}&lt;/span&gt; &lt;br&gt;&lt;br&gt;      &lt;span style="font-weight:bold;color:#990066"&gt;public&lt;/span&gt; &lt;span style="font-weight:bold;color:#990066"&gt;static&lt;/span&gt; &lt;span style="font-weight:bold;color:#990066"&gt;void&lt;/span&gt; main&lt;span style="color:#000000"&gt;(&lt;/span&gt;&lt;span style="color:#aaaadd"&gt;String&lt;/span&gt;&lt;span style="color:#000000"&gt;[&lt;/span&gt;&lt;span style="color:#000000"&gt;]&lt;/span&gt; args&lt;span style="color:#000000"&gt;)&lt;/span&gt;&lt;span style="color:#000000"&gt;{&lt;/span&gt; &lt;br&gt;          &lt;span style="font-weight:bold;color:#990066"&gt;new&lt;/span&gt; Test&lt;span style="color:#000000"&gt;(&lt;/span&gt;&lt;span style="color:#000000"&gt;)&lt;/span&gt;.&lt;span style="color:#000000"&gt;B&lt;/span&gt;&lt;span style="color:#000000"&gt;(&lt;/span&gt;&lt;span style="color:#000000"&gt;)&lt;/span&gt;;      &lt;br&gt;      &lt;span style="color:#000000"&gt;}&lt;/span&gt; &lt;br&gt;&lt;span style="color:#000000"&gt;}&lt;/span&gt;&lt;/font&gt;
&lt;p&gt;&lt;font color="#333333"&gt;&lt;span style="color:#000000"&gt;&lt;span&gt;是不会死锁的(不过小心进入死循环); &lt;/span&gt;&lt;/span&gt;
&lt;div&gt;一般来说&lt;/div&gt;
&lt;div&gt;非静态的synchronized()用的是对象锁.  object lock&lt;br&gt;静态的 synchronized()用的是类锁. class lock&lt;br&gt;&lt;/div&gt;&lt;/font&gt;&lt;/font&gt;&lt;font color="#333333"&gt;&lt;/font&gt;&lt;/div&gt;&lt;img src="http://c.services.spaces.live.com/CollectionWebService/c.gif?cid=4841837938742446725&amp;page=RSS%3a+Java%e7%9a%84synchronized()&amp;referrer=" width="1px" height="1px" border="0" alt=""&gt;&lt;img style="position:absolute" alt="" width="0px" height="0px" src="http://c.live.com/c.gif?NC=31263&amp;amp;NA=1149&amp;amp;PI=73329&amp;amp;RF=&amp;amp;DI=3919&amp;amp;PS=85545&amp;amp;TP=babaozhou.spaces.live.com&amp;amp;GT1=babaozhou"&gt;</description><comments>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!732.entry#comment</comments><guid isPermaLink="true">http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!732.entry</guid><pubDate>Sat, 27 Aug 2005 08:11:52 GMT</pubDate><slash:comments>1</slash:comments><msn:type>blogentry</msn:type><live:type>blogentry</live:type><live:typelabel>Blog entry</live:typelabel><wfw:commentRss>http://babaozhou.spaces.live.com/blog/cns!4331A9F3BEC0CA85!732/comments/feed.rss</wfw:commentRss><wfw:comment>http://babaozhou.spaces.live.com/Blog/cns!4331A9F3BEC0CA85!732.entry#comment</wfw:comment><dcterms:modified>2006-04-29T12:57:05Z</dcterms:modified></item></channel></rss>