<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Kings &#187; 读书</title>
	<atom:link href="http://welog.org/blog/category/learning/feed" rel="self" type="application/rss+xml" />
	<link>http://welog.org</link>
	<description>@exploring, thinking @Web2.0 @Twitter @Social Media Marketing @ROR</description>
	<lastBuildDate>Thu, 27 Oct 2011 02:09:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>will_paginate and ajax in rails 3</title>
		<link>http://welog.org/blog/1147</link>
		<comments>http://welog.org/blog/1147#comments</comments>
		<pubDate>Sun, 15 May 2011 02:52:13 +0000</pubDate>
		<dc:creator>King</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://welog.org/?p=1147</guid>
		<description><![CDATA[在rails3项目中出现分页内容不能加载Ajax情况，开始以为是升级rails 3的插件问题，记录一下解决办法。 1.view 显示层(如ask/show.html.erb) < div id="queue"> < %= render :partial => &#8216;queue&#8217; %> < script> $(document).ready(function() { $(&#8216;.pagination a&#8217;).attr(&#8216;data-remote&#8217;, &#8216;true&#8217;); }); 2.controller (如ask_controller.rb) def show @user = User.find(params[:id]) @queue_items = @user.queue_items.with_state(:pending).paginate(:page => params[:queue_page] &#124;&#124; 1, :per_page => 1) respond_to do &#124;format&#124; format.html format.js end end 3.js template $(&#8216;#queue&#8217;).html(&#8216;< %=escape_javascript render :partial => &#8220;queue&#8221; %>&#8217;); &#8230; <a href="http://welog.org/blog/1147">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>在rails3项目中出现分页内容不能加载Ajax情况，开始以为是升级rails 3的插件问题，记录一下解决办法。<br />
1.view 显示层(如ask/show.html.erb)<br />
< div id="queue"> < %= render :partial => &#8216;queue&#8217; %><br />
< script><br />
$(document).ready(function() {<br />
    $(&#8216;.pagination a&#8217;).attr(&#8216;data-remote&#8217;, &#8216;true&#8217;);<br />
});</p>
<p>2.controller (如ask_controller.rb)</p>
<p>def show<br />
  @user = User.find(params[:id])<br />
  @queue_items = @user.queue_items.with_state(:pending).paginate(:page => params[:queue_page] || 1, :per_page => 1)<br />
  respond_to do |format|<br />
    format.html<br />
    format.js<br />
  end<br />
end</p>
<p>3.js template</p>
<p>$(&#8216;#queue&#8217;).html(&#8216;< %=escape_javascript render :partial => &#8220;queue&#8221; %>&#8217;);<br />
$(&#8216;.pagination a&#8217;).attr(&#8216;data-remote&#8217;, &#8216;true&#8217;);</p>
<p>还有一种在Rails3中的方法也一并记录如下。(via:火哥的零碎)</p>
<p>class RemoteLinkRenderer < WillPaginate::ViewHelpers::LinkRenderer<br />
  def prepare(collection, options, template)<br />
    @remote = options.delete(:remote) || { }<br />
    super<br />
  end</p>
<p>  def link(text, target, attributes = {})<br />
    if target.is_a? Fixnum<br />
      attributes[:rel] = rel_value(target)<br />
      target = url(target)<br />
    end<br />
    attributes[:href] = target<br />
    #    page_attr = { :page => target }<br />
    @template.link_to( text.to_s.html_safe, target, :remote => true )<br />
  end<br />
end</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/1147/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>2008年4月18日</title>
		<link>http://welog.org/blog/719</link>
		<comments>http://welog.org/blog/719#comments</comments>
		<pubDate>Sun, 20 Apr 2008 12:56:35 +0000</pubDate>
		<dc:creator>King</dc:creator>
				<category><![CDATA[读书]]></category>
		<category><![CDATA[家乐福]]></category>

		<guid isPermaLink="false">http://welog.org/?p=719</guid>
		<description><![CDATA[去不去家乐福，这已经成为了最近网络上人人要表态的话题。晚上和几位老师也聊了很多，能理解大家的这种抵制情绪，当共同利益受损时迫切地想要寻找一种伤害者看得到的方式，来表明自己的姿态。在西藏问题上，涉及的因素太多，多听听不同的声音，多去思考。这样才能找到问题的根本，找到应对的办法。 当看到&#8221;武汉家乐福的柜台被砸得一塌糊涂，看到一条留言说：最后，收拾残局的，还是一群月薪800元的家乐福中国职员。 &#8220;,当看到金晶，一个几天前还是“民族英雄，最美的女神”，却因为说了 不赞成抵制法国家乐福 的话，就被批为汉奸。这就是爱国的表达形式吗？我只想建议在&#8221;抵制&#8221;之前稍微使用一下自己的智商，冷静的理性的对待，这样下去抵抗西方没实现反而自己人和自己人先掐起脖子来&#8230;&#8230;]]></description>
			<content:encoded><![CDATA[<p>去不去家乐福，这已经成为了最近网络上人人要表态的话题。晚上和几位老师也聊了很多，能理解大家的这种抵制情绪，当共同利益受损时迫切地想要寻找一种伤害者看得到的方式，来表明自己的姿态。在西藏问题上，涉及的因素太多，多听听不同的声音，多去思考。这样才能找到问题的根本，找到应对的办法。<br />
当看到&#8221;<strong>武汉家乐福的柜台被砸得一塌糊涂，看到一条留言说：最后，收拾残局的，还是一群月薪800元的家乐福中国职员。</strong> &#8220;,当看到金晶，一个几天前还是“民族英雄，最美的女神”，却因为说了 <a href="http://news.163.com/08/0416/14/49LIQSV60001124J.html">不赞成抵制法国家乐福</a> 的话，就被批为汉奸。这就是爱国的表达形式吗？我只想建议在&#8221;抵制&#8221;之前稍微使用一下自己的智商，冷静的理性的对待，这样下去抵抗西方没实现反而自己人和自己人先掐起脖子来&#8230;&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/719/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>海底光缆修复了?</title>
		<link>http://welog.org/blog/558</link>
		<comments>http://welog.org/blog/558#comments</comments>
		<pubDate>Mon, 29 Jan 2007 02:24:00 +0000</pubDate>
		<dc:creator>King</dc:creator>
				<category><![CDATA[生活]]></category>
		<category><![CDATA[读书]]></category>
		<category><![CDATA[修复]]></category>
		<category><![CDATA[光缆]]></category>
		<category><![CDATA[地震]]></category>

		<guid isPermaLink="false">http://welog.org/blog/558</guid>
		<description><![CDATA[从昨天开始，不用代理也能正常访问我的BLOG了。且其它一此国外网站都可以访问，看来经过一个月的等待不用再忍受龟速一样的网络了。(具体是否开通也没听到电信的说法，只能通过这几点做的判断吧) 人有时候就是这样，什么东西失去了，才知道它的好。因为这次的海底光缆中断，导致许多国外的网站及服务无法使用，我想有不少人都会得上地震后遗症的。也只有这个时候我们才知道这条细细的连通世界的光缆有多么重要。 这次的电信部门不知道干嘛去了，这么大个表彰的机会也放弃了，可惜呀，实在可惜了&#8230;&#8230; 就像FENNG说的：“上帝说，网络通。就通; 上帝说，没时间修。那么用户就只有等; 上帝说，好了我也不告诉你。我们就不知道。” 上周我的这个BLOG已经升级到Wordpress2.1版本，由于网络的原因很多插件及需要修改的东西没有来得及修正。这段时间有必要将之做一次全面的调整及优化，同时BLOG也会正常更新&#8230;&#8230;.]]></description>
			<content:encoded><![CDATA[<p>从昨天开始，不用代理也能正常访问我的BLOG了。且其它一此国外网站都可以访问，看来经过一个月的等待不用再忍受龟速一样的网络了。(具体是否开通也没听到电信的说法，只能通过这几点做的判断吧)<br />
人有时候就是这样，什么东西失去了，才知道它的好。因为这次的海底光缆中断，导致许多国外的网站及服务无法使用，我想有不少人都会得上<a href="http://www.caozenghui.cn/?p=115">地震后遗症</a>的。也只有这个时候我们才知道这条细细的连通世界的光缆有多么重要。<br />
这次的电信部门不知道干嘛去了，这么大个表彰的机会也放弃了，可惜呀，实在可惜了&#8230;&#8230;<br />
就像FENNG说的：“上帝说，网络通。就通; 上帝说，没时间修。那么用户就只有等; 上帝说，好了我也不告诉你。我们就不知道。”</p>
<p>上周我的这个BLOG已经升级到Wordpress2.1版本，由于网络的原因很多插件及需要修改的东西没有来得及修正。这段时间有必要将之做一次全面的调整及优化，同时BLOG也会正常更新&#8230;&#8230;.</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/558/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Happy blogDay 2006</title>
		<link>http://welog.org/blog/447</link>
		<comments>http://welog.org/blog/447#comments</comments>
		<pubDate>Thu, 31 Aug 2006 06:24:49 +0000</pubDate>
		<dc:creator>King</dc:creator>
				<category><![CDATA[技术]]></category>
		<category><![CDATA[生活]]></category>
		<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/447</guid>
		<description><![CDATA[今天是BlogDay！国内相关的文字很少，我也是看到这篇文章才想起8月31日这个日子。 什么是BlogDay BlogDay 起源于博客们（Bloggers）认为自己应该有一个专属的节日，用以认识其它来自于不同国度或拥有各种不同嗜好、兴趣的博客。在 BlogDay当天，所有参与活动的博客们应该在自己的站上推荐五个具有特色的博客（Blogs）给所有来访的朋友，藉此和大家分享更多崭新而有趣的博客。 谁提出BlogDay 你有否注意日期3108（8月31日）这样的写法看起来很像“Blog”这个词。是的，Nir Ofir首先在以色列的一次Blog会议上一边涂鸦一边发现到这个象形，并由此产生出将象形与节日结合的创意，设立一个庆祝日——Blogday，作为博客群体的节日，甚至希望它能成为今后全球的传统节日。这个创意不亚于n年前同样因创意而诞生的Blog，而且创意者的本意不仅仅是单纯设立一个节日，而是号召大家在8月31日这一天都发表一篇网志，让人们发现一些优秀的Blog，并相互推广。 在BlogDay做什么 在八月三十一日这一天内，全世界参与活动的网民都会发表一篇帖子推荐五个新颖的博客，而且最好这五个部落格的内容可能是来自不同的文化、观点和型态。而所有造访的朋友都可以在八月三十一日当天发现自己前所未知的博客，藉此认识更多博客并为这些新发现而庆祝。 1. 找出五个你觉得有趣的新鲜博客。 2. 在2005年的BlogDay当天，留言给这五位博客的主人，告知你推荐了他们的博客。 3. 为推荐的博客写下简短的介绍，并在文中放置这些链结。 4. 在8月31日当天张贴上推荐的帖子。5. 並且加上BlogDay的標籤（Tag）： http://technorati.com/tag/BlogDay2006/ ，同時連結到BlogDay 官方網站http://www.blogday.org/ 这是个特别的日子，是我们所有BLOGGER共同的节日，写下此文时已经是8.31:2点45分了，没有做什么准备不打算做推荐了，就以此文和众BLOGER同庆吧。 BTW:不知道BLOGDAY是怎么了，打开时出现Error establishing a database connection的错误&#8230;.]]></description>
			<content:encoded><![CDATA[<p><strong>今天是BlogDay！国内相关的文字很少，我也是看到<a href="http://internet.solidot.org/article.pl?sid=06/08/31/0347243&#038;from=rss" target="_blank">这篇</a>文章才想起8月31日这个日子。</strong></p>
<blockquote><p><strong>什么是BlogDay<br />
</strong>BlogDay 起源于博客们（Bloggers）认为自己应该有一个专属的节日，用以认识其它来<img src="http://aycu03.webshots.com/image/2362/1861297056832685428_rs.jpg" align="right" />自于不同国度或拥有各种不同嗜好、兴趣的博客。在 BlogDay当天，所有参与活动的博客们应该在自己的站上推荐五个具有特色的博客（Blogs）给所有来访的朋友，藉此和大家分享更多崭新而有趣的博客。</p></blockquote>
<blockquote><p><strong>谁提出BlogDay<br />
</strong>你有否注意日期3108（8月31日）这样的写法看起来很像“Blog”这个词。是的，Nir Ofir首先在以色列的一次Blog会议上一边涂鸦一边发现到这个象形，并由此产生出将象形与节日结合的创意，设立一个庆祝日——Blogday，作为博客群体的节日，甚至希望它能成为今后全球的传统节日。这个创意不亚于n年前同样因创意而诞生的Blog，而且创意者的本意不仅仅是单纯设立一个节日，而是号召大家在8月31日这一天都发表一篇网志，让人们发现一些优秀的Blog，并相互推广。</p></blockquote>
<blockquote><p><strong>在BlogDay做什么<br />
</strong>在八月三十一日这一天内，全世界参与活动的网民都会发表一篇帖子推荐五个新颖的博客，而且最好这五个部落格的内容可能是来自不同的文化、观点和型态。而所有造访的朋友都可以在八月三十一日当天发现自己前所未知的博客，藉此认识更多博客并为这些新发现而庆祝。</p>
<p> 1. 找出五个你觉得有趣的新鲜博客。<br />
 2. 在2005年的BlogDay当天，留言给这五位博客的主人，告知你推荐了他们的博客。<br />
 3. 为推荐的博客写下简短的介绍，并在文中放置这些链结。<br />
 4. 在8月31日当天张贴上推荐的帖子。5. 並且加上BlogDay的標籤（Tag）： <a href="http://technorati.com/tag/BlogDay2006/">http://technorati.com/tag/BlogDay2006/</a> ，同時連結到BlogDay 官方網站<a href="http://www.blogday.org/">http://www.blogday.org/</a></p></blockquote>
<p>这是个特别的日子，是我们所有BLOGGER共同的节日，写下此文时已经是8.31:2点45分了，没有做什么准备不打算做推荐了，就以此文和众BLOGER同庆吧。<br />
BTW:不知道<a href="http://www.blogday.org/" target="_blank">BLOGDAY</a>是怎么了，打开时出现<strong>Error establishing a database connection</strong>的错误&#8230;.</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/447/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Aboslute 布局暂存&#8230;.</title>
		<link>http://welog.org/blog/395</link>
		<comments>http://welog.org/blog/395#comments</comments>
		<pubDate>Sat, 25 Feb 2006 22:41:51 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/aboslute-%e5%b8%83%e5%b1%80%e6%9a%82%e5%ad%98/</guid>
		<description><![CDATA[暂存，待整理！ 定义座标作为限制(x,y) and (w,h) coordinates: [CODE_LITE] private int x, y, width, height; public static final int ADAPT = -1; public XYConstraints(int x, int y, int width, int height) { this.x = x; this.y = y; this.width = width; this.height = height; } [/CODE_LITE] 适应常数可能被使用为宽度和高度以便布局经理使用宽度并且高度定义由组分(got from get&#8230;..Size()).必须实施LayoutManager2 和所有方法被定义: 首先我们假设我们的布局不需要任何特别对准线, 对上部左角落总将被排列: [CODE_LITE] public float getLayoutAlignmentX(Container arg0) { &#8230; <a href="http://welog.org/blog/395">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>暂存，待整理！<br />
定义座标作为限制(x,y) and (w,h) coordinates:<br />
[CODE_LITE]<br />
 private int x, y, width, height;</p>
<p>    public static final int ADAPT = -1;</p>
<p>    public XYConstraints(int x, int y, int width, int height) {<br />
        this.x = x;<br />
        this.y = y;<br />
        this.width = width;<br />
        this.height = height;<br />
    }<br />
[/CODE_LITE]<br />
适应常数可能被使用为宽度和高度以便布局经理使用宽度并且高度定义由组分(got from get&#8230;..Size()).必须实施LayoutManager2 和所有方法被定义:<br />
首先我们假设我们的布局不需要任何特别对准线, 对上部左角落总将被排列:<br />
[CODE_LITE]<br />
 public float getLayoutAlignmentX(Container arg0) {<br />
        return 0;<br />
    }</p>
<p>    public float getLayoutAlignmentY(Container arg0) {<br />
        return 0;<br />
    }<br />
[/CODE_LITE]<br />
1) 审阅所有分组和增加他们的X 和W 座标和Y 和H 座标。<br />
2) 如果分组使用适应常数, 使用对应的方法在分组(得到..大小) 。<br />
[B]E.g. the getPreferredSize method:[/B]<br />
[CODE_LITE]<br />
public Dimension preferredLayoutSize(Container arg0) {<br />
        int rightBound = 0;<br />
        int bottomBound = 0;</p>
<p>        for (Iterator iter = constraints.keySet().iterator(); iter.hasNext();) {<br />
            Component comp = (Component) iter.next();<br />
            XYConstraints constraint = (XYConstraints) constraints.get(comp);<br />
            Dimension size = comp.getPreferredSize();<br />
            int width = constraint.getWidth();<br />
            if (width == XYConstraints.ADAPT) {<br />
                width = size.width;<br />
            }<br />
            if ((constraint.getX() + width) &gt; rightBound) {<br />
                rightBound = constraint.getX() + width;<br />
            }<br />
            int height = constraint.getHeight();<br />
            if (height == XYConstraints.ADAPT) {<br />
                height = size.height;<br />
            }<br />
            if ((constraint.getY() + height) &gt; bottomBound) {<br />
                bottomBound = constraint.getX() + height;<br />
            }<br />
        }<br />
        return new Dimension(rightBound, bottomBound);<br />
    }<br />
[/CODE_LITE]<br />
因为我们不存储什么, 我们不需要实施其它的invalidateLayout:<br />
[CODE_LITE]<br />
public void invalidateLayout(Container arg0) {<br />
        // No information cached<br />
    }<br />
[/CODE_LITE]<br />
现在我们来到有趣的部份,首先我们需要实施方法增加分组以限制来布局。<br />
有二个方法: 一以限制代表作为对象和其他作为串。 串一个, 我们将解码串对对象和将要求第一方法:<br />
[CODE_LITE]<br />
 public void addLayoutComponent(String constraintString, Component component) {<br />
        XYConstraints constraint = new XYConstraints(0, 0, XYConstraints.ADAPT, XYConstraints.ADAPT);<br />
        String[] args = constraintString.split(&#8220;;&#8221;);<br />
        for (int i = 0; i<br />
暂存，待整理！<br />
定义座标作为限制(x,y) and (w,h) coordinates:<br />
[CODE_LITE]<br />
 private int x, y, width, height;</p>
<p>    public static final int ADAPT = -1;</p>
<p>    public XYConstraints(int x, int y, int width, int height) {<br />
        this.x = x;<br />
        this.y = y;<br />
        this.width = width;<br />
        this.height = height;<br />
    }<br />
[/CODE_LITE]<br />
适应常数可能被使用为宽度和高度以便布局经理使用宽度并且高度定义由组分(got from get&#8230;..Size()).必须实施LayoutManager2 和所有方法被定义:<br />
首先我们假设我们的布局不需要任何特别对准线, 对上部左角落总将被排列:<br />
[CODE_LITE]<br />
 public float getLayoutAlignmentX(Container arg0) {<br />
        return 0;<br />
    }</p>
<p>    public float getLayoutAlignmentY(Container arg0) {<br />
        return 0;<br />
    }<br />
[/CODE_LITE]<br />
1) 审阅所有分组和增加他们的X 和W 座标和Y 和H 座标。<br />
2) 如果分组使用适应常数, 使用对应的方法在分组(得到..大小) 。<br />
[B]E.g. the getPreferredSize method:[/B]<br />
[CODE_LITE]<br />
public Dimension preferredLayoutSize(Container arg0) {<br />
        int rightBound = 0;<br />
        int bottomBound = 0;</p>
<p>        for (Iterator iter = constraints.keySet().iterator(); iter.hasNext();) {<br />
            Component comp = (Component) iter.next();<br />
            XYConstraints constraint = (XYConstraints) constraints.get(comp);<br />
            Dimension size = comp.getPreferredSize();<br />
            int width = constraint.getWidth();<br />
            if (width == XYConstraints.ADAPT) {<br />
                width = size.width;<br />
            }<br />
            if ((constraint.getX() + width) &gt; rightBound) {<br />
                rightBound = constraint.getX() + width;<br />
            }<br />
            int height = constraint.getHeight();<br />
            if (height == XYConstraints.ADAPT) {<br />
                height = size.height;<br />
            }<br />
            if ((constraint.getY() + height) &gt; bottomBound) {<br />
                bottomBound = constraint.getX() + height;<br />
            }<br />
        }<br />
        return new Dimension(rightBound, bottomBound);<br />
    }<br />
[/CODE_LITE]<br />
因为我们不存储什么, 我们不需要实施其它的invalidateLayout:<br />
[CODE_LITE]<br />
public void invalidateLayout(Container arg0) {<br />
        // No information cached<br />
    }<br />
[/CODE_LITE]<br />
现在我们来到有趣的部份,首先我们需要实施方法增加分组以限制来布局。<br />
有二个方法: 一以限制代表作为对象和其他作为串。 串一个, 我们将解码串对对象和将要求第一方法:<br />
[CODE_LITE]<br />
 public void addLayoutComponent(String constraintString, Component component) {<br />
        XYConstraints constraint = new XYConstraints(0, 0, XYConstraints.ADAPT, XYConstraints.ADAPT);<br />
        String[] args = constraintString.split(&#8220;;&#8221;);<br />
        for (int i = 0; i </p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/395/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>再谈Java中关于乱码问题的解决</title>
		<link>http://welog.org/blog/379</link>
		<comments>http://welog.org/blog/379#comments</comments>
		<pubDate>Sun, 15 Jan 2006 04:40:26 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/%e5%86%8d%e8%b0%88java%e4%b8%ad%e5%85%b3%e4%ba%8e%e4%b9%b1%e7%a0%81%e9%97%ae%e9%a2%98%e7%9a%84%e8%a7%a3%e5%86%b3/</guid>
		<description><![CDATA[&#160;&#160;&#160;&#160;&#160;&#160; 在JSP和java的开发中乱码问题有时候是非常让人头疼的，今天朋友就出了这个问题，发来信息让我帮忙看看。其实java开发者都知道，出现乱码问题有 很多种原因，需要具体问题具体分析，从他和我说的配置环境是JSP（视图）+Tomcat（模型）+Servlet（业务处理），在本地的调试环境 （Tomcat+Resin）下出现乱码问题。通常我们使用的编码方式都是为GB2312，因为页面中所有的中文都是乱码，所以通过简单的分析出问题的最 有可能出问题的地方就是JSP视图，其次是业务处理部分部分，作为Bean只是用来存储数据的，不可能出现问题。所以得先从下面几种方式开始检查(我不是 高手，一下看不出根本问题的所在)： 第一： 1:在jsp页面加入： &#160; &#60;%@ &#160;page &#160;contentType=&#34;text/html; &#160;charset=gb2312&#34; &#160;%&#62; 2.在JSP页面的最上面&#60;%@的下面添加request.setCharacterEncoding(&#34;gb2312&#34;)，JSP页面接收数据的统一为GB2312编码格式； 3:在servlet里面: &#160; &#160; &#160;public &#160;void &#160;doGet(HttpServletRequest &#160;request, &#160;HttpServletResponse &#160;response) &#160;throws &#160;ServletException, &#160;IOException &#160;{ &#160; &#160; &#160; &#160; &#160;response.setContentType(&#34;text/html; &#160;charset=gb2312&#34;);&#160; 4:以上如果还不行就用如下的方法在数据入库前进行调用： [CODE_LITE] public static String UnicodeToChinese(String s){ try{ if(s==null ¦ ¦s.equals(&#8220;&#8221;)) return &#8220;&#8221;; String newstring=null; newstring=new String(s.getBytes(&#8220;ISO8859_1&#8243;),&#8221;gb2312&#8243;); return newstring; } catch(UnsupportedEncodingException &#8230; <a href="http://welog.org/blog/379">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在JSP和java的开发中乱码问题有时候是非常让人头疼的，今天朋友就出了这个问题，发来信息让我帮忙看看。其实java开发者都知道，出现乱码问题有 很多种原因，需要具体问题具体分析，从他和我说的配置环境是JSP（视图）+Tomcat（模型）+Servlet（业务处理），在本地的调试环境 （Tomcat+Resin）下出现乱码问题。通常我们使用的编码方式都是为GB2312，因为页面中所有的中文都是乱码，所以通过简单的分析出问题的最 有可能出问题的地方就是JSP视图，其次是业务处理部分部分，作为Bean只是用来存储数据的，不可能出现问题。所以得先从下面几种方式开始检查(我不是 高手，一下看不出根本问题的所在)：<br /> 第一：<br /> 1:在jsp页面加入： &nbsp;<br /> &lt;%@ &nbsp;page &nbsp;contentType=&quot;text/html; &nbsp;charset=gb2312&quot; &nbsp;%&gt;<br /> 2.在JSP页面的最上面&lt;%@的下面添加request.setCharacterEncoding(&quot;gb2312&quot;)，JSP页面接收数据的统一为GB2312编码格式；  <br /> 3:在servlet里面: &nbsp;<br /> &nbsp; &nbsp;public &nbsp;void &nbsp;doGet(HttpServletRequest &nbsp;request, &nbsp;HttpServletResponse &nbsp;response) &nbsp;throws &nbsp;ServletException, &nbsp;IOException &nbsp;{ &nbsp;<br /> &nbsp; &nbsp; &nbsp; &nbsp;response.setContentType(&quot;text/html; &nbsp;charset=gb2312&quot;);&nbsp;<br /> 4:以上如果还不行就用如下的方法在数据入库前进行调用：<br />
[CODE_LITE]<br />
public  static  String  UnicodeToChinese(String  s){<br />
   try{<br />
         if(s==null  ¦  ¦s.equals(&#8220;&#8221;))  return  &#8220;&#8221;;<br />
         String  newstring=null;<br />
         newstring=new  String(s.getBytes(&#8220;ISO8859_1&#8243;),&#8221;gb2312&#8243;);<br />
         return  newstring;<br />
       }<br />
   catch(UnsupportedEncodingException  e)<br />
   {<br />
   return  s;<br />
   }<br />
   }<br />
public  static  String  ChineseToUnicode(String  s){<br />
   try{<br />
   if(s==null  ¦  ¦s.equals(&#8220;&#8221;))  return  &#8220;&#8221;;<br />
   String  newstring=null;<br />
   newstring=new  String(s.getBytes(&#8220;gb2312&#8243;),&#8221;ISO8859_1&#8243;);<br />
     return  newstring;<br />
   }<br />
   catch(UnsupportedEncodingException  e)<br />
   {<br />
   return  s;<br />
 }<br />
   }<br />
[/CODE_LITE]<br />
第二、朋友用的是MYsql，如果是连接数据库出现乱码问题得先下载mysql&nbsp;jdbc驱动，并解压到JDK目录下的lib文件夹和resin安装目录下的lib目录，当然这时的系统变量CLASSPATH别忘了加上,重启resin，加上连接文件。<br /> 第三、以上如果问题任然存在可能就是从数据库中取出来的时候就不是gb2312的编码格式，还有就是Servlet的传输数据的时候出的问题,根据这种情 况先从数据库原因查起,没有看到他的数据库配置，不过如果编码方式为GBK，就没有问题，那么问题就出在Servlet上了，JSP在执行时首先要编译成 Servlet，通过上面的方法可以进行下面的检查:<br /> 1.response.setContentType(CONTENT_TYPE)，CONTENT_TYPE是一个常量，默认是&ldquo;text/html; charset=ISO-8859-1&rdquo;(这里朋友给我的代码中是ISO8859-1，明显是个错误),看来这里是有问题了，应该把&ldquo;charset=ISO-8859-1&rdquo;改为&ldquo;charset=gb2312&rdquo;；<br /> 2.request.setCharacterEncoding(&quot;gb2312&quot;);在doGet或者doPost方法的最上面是否有这个设置。<br /> 通过这些方法朋友解决了他的乱码问题，其实在开发JSP时遇到乱码问题很常见，很多时候是因我们在一些细节上不规范，从而导致不一致，当然这只是乱码问题其中的一个。<br /> BTW：早期的IBM网站有关于乱码问题的<a href="http://www-128.ibm.com/developerworks/cn/java/java_chinese/index.html">资料</a>，这里也贴出来以便大家了解乱码的根本原因，以及下面有关乱码问题的文章一起放上来吧~~~~<br />&nbsp;<strong>Web应用中的中文乱码问题</strong><br />
    * [URL=http://www.javaworld.com.tw/jute/post/view?bid=9&amp;id=44042&amp;st]解决 Tomcat 5.0.19 中文参数传递问题[/URL]<br />
    * [URL=http://togetherj.blogdriver.com/togetherj/253018.html]Tomcat中文问题[/URL]<br />
    * [URL=http://www.knowsky.com/5352.html]深入剖析JSP和Servlet对中文的处理[/URL]<br />
    * [URL=http://www.knowsky.com/list.asp?id=2702]用XMLHTTP Post/Get HTML页面时的中文乱码之完全Script解决方案 [/URL]<br />
    * [URL=http://www.javaworld.com.tw/jute/post/view?bid=11&amp;id=57879&amp;sty=1&amp;tpg=1&amp;age=-1]修正上传 attachement file时的中文档名乱码问题[/URL] (修改mvnforum-1.0.0-rc3)<br />
    * 深入剖析Java编程中的中文问题及建议最优解决方法</p>
<p>http://dev.csdn.net/article/27/27140.shtm</p>
<p>http://dev.csdn.net/article/27/27142.shtm</p>
<p>    * [URL=http://www.chedong.com/tech/hello_unicode.html]Java中文处理学习笔记——Hello Unicode[/URL]<br />
    * [URL=http://www-900.ibm.com/developerWorks/cn/java/java_chinese/]Java编程技术中汉字问题的分析及解决 [/URL]<br />
    * [URL=http://www-900.ibm.com/developerWorks/cn/java/l-javachinese/index.shtml]关于Java中文问题的几条分析原则[/URL]<br />
    * [URL=http://gceclub.sun.com.cn/NASApp/sme/jive/thread.jsp?forum=8&amp;thread=13425]<br />
Java中文问题及最优解决方法[/URL]<br />
<span id="more-379"></span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在JSP和java的开发中乱码问题有时候是非常让人头疼的，今天朋友就出了这个问题，发来信息让我帮忙看看。其实java开发者都知道，出现乱码问题有 很多种原因，需要具体问题具体分析，从他和我说的配置环境是JSP（视图）+Tomcat（模型）+Servlet（业务处理），在本地的调试环境 （Tomcat+Resin）下出现乱码问题。通常我们使用的编码方式都是为GB2312，因为页面中所有的中文都是乱码，所以通过简单的分析出问题的最 有可能出问题的地方就是JSP视图，其次是业务处理部分部分，作为Bean只是用来存储数据的，不可能出现问题。所以得先从下面几种方式开始检查(我不是 高手，一下看不出根本问题的所在)：<br /> 第一：<br /> 1:在jsp页面加入： &nbsp;<br /> &lt;%@ &nbsp;page &nbsp;contentType=&quot;text/html; &nbsp;charset=gb2312&quot; &nbsp;%&gt;<br /> 2.在JSP页面的最上面&lt;%@的下面添加request.setCharacterEncoding(&quot;gb2312&quot;)，JSP页面接收数据的统一为GB2312编码格式；  <br /> 3:在servlet里面: &nbsp;<br /> &nbsp; &nbsp;public &nbsp;void &nbsp;doGet(HttpServletRequest &nbsp;request, &nbsp;HttpServletResponse &nbsp;response) &nbsp;throws &nbsp;ServletException, &nbsp;IOException &nbsp;{ &nbsp;<br /> &nbsp; &nbsp; &nbsp; &nbsp;response.setContentType(&quot;text/html; &nbsp;charset=gb2312&quot;);&nbsp;<br /> 4:以上如果还不行就用如下的方法在数据入库前进行调用：<br />
[CODE_LITE]<br />
public  static  String  UnicodeToChinese(String  s){<br />
   try{<br />
         if(s==null  ¦  ¦s.equals(&#8220;&#8221;))  return  &#8220;&#8221;;<br />
         String  newstring=null;<br />
         newstring=new  String(s.getBytes(&#8220;ISO8859_1&#8243;),&#8221;gb2312&#8243;);<br />
         return  newstring;<br />
       }<br />
   catch(UnsupportedEncodingException  e)<br />
   {<br />
   return  s;<br />
   }<br />
   }<br />
public  static  String  ChineseToUnicode(String  s){<br />
   try{<br />
   if(s==null  ¦  ¦s.equals(&#8220;&#8221;))  return  &#8220;&#8221;;<br />
   String  newstring=null;<br />
   newstring=new  String(s.getBytes(&#8220;gb2312&#8243;),&#8221;ISO8859_1&#8243;);<br />
     return  newstring;<br />
   }<br />
   catch(UnsupportedEncodingException  e)<br />
   {<br />
   return  s;<br />
 }<br />
   }<br />
[/CODE_LITE]<br />
第二、朋友用的是MYsql，如果是连接数据库出现乱码问题得先下载mysql&nbsp;jdbc驱动，并解压到JDK目录下的lib文件夹和resin安装目录下的lib目录，当然这时的系统变量CLASSPATH别忘了加上,重启resin，加上连接文件。<br /> 第三、以上如果问题任然存在可能就是从数据库中取出来的时候就不是gb2312的编码格式，还有就是Servlet的传输数据的时候出的问题,根据这种情 况先从数据库原因查起,没有看到他的数据库配置，不过如果编码方式为GBK，就没有问题，那么问题就出在Servlet上了，JSP在执行时首先要编译成 Servlet，通过上面的方法可以进行下面的检查:<br /> 1.response.setContentType(CONTENT_TYPE)，CONTENT_TYPE是一个常量，默认是&ldquo;text/html; charset=ISO-8859-1&rdquo;(这里朋友给我的代码中是ISO8859-1，明显是个错误),看来这里是有问题了，应该把&ldquo;charset=ISO-8859-1&rdquo;改为&ldquo;charset=gb2312&rdquo;；<br /> 2.request.setCharacterEncoding(&quot;gb2312&quot;);在doGet或者doPost方法的最上面是否有这个设置。<br /> 通过这些方法朋友解决了他的乱码问题，其实在开发JSP时遇到乱码问题很常见，很多时候是因我们在一些细节上不规范，从而导致不一致，当然这只是乱码问题其中的一个。<br /> BTW：早期的IBM网站有关于乱码问题的<a href="http://www-128.ibm.com/developerworks/cn/java/java_chinese/index.html">资料</a>，这里也贴出来以便大家了解乱码的根本原因，以及下面有关乱码问题的文章一起放上来吧~~~~<br />&nbsp;<strong>Web应用中的中文乱码问题</strong><br />
    * [URL=http://www.javaworld.com.tw/jute/post/view?bid=9&amp;id=44042&amp;st]解决 Tomcat 5.0.19 中文参数传递问题[/URL]<br />
    * [URL=http://togetherj.blogdriver.com/togetherj/253018.html]Tomcat中文问题[/URL]<br />
    * [URL=http://www.knowsky.com/5352.html]深入剖析JSP和Servlet对中文的处理[/URL]<br />
    * [URL=http://www.knowsky.com/list.asp?id=2702]用XMLHTTP Post/Get HTML页面时的中文乱码之完全Script解决方案 [/URL]<br />
    * [URL=http://www.javaworld.com.tw/jute/post/view?bid=11&amp;id=57879&amp;sty=1&amp;tpg=1&amp;age=-1]修正上传 attachement file时的中文档名乱码问题[/URL] (修改mvnforum-1.0.0-rc3)<br />
    * 深入剖析Java编程中的中文问题及建议最优解决方法</p>
<p>http://dev.csdn.net/article/27/27140.shtm</p>
<p>http://dev.csdn.net/article/27/27142.shtm</p>
<p>    * [URL=http://www.chedong.com/tech/hello_unicode.html]Java中文处理学习笔记——Hello Unicode[/URL]<br />
    * [URL=http://www-900.ibm.com/developerWorks/cn/java/java_chinese/]Java编程技术中汉字问题的分析及解决 [/URL]<br />
    * [URL=http://www-900.ibm.com/developerWorks/cn/java/l-javachinese/index.shtml]关于Java中文问题的几条分析原则[/URL]<br />
    * [URL=http://gceclub.sun.com.cn/NASApp/sme/jive/thread.jsp?forum=8&amp;thread=13425]<br />
Java中文问题及最优解决方法[/URL]</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/379/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>AJAX: 怎么处理书签和按钮!</title>
		<link>http://welog.org/blog/304</link>
		<comments>http://welog.org/blog/304#comments</comments>
		<pubDate>Sat, 29 Oct 2005 02:54:40 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/ajax-%e6%80%8e%e4%b9%88%e5%a4%84%e7%90%86%e4%b9%a6%e7%ad%be%e5%92%8c%e6%8c%89%e9%92%ae/</guid>
		<description><![CDATA[&#8220;真正地简单的历史框架包括二个开源Javascript组, DhtmlHistory 与 HistoryStorage. 这两类使AJAX 应用支持按书签自由翻动按钮。 首先,我们将创造一个AJAX 网页应用一系列的题目链接; 当题目被选择, 他们的内容将被装载并且显示在页的右边而没有执行整页刷新:&#8230; &#34;真正地简单的历史框架包括二个开源Javascript组, DhtmlHistory 与 HistoryStorage. 这两类使AJAX 应用支持按书签自由翻动按钮。首先,我们将创造一个AJAX 网页应用一系列的题目链接; 当题目被选择, 他们的内容将被装载并且显示在页的右边而没有执行整页刷新:图：最后实现的效果. 这里有完成后的效果，大家可以看看&#8230;. 这个例子比较简单且可以创造其它的简单的技术，譬如使用iframe 的iframe 和hyperlinks 。然而,这足够说明怎么使用简单的历史API控制的先进方式, 提供按书签, 和存贮过程的服务器的声明。它提供剪贴代码这样的比较先进的AJAX 应用。例子应用包括四个主要文件: advanced.html advanced.css advanced.js 和 topics.xml。我们并且使用三个框架加速发展 : DhtmlHistory 和HistoryStorage APIs; X DHTML&#160;topics (DHTML 的一个开放来源工具箱;&#160;) Sarissa (一个开源API 为提供 XmlHttpRequest 和XML.这里作用的就是这个开源的API)我们先从XML 文件开始, 命名topics.xml 我们将使用这个文件创造我们最初的用户界面: [CODE_LITE] [/CODE_LITE] 这是记录各个可得到的topics的一个简单XML 文件。我们分配各个题目几个属性, 譬如id 和 title &#8230; <a href="http://welog.org/blog/304">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>&#8220;真正地简单的历史框架包括二个开源Javascript组, DhtmlHistory 与 HistoryStorage. 这两类使AJAX 应用支持按书签自由翻动按钮。<br />
首先,我们将创造一个AJAX 网页应用一系列的题目链接; 当题目被选择, 他们的内容将被装载并且显示在页的右边而没有执行整页刷新:&#8230;<br />
<span id="more-304"></span></p>
<p>&quot;真正地简单的历史框架包括二个开源Javascript组, DhtmlHistory 与 HistoryStorage. 这两类使AJAX 应用支持按书签自由翻动按钮。首先,我们将创造一个AJAX 网页应用一系列的题目链接; 当题目被选择, 他们的内容将被装载并且显示在页的右边而没有执行整页刷新:<img height="261" alt="Ajax简单事例" src="http://www.blueclassic.net/FCKeditor/advanced_screencast_thumbnail.gif" width="448" align="absMiddle" border="1" /><br /><em>图：最后实现的效果.<br /></em><br />
<a href="http://www.blueclassic.net/ajax/ajax/advanced.html">这里有完成后的效果，大家可以看看&#8230;.<br />
 </a><br />
这个例子比较简单且可以创造其它的简单的技术，譬如使用iframe 的iframe 和hyperlinks 。然而,这足够说明怎么使用简单的历史API控制的先进方式, 提供按书签, 和存贮过程的服务器的声明。它提供剪贴代码这样的比较先进的AJAX 应用。<br />例子应用包括四个主要文件: <font color="#0000ff">advanced.html advanced.css advanced.js</font> 和 <font color="#0000ff">topics.xml</font>。我们并且使用三个框架加速发展 : <code>DhtmlHistory</code> 和<code>HistoryStorage</code> APIs; <a href="http://cross-browser.com/">X DHTML&nbsp;topics </a>(DHTML 的一个开放来源工具箱;&nbsp;) <a href="http://sarissa.sourceforge.net/doc/">Sarissa </a>(一个开源API 为提供 <code>XmlHttpRequest</code> 和XML.这里作用的就是这个开源的API)<br />我们先从XML 文件开始, 命名<code>topics.xml</code> 我们将使用这个文件创造我们最初的用户界面:<br />
[CODE_LITE]</p>
<p>[/CODE_LITE]<br />
这是记录各个可得到的topics的一个简单XML 文件。我们分配各个题目几个属性, 譬如<code>id</code> 和 <code>title</code> 我们以后将提取使用Javascript加强这份菜单sidebar 。<br />其次, 我们创造<code>advanced.html文件</code>。<br />
[CODE_LITE]</p>
<p>    <!-- The X Cross-Browser DHTML Library --></p>
<p>     <!-- The Sarissa Library --></p>
<p>     <!-- Our application's JavaScript --></p>
<p>    <!-- Link in style sheets --></p>
<div>
<h1>Topic Title</h1>
<div>
          Topic Content Goes Here
        </div>
</p></div>
<div>
      </div>
<p>[/CODE_LITE]<br />
<br />接着建立一个<code>advanced.js文件</code>。<br />
[CODE_LITE]<br />
/*<br />
   Copyright (c) 2005, Brad Neuberg, </p>
<p>   Permission is hereby granted, free of charge,<br />
   to any person obtaining a copy of this software<br />
   and associated documentation files (the<br />
   &#8220;Software&#8221;), to deal in the Software without<br />
   restriction, including without limitation<br />
   the rights to use, copy, modify, merge,<br />
   publish, distribute, sublicense, and/or sell<br />
   copies of the Software, and to permit persons<br />
   to whom the Software is furnished to do so,<br />
   subject to the following conditions:</p>
<p>   The above copyright notice and this<br />
   permission notice shall be included in all<br />
   copies or substantial portions of the Software.</p>
<p>   THE SOFTWARE IS PROVIDED &#8220;AS IS&#8221;, WITHOUT<br />
   WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,<br />
   INCLUDING BUT NOT LIMITED TO THE WARRANTIES<br />
   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR<br />
   PURPOSE AND NONINFRINGEMENT.<br />
   IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT<br />
   HOLDERS BE LIABLE FOR ANY<br />
   CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER<br />
   IN AN ACTION OF CONTRACT, TORT<br />
   OR OTHERWISE, ARISING FROM, OUT OF OR IN<br />
   CONNECTION WITH THE SOFTWARE OR<br />
   THE USE OR OTHER DEALINGS IN THE SOFTWARE.<br />
*/</p>
<p>// initialize ourselves when the page is finished<br />
// loading<br />
window.onload = initialize;</p>
<p>// an array of our topics<br />
var topics = new Array();</p>
<p>function initialize() {<br />
  // initialize the DhtmlHistory<br />
  // framework<br />
  dhtmlHistory.initialize();</p>
<p>  // if this is the first time the page<br />
  // has loaded, fetch the list of<br />
  // topics remotely<br />
  if (dhtmlHistory.isFirstLoad()) {<br />
    topics = loadTopics();<br />
    historyStorage.put(&#8220;topics&#8221;, topics);<br />
  }<br />
  else {<br />
    // else, simply extract it from our<br />
    // history storage<br />
    topics = historyStorage.get(&#8220;topics&#8221;);<br />
  }</p>
<p>  // display our topics list<br />
  displayTopicsList(); </p>
<p>  // initialize our initial state from<br />
  // the browser location after the hash<br />
  var currentTopic =<br />
        dhtmlHistory.getCurrentLocation();<br />
  displayTopic(currentTopic);</p>
<p>  // catch when a user clicks on a new<br />
  // topic<br />
  var menu =<br />
        document.getElementById(&#8220;menu&#8221;);<br />
  xAddEventListener(menu, &#8220;click&#8221;,<br />
                    handleTopicChange,<br />
                    false);</p>
<p>  // set ourselves up to listen to<br />
  // history events<br />
  dhtmlHistory.addListener(<br />
                    handleHistoryEvent);<br />
}</p>
<p>function handleHistoryEvent(newLocation,<br />
                            historyData) {<br />
  var topicID = newLocation;</p>
<p>  // display this topic<br />
  displayTopic(topicID);<br />
}</p>
<p>function handleTopicChange(e) {<br />
  var evt = new xEvent(e);<br />
  var target = evt.target;<br />
  var topicID = target.getAttribute(&#8220;topicID&#8221;);</p>
<p>  // display this topic<br />
  var content = displayTopic(topicID);</p>
<p>  // add this to our history<br />
  dhtmlHistory.add(topicID, content);</p>
<p>  // cancel the default behavior of hyperlinks<br />
  return evt.cancel();<br />
}</p>
<p>function displayTopic(topicID) {<br />
  var topic;</p>
<p>  // if no topic passed in then get the<br />
  // default topic<br />
  if (topicID == null ||<br />
      topicID == &#8220;&#8221;) {<br />
    for (var i = 0; i initialize()</code>, 当第一页装载, 我们必须使用<code>dhtmlHistory .getCurrentLocation()</code> 方法得到当前地点在散列值以;&nbsp;&nbsp;</p>
<p>下面建立页面显示的内容，分别为topic1.html、topic2.html、topic3.html,这里的文字可以随便写了！</p>
<p>topic1.html<br />
[CODE_LITE]<br />
Hello Topic 1 World!</p>
<p>-Ajax<br />
  -advanced.css<br />
  -advanced.html<br />
  -advanced.js<br />
  -topic1.html<br />
  -topic2.html<br />
  -topic3.html<br />
  -topics.xml<br />
-Lib<br />
 --history<br />
    ---dhtmlHistory.js<br />
    ---historyStorage.js<br />
    ---serializer.js<br />
 --sarissa<br />
    ---sarissa.js<br />
    ---sarissa_dhtml.js<br />
    ---sarissa_ieemu_xpath.js<br />
    ---sarissa_ieemu_xslt.js<br />
--x<br />
    ---x_core.js<br />
    ---x_dom.js<br />
    ---x_event.js<br />
[/CODE_LITE]</p>
<p>topic2.html<br />
[CODE_LITE]<br />
Hello Topic 2 World!<br />
This is a simple two column layout with a left menu box. By modifying the stylesheet, this layout can serve as the basis for many standard two column layouts. As is the case with most layouts in the Reservoir, the order of elements (header, content, menu) in the HTML source is friendly and accessible to mobile computers, text-based browsers, and alternative/accessible devices.<br />
[/CODE_LITE]</p>
<p>topic3.html<br />
[CODE_LITE]<br />
Hello Topic 3 World!<br />
[/CODE_LITE]<br />
再有就是建立一个advanced.css样式表!<br />
[CODE_LITE]<br />
body {<br />
	margin:0px;<br />
	padding:0px;<br />
	font-family:verdana, arial, helvetica,<br />
              sans-serif;<br />
	color:#333;<br />
	background-color:white;<br />
	}<br />
h1 {<br />
	margin:0px 0px 15px 0px;<br />
	padding:0px;<br />
	font-size:28px;<br />
	line-height:28px;<br />
	font-weight:900;<br />
	color:#ccc;<br />
	}<br />
p {<br />
	font:11px/20px verdana, arial, helvetica,<br />
       sans-serif;<br />
	margin:0px 0px 16px 0px;<br />
	padding:0px;<br />
	}</p>
<p>a {<br />
  display:block;<br />
	color:#09c;<br />
	font-size:11px;<br />
	text-decoration:none;<br />
	font-weight:600;<br />
	font-family:verdana, arial, helvetica,<br />
              sans-serif;<br />
	}<br />
a:link {color:#09c;}<br />
a:visited {color:#07a;}<br />
a:hover {background-color:#eee;}</p>
<p>#content {<br />
	margin:50px 50px 50px 220px;<br />
	padding:10px;<br />
	}</p>
<p>#menu {<br />
	position:absolute;<br />
	top:55px;<br />
	left:20px;<br />
	width:172px;<br />
	padding:10px;<br />
	background-color:#eee;<br />
	border:1px dashed #999;<br />
	line-height:17px;<br />
	}<br />
[/CODE_LITE]<br />
至此一个简单的Ajas应用就实现了，当然<a href="http://cross-browser.com">X DHTML&nbsp;topics&nbsp;</a>与 <a href="http://sarissa.sourceforge.net/doc">Sarissa </a>的API是必不可少的，主要的目录文件大家可以去相关的网站下载，这里我给出目录结构:<br />
些Ajax应该的目录结构如下：<br />
-Ajax<br />
  -advanced.css<br />
  -advanced.html<br />
  -advanced.js<br />
  -topic1.html<br />
  -topic2.html<br />
  -topic3.html<br />
  -topics.xml<br />
-Lib<br />
 --history<br />
    ---dhtmlHistory.js<br />
    ---historyStorage.js<br />
    ---serializer.js<br />
 --sarissa<br />
    ---sarissa.js<br />
    ---sarissa_dhtml.js<br />
    ---sarissa_ieemu_xpath.js<br />
    ---sarissa_ieemu_xslt.js<br />
--x<br />
    ---x_core.js<br />
    ---x_dom.js<br />
    ---x_event.js</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/304/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Java之Constructor finalize()</title>
		<link>http://welog.org/blog/274</link>
		<comments>http://welog.org/blog/274#comments</comments>
		<pubDate>Wed, 28 Sep 2005 01:04:05 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/java%e4%b9%8bconstructor-finalize/</guid>
		<description><![CDATA[[IMG]upload/sun.gif[/IMG] [B]Constructor[/B] - 每个class都必须有自己的constructor，它不能从父类中inherited,一个class可以有多个，但至少有一个, 如果没有显示声明构造函数，compiler会提供一个默认的不带参数的构造函数，只要有一个显示声明的constructor,将不会提供default constructor. - constructor 不可以有返回值，如果有返回值将会被视为一个普通的方法，不过与类同名。但是在constructor里可以写return语句，public Cons(){return;} 这样是允许的。 [IMG]upload/sun.gif[/IMG] [B]Constructor[/B] - 每个class都必须有自己的constructor，它不能从父类中inherited,一个class可以有多个，但至少有一个, 如果没有显示声明构造函数，compiler会提供一个默认的不带参数的构造函数，只要有一个显示声明的constructor,将不会提供default constructor. - constructor 不可以有返回值，如果有返回值将会被视为一个普通的方法，不过与类同名。但是在constructor里可以写return语句，public Cons(){return;} 这样是允许的。 在子类调用其constructor的时候，compliler会自动为其加上super();所以如果父类中没有显示的申明不带 参数的构造函数，将会有编译错误。 - 在constructor里可以用this()/super()调用自己/父类中的其他构造函数，调用自己会有recursive invocation error.注意的是this();或者super()都必须写在其第一句话，所以，this();和super();显然不能同时被调用。 [CODE_LITE] class base{ base(int i){ System.out.println(&#8220;base constructor int i&#8221;); } } class derived extends base{ derived(){ super(8); System.out.println(&#8220;derived constructor&#8221;); } derived(int i){ super(i); System.out.println(&#8220;derived constructor int i&#8221;); &#8230; <a href="http://welog.org/blog/274">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>[IMG]upload/sun.gif[/IMG]<br />
[B]Constructor[/B]<br />
- 每个class都必须有自己的constructor，它不能从父类中inherited,一个class可以有多个，但至少有一个, 如果没有显示声明构造函数，compiler会提供一个默认的不带参数的构造函数，只要有一个显示声明的constructor,将不会提供default constructor.<br />
- constructor 不可以有返回值，如果有返回值将会被视为一个普通的方法，不过与类同名。但是在constructor里可以写return语句，public Cons(){return;} 这样是允许的。<br />
<span id="more-274"></span><br />
[IMG]upload/sun.gif[/IMG]<br />
[B]Constructor[/B]<br />
- 每个class都必须有自己的constructor，它不能从父类中inherited,一个class可以有多个，但至少有一个, 如果没有显示声明构造函数，compiler会提供一个默认的不带参数的构造函数，只要有一个显示声明的constructor,将不会提供default constructor.<br />
- constructor 不可以有返回值，如果有返回值将会被视为一个普通的方法，不过与类同名。但是在constructor里可以写return语句，public Cons(){return;} 这样是允许的。<br />
在子类调用其constructor的时候，compliler会自动为其加上super();所以如果父类中没有显示的申明不带  参数的构造函数，将会有编译错误。<br />
- 在constructor里可以用this()/super()调用自己/父类中的其他构造函数，调用自己会有recursive invocation error.注意的是this();或者super()都必须写在其第一句话，所以，this();和super();显然不能同时被调用。<br />
[CODE_LITE]<br />
class base{<br />
base(int i){<br />
System.out.println(&#8220;base constructor int i&#8221;);<br />
}<br />
}<br />
class derived extends base{<br />
  derived(){<br />
    super(8);<br />
    System.out.println(&#8220;derived constructor&#8221;);<br />
  }<br />
  derived(int i){<br />
    super(i);<br />
    System.out.println(&#8220;derived constructor int i&#8221;);<br />
  }<br />
  public static void main(String［］ args){<br />
    derived d=new derived();<br />
    derived t=new derived(9);<br />
  }<br />
}[/CODE_LITE]<br />
super(i)表示父类的构造函数base(i),super(i)一个是super(8)。<br />
子类如果有多个构造函数的时候，父类要么没有构造函数，让编译器自动产生，那么在执行子类构造函数之前先执行编译器自动产生的父类的缺省构造函数；要么至少要有一个显式的缺省构造函数可以让子类的构造函数调用。</p>
<p>[B]finalize() [/B]<br />
-在 Java 中，当你创建一个对象时，Java 虚拟机（JVM）为该对象分配内存、调用构造函数并开始跟踪你使用的对象。当你停止使用一个对象（就是说，当没有对该对象有效的引用时），JVM 通过垃圾回收器将该对象标记为释放状态。<br />
-当垃圾回收器将要释放一个对象的内存时，它调用该对象的finalize() 方法（如果该对象定义了此方法）。垃圾回收器以独立的低优先级的方式运行，只有当其他线程挂起等待该内存释放的情况出现时，它才开始运行释放对象的内存。（事实上，你可以调用System.gc() 方法强制垃圾回收器来释放这些对象的内存。）<br />
-在以上的描述中，有一些重要的事情需要注意。首先，只有当垃圾回收器释放该对象的内存时，才会执行finalize()。如果在 Applet 或应用程序退出之前垃圾回收器没有释放内存，垃圾回收器将不会调用finalize()。<br />
-再者，除非垃圾回收器认为你的 Applet 或应用程序需要额外的内存，否则它不会试图释放不再使用的对象的内存。换句话说，这是完全可能的：一个 Applet 给少量的对象分配内存，没有造成严重的内存需求，于是垃圾回收器没有释放这些对象的内存就退出了。<br />
-显然，如果你为某个对象定义了finalize() 方法，JVM 可能不会调用它，因为垃圾回收器不曾释放过那些对象的内存。调用System.gc() 也不会起作用，因为它仅仅是给 JVM 一个建议而不是命令。<br />
-且finalize()还有一个用处就是[B]死亡条件[/B](The death condition)检查.<br />
如果你在类中定义了finalize() ，它将不会自动调用基类中的方法。在我们讨论了finalize() 与 C++ 的析构函数的不同点后，对这个结论不会惊讶，因为为某个类定制的清除代码另一个类不一定会需要。<br />
-如果你决定要通过派生一个类的finalize() 方法来调用基类中的finalize() 方法，你可以象其他继承方法一样处理。<br />
        protected void finalize()<br />
        {<br />
          super.finalize();<br />
          // other finalization code&#8230;<br />
        }<br />
除了允许你控制是否执行清除操作外，这个技术还使你可以控制当前类的finalize() 方法何时执行。<br />
Java 的自动垃圾回收器不会失去平衡。作为代价，你不得不放弃对系统资源释放的控制。Java Applet 不会自动执行你的类中的finalize() 方法。因此，你不应当依靠finalize() 来执行你的 Applet 和应用程序的资源清除工作。取而代之，你应当明确的清除那些资源或创建一个try&#8230;finally 块（或类似的机制）来实现。</p>
<p>[CODE_LITE]<br />
//A: final_things.java<br />
import java.applet.*;<br />
import java.awt.*;<br />
class thing<br />
{<br />
  public static int thingcount = 0;<br />
  public static int thingfinal = 0;<br />
  public thing(){<br />
    ++thingcount;<br />
  }<br />
  protected void finalize(){<br />
    ++thingfinal;<br />
  }<br />
}<br />
public class final_things extends Applet{<br />
  public final_things(){<br />
  }<br />
  public String getAppletInfo(){<br />
    return &#8220;Name: final_thing\r\n&#8221; +<br />
           &#8220;Author: Tim Gooch\r\n&#8221; +<br />
           &#8220;Created with Microsoft &#8221; +<br />
           &#8220;Visual J++ Version 1.1&#8243;;<br />
  }<br />
  public void init(){<br />
      resize(320, 240);<br />
  }<br />
  public void destroy(){<br />
  }<br />
  public void paint(Graphics g){<br />
    g.drawString(&#8220;Created with Microsoft&#8221; +<br />
      &#8220;Visual J++ Version 1.1&#8243;, 10, 20);<br />
  }<br />
  public void start(){<br />
    while(thing.thingfinal </p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/274/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JAVA学习之Static</title>
		<link>http://welog.org/blog/255</link>
		<comments>http://welog.org/blog/255#comments</comments>
		<pubDate>Thu, 01 Sep 2005 02:57:57 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/java%e5%ad%a6%e4%b9%a0%e4%b9%8bstatic/</guid>
		<description><![CDATA[[IMG]upload/sun.gif[/IMG] Static涉及到的有类(static)变量、类(static)方法、静态初始化。 结合[URL=http://www.javaresearch.org/article/showarticle.jsp?column=544&#38;thread=9703]JR中Java中static、this、super、final用法简谈(一)[/URL]这篇文章及《Thinking in java》用一个完整的程序来呈现Static关键字的用法！ [IMG]upload/sun.gif[/IMG] Static涉及到的有类(static)变量、类(static)方法、静态初始化。 结合[URL=http://www.javaresearch.org/article/showarticle.jsp?column=544&#38;thread=9703]JR中Java中static、this、super、final用法简谈(一)[/URL]这篇文章及《Thinking in java》用一个完整的程序来呈现Static关键字的用法！ [CODE_LITE]1． /** 2． *MyClass.java 3． *www.blueclassic.net 4． *2005.08.31 5． */ 6． 7． class MyClass { 8． static int statInt = 4; 9． static Double statDouble = 16.0; 10． int instInt; 11． double instDouble; 12． 13． public static void statMethod(){ 14． System.out.println (&#8220;statInt=&#8221;+statInt+ 15． &#8220;;statdouble=&#8221;+statDouble); 16． &#8230; <a href="http://welog.org/blog/255">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>[IMG]upload/sun.gif[/IMG]<br />
Static涉及到的有类(static)变量、类(static)方法、静态初始化。<br />
结合[URL=http://www.javaresearch.org/article/showarticle.jsp?column=544&amp;thread=9703]JR中Java中static、this、super、final用法简谈(一)[/URL]这篇文章及《Thinking in java》用一个完整的程序来呈现Static关键字的用法！<br />
<span id="more-255"></span><br />
[IMG]upload/sun.gif[/IMG]<br />
Static涉及到的有类(static)变量、类(static)方法、静态初始化。<br />
结合[URL=http://www.javaresearch.org/article/showarticle.jsp?column=544&amp;thread=9703]JR中Java中static、this、super、final用法简谈(一)[/URL]这篇文章及《Thinking in java》用一个完整的程序来呈现Static关键字的用法！</p>
<p>[CODE_LITE]1．	/**<br />
2．	*MyClass.java<br />
3．	*www.blueclassic.net<br />
4．	*2005.08.31<br />
5．	*/<br />
6．<br />
7．	class MyClass {<br />
8．	  static int statInt = 4;<br />
9．	  static Double statDouble = 16.0;<br />
10．	  int instInt;<br />
11．	  double instDouble;<br />
12．<br />
13．	  public static void statMethod(){<br />
14．	    System.out.println (&#8220;statInt=&#8221;+statInt+<br />
15．	        &#8220;;statdouble=&#8221;+statDouble);<br />
16．	}<br />
17．	public static void instMethod(){<br />
18．	  System.out.println(&#8220;instInt=&#8221;+instInt+<br />
19．	    &#8220;;instdouble=&#8221;+instDouble);<br />
20．	}<br />
21．	public MyClass(int intArg, double doubleArg){<br />
22．	  instInt = intArg;<br />
23．	  instDouble = doubleArg;<br />
24．	}<br />
25．	public static void main(string args[]){<br />
26．	  MyClass instance1 = new MyClass(1,2.0);<br />
27．	  MyClass instance2 = new MyClass(3,4.0);<br />
28．<br />
29．	  MyClass.statMethod(); //Outputs:statInt=4;<br />
30．	         //statDouble=16.0<br />
31．<br />
32．	  instance1.instMethod(); //Outputs:instInt=1;<br />
33．	        //instDouble=2.0<br />
34．	  instance1.statMethod(); //Outputs:statInt=4;<br />
35．	        //statDouble=16.0<br />
36．<br />
37．	  instance2.instMethod(); //Outputs:instInt=3;<br />
38．	        //instDouble=4.0<br />
39．	  instance2.statMethod(); //Outputs:statInt=4;<br />
40．	        //statDouble=16.0<br />
41．	}<br />
42．	} [/CODE_LITE]</p>
<p>[ALIGN-CENTER][IMG]upload/myclass.gif[/IMG]<br />
MyClass的框架图[/ALIGN-CENTER]<br />
从图中Static方法和数据的单个（共享）副本是因为类和该类的所有实例而存在。通过一个实例或通过类本身可以访问static成员。</p>
<p>====类(static)变量=====</p>
<p>   [CODE_LITE]public class Count {<br />
             private int serialNumber;<br />
             private static int counter = 0;<br />
             public Count() {<br />
               counter++;<br />
               serialNumber = counter;<br />
             }<br />
           }[/CODE_LITE]<br />
    在这个例子中，被创建的每个对象被赋于一个独特的序号，从1开始并继续往上。变量counter在所有实例中共享，所以，当一个对象的构造函数增加counter时，被创建的下一个对象接受增加过的值。<br />
    Static变量在某种程度上与其它语言中的全局变量相似。Java编程语言没有这样的全局语言，但static变量是可以从类的任何实例访问的单个变量。<br />
    如果static变量没有被标记成private，它可能会被从该类的外部进行访问。要这样做，不需要类的实例，可以通过类名指向它。<br />
[CODE_LITE]public class StaticVar {<br />
  public static int number;<br />
}<br />
public class OtherClass {<br />
  public void method() {<br />
    int x = StaticVar.number;<br />
  }<br />
}[/CODE_LITE]</p>
<p>[B]======类(static)方法======[/B]</p>
<p>          [CODE_LITE] public class GeneralFunction {<br />
             public static int addUp(int x, int y) {<br />
               return x + y;<br />
             }<br />
           }<br />
           public class UseGeneral {<br />
             public void method() {<br />
               int a = 9;<br />
               int b = 10;<br />
               int c = GeneralFunction.addUp(a, b);<br />
               System.out.println(&#8220;addUp() gives &#8221; + c);<br />
             }<br />
           }[/CODE_LITE]<br />
    因为static方法不需它所属的类的任何实例就会被调用，因此没有this值。结果是，static方法不能访问与它本身的参数以及static变量分离的任何变量。访问非静态变量的尝试会引起编译错误。</p>
<p>[CODE_LITE]public class Wrong {<br />
  int x;<br />
  public static void main(String args[]) {<br />
    x = 9; // COMPILER ERROR!<br />
  }<br />
}[/CODE_LITE]</p>
<p>    Main()是静态的，因为它必须在任何实例化发生前被顺序地访问，以便应用程序的运行。<br />
    静态方法不能被覆盖成非静态。</p>
<p>[FLASH=128,15,]http://doubleaf.com/wp-content/plugins//AsySound.swf?http://blog.ekoala.net/music/newage/era/the.mass/05.MP3[/FLASH]</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/255/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>JAVA学习之OOP Object Reference</title>
		<link>http://welog.org/blog/249</link>
		<comments>http://welog.org/blog/249#comments</comments>
		<pubDate>Sat, 27 Aug 2005 05:26:40 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/java%e5%ad%a6%e4%b9%a0%e4%b9%8boop-object-reference/</guid>
		<description><![CDATA[[IMG]upload/sun.gif[/IMG] 对象是一些相关的变量和方法的软件集,对象是理解面向对象技术的关键。现实生活中的对象，比如狗、桌子、电视、自行车等等。你可以发现现实世界中的对象有两个共同特征：它们都有状态和行为。比如狗有自己的状态（比如名字、颜色、以及饥饿等等）和行为（比如摇尾巴等等），而Reference就是提供行为的方法。 [FONT-COLOR=Red]UPDATE：Reference、Static用法。[/FONT-COLOR] [IMG]upload/sun.gif[/IMG] JAVA的学习断断续续学习差不多快一年了，但每次都没有系统把所有的知识结合起来！这次花点时间结合《THINKING IN JAVA》把前阶段的知识整理一下，在这里做个记录！ [CODE_LITE]对象是一些相关的变量和方法的软件集,对象是理解面向对象技术的关键。现实生活中的对象，比如狗、桌子、电视、自行车等等。你可以发现现实世界中的对象有两个共同特征：它们都有状态和行为。比如狗有自己的状态（比如名字、颜色、生育以及饥饿等等）和行为（比如摇尾巴等等）。而Reference就是提供行为的方法 [/CODE_LITE] 1.OOP中唯一关系的是对象的接口是什么，就像计算机的销售商她不管电源内部结构是怎样的，他只关系能否给你提供电就行了，也就是只要知道can or not而不是how and why.所有的程序是由一定的属性和行为对象组成的，不同的对象的访问通过函数调用来完成，对象间所有的交流都是通过方法调用，通过对封装对象数据，很大限度上提高复用率。 2.OOP中最重要的思想是类，类是模板是蓝图，从类中构造一个对象，即创建了这个类的一个实例(instance)。 3.对象的3个主要特性 　　behavior&#8212;说明这个对象能做什么. 　　state&#8212;当对象施加方法时对象的反映. 　　dentity&#8212;与其他相似行为对象的区分标志. 　　每个对象有唯一的indentity 而这3者之间相互影响. 4、fields和methods JAVA其实要做的事情无非就是：定义CLASS、产生对像、将消息发送给对像。 每个对像有会有数据成员（fields）和成员函数（methods），不同的对像彼此之间并不共享数据成员。 如：class Date{ int m; float n; boolean o; } 为上面的class产生一个对像 Date s=new date(); 5.类之间的关系: 　　use-a :依赖关系 　　has-a :聚合关系 　　is-a :继承关系&#8211;例:A类继承了B类，此时A类不仅有了B类的方法，还有其自己的方法.(个性存在于共性中) 6.Reference: 《Thinking In Java》切入Java就提出“Everything is Object”。在Java这个充满Object的世界中，reference是一切谜题的根源，所有的故事都是从这里开始的。 [FONT-COLOR=Green]没有null reference，reference必须有初值。[/FONT-COLOR] 使用reference要比使用指针效率高。因为reference不需要测试其有效性。指针可以重新赋值，而 reference总是指向它最初获得的对象。 用一段代码表达： &#8230; <a href="http://welog.org/blog/249">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>[IMG]upload/sun.gif[/IMG]<br />
对象是一些相关的变量和方法的软件集,对象是理解面向对象技术的关键。现实生活中的对象，比如狗、桌子、电视、自行车等等。你可以发现现实世界中的对象有两个共同特征：它们都有状态和行为。比如狗有自己的状态（比如名字、颜色、以及饥饿等等）和行为（比如摇尾巴等等），而Reference就是提供行为的方法。<br />
[FONT-COLOR=Red]UPDATE：Reference、Static用法。[/FONT-COLOR]<br />
<span id="more-249"></span><br />
[IMG]upload/sun.gif[/IMG]<br />
JAVA的学习断断续续学习差不多快一年了，但每次都没有系统把所有的知识结合起来！这次花点时间结合《THINKING IN JAVA》把前阶段的知识整理一下，在这里做个记录！</p>
<p>[CODE_LITE]对象是一些相关的变量和方法的软件集,对象是理解面向对象技术的关键。现实生活中的对象，比如狗、桌子、电视、自行车等等。你可以发现现实世界中的对象有两个共同特征：它们都有状态和行为。比如狗有自己的状态（比如名字、颜色、生育以及饥饿等等）和行为（比如摇尾巴等等）。而Reference就是提供行为的方法 [/CODE_LITE]<br />
1.OOP中唯一关系的是对象的接口是什么，就像计算机的销售商她不管电源内部结构是怎样的，他只关系能否给你提供电就行了，也就是只要知道can or not而不是how and why.所有的程序是由一定的属性和行为对象组成的，不同的对象的访问通过函数调用来完成，对象间所有的交流都是通过方法调用，通过对封装对象数据，很大限度上提高复用率。  </p>
<p>2.OOP中最重要的思想是类，类是模板是蓝图，从类中构造一个对象，即创建了这个类的一个实例(instance)。  </p>
<p>3.对象的3个主要特性<br />
　　behavior&#8212;说明这个对象能做什么.<br />
　　state&#8212;当对象施加方法时对象的反映.<br />
　　dentity&#8212;与其他相似行为对象的区分标志.<br />
　　每个对象有唯一的indentity 而这3者之间相互影响. </p>
<p>4、fields和methods<br />
   JAVA其实要做的事情无非就是：定义CLASS、产生对像、将消息发送给对像。<br />
   每个对像有会有数据成员（fields）和成员函数（methods），不同的对像彼此之间并不共享数据成员。<br />
    如：class Date{<br />
         int m;<br />
         float n;<br />
         boolean o;<br />
        }<br />
      为上面的class产生一个对像<br />
        Date s=new date();</p>
<p>5.类之间的关系:<br />
　　use-a :依赖关系<br />
　　has-a :聚合关系<br />
　　is-a :继承关系&#8211;例:A类继承了B类，此时A类不仅有了B类的方法，还有其自己的方法.(个性存在于共性中)  </p>
<p>6.Reference:<br />
  《Thinking In Java》切入Java就提出“Everything is Object”。在Java这个充满Object的世界中，reference是一切谜题的根源，所有的故事都是从这里开始的。<br />
   [FONT-COLOR=Green]没有null reference，reference必须有初值。[/FONT-COLOR]<br />
     使用reference要比使用指针效率高。因为reference不需要测试其有效性。指针可以重新赋值，而<br />
     reference总是指向它最初获得的对象。<br />
   用一段代码表达：<br />
   [CODE_LITE]<br />
/*<br />
* 创建日期 2005-8-31<br />
*ReferenceTest.java<br />
*www.blueclassic.net<br />
*/<br />
public class ReferenceTricks<br />
{<br />
  public static void main(String[] args)<br />
  {<br />
    ReferenceTricks r = new ReferenceTricks();<br />
    // reset integer<br />
    r.i = 0;<br />
    System.out.println<br />
	(&#8220;Before changeInteger:&#8221; + r.i);<br />
    changeInteger(r);<br />
    System.out.println<br />
	(&#8220;After changeInteger:&#8221; + r.i);</p>
<p>    // just for format<br />
    System.out.println();</p>
<p>    // reset integer<br />
    r.i = 0;<br />
    System.out.println<br />
	(&#8220;Before changeReference:&#8221; + r.i);<br />
    changeReference(r);<br />
    System.out.println<br />
	(&#8220;After changeReference:&#8221; + r.i);<br />
  }</p>
<p>  private static void<br />
  changeReference(ReferenceTricks r)<br />
  {<br />
   r = new ReferenceTricks();<br />
   r.i = 5;<br />
   System.out.println<br />
   (&#8220;In changeReference: &#8221; + r.i);<br />
  }</p>
<p>  private static void<br />
  changeInteger(ReferenceTricks r)<br />
{<br />
   r.i = 5;<br />
   System.out.println<br />
   (&#8220;In changeInteger:&#8221; + r.i);<br />
  }</p>
<p>  public int i;<br />
}[/CODE_LITE]</p>
<p>运行结果如下：<br />
  [CODE_LITE]Before changeInteger:0<br />
In changeInteger:5<br />
After changeInteger:5</p>
<p>Before changeReference:0<br />
In changeReference: 5<br />
After changeReference:0[/CODE_LITE]<br />
这里，我们关注的是两个change，changeReference和changeInteger。从输出的内容中，我们可以看出，两个方法在调用前和调用中完全一样，差异出现在调用后的结果。 </p>
<p>7.构造对象使用构造器:构造器的提出，构造器是一种特殊的方法，构造对象并对其初始化。<br />
　　例:Data类的构造器叫Data<br />
　　new Data()&#8212;构造一个新对象，且初始化当前时间.<br />
　　Data happyday=new Data()&#8212;把一个对象赋值给一个变量happyday，从而使该对象能够多次使用，此处要声明的使变量与对象变量二者是不同的.new返回的值是一个引用。  </p>
<p>　　构造器特点:构造器可以有0个，一个或多个参数<br />
　　构造器和类有相同的名字<br />
　　一个类可以有多个构造器<br />
　　构造器没有返回值<br />
　　构造器总是和new运算符一起使用.　　</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/249/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>BLOG升级相关记录！！</title>
		<link>http://welog.org/blog/247</link>
		<comments>http://welog.org/blog/247#comments</comments>
		<pubDate>Fri, 26 Aug 2005 07:47:25 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/blog%e5%8d%87%e7%ba%a7%e7%9b%b8%e5%85%b3%e8%ae%b0%e5%bd%95%ef%bc%81%ef%bc%81/</guid>
		<description><![CDATA[今天花了三四小时的时间将Z-BLOG程序从1.3升级到现在的1.4_sp1。之前的升级只是修改了需要修改的文件，这样下来难免会产生垃圾代码，程序也慢了很多。这次的1.4SP1,作者做了不小的调整，所兴这次来个大换血，将原来的文件全部清除。先在这里做个记录，方便下次升级！ 1、根据WOOOH的样式修改了模板库内default.html,b_article_comment.html,b_article_commentpost.html,b_article-multi.html的模板文件，目前的程序&#8230; [FONT-COLOR=Red]UPDATE：太晚了，先记录到此&#8230;&#8230;.[/FONT-COLOR] 今天花了三四小时的时间将Z-BLOG程序从1.3升级到现在的1.4_sp1。之前的升级只是修改了需要修改的文件，这样下来难免会产生垃圾代码，程序也慢了很多。这次的1.4SP1,作者做了不小的调整，所兴这次来个大换血，将原来的文件全部清除。先在这里做个记录，方便下次升级！ 1、根据WOOOH的样式修改了模板库内default.html,b_article_comment.html,b_article_commentpost.html,b_article-multi.html的模板文件，目前的程序只需要修改模板文件不用再动程序本身，相对来说方便了不少，具体的样式等有时间再做修改。 [FONT-COLOR=Red]b_article_comment.html[/FONT-COLOR] [CODE_LITE] &#8220;&#62;. &#8220;&#62; &#124; &#8221; rel=&#8221;nofollow&#8221; target=&#8221;_blank&#8221;&#62;HOME [/CODE_LITE] 2、增加了友情连接的插件，不用来回的折腾文件，现在后台直接添加。这个插件省了不少事！]]></description>
			<content:encoded><![CDATA[<p>今天花了三四小时的时间将Z-BLOG程序从1.3升级到现在的1.4_sp1。之前的升级只是修改了需要修改的文件，这样下来难免会产生垃圾代码，程序也慢了很多。这次的1.4SP1,作者做了不小的调整，所兴这次来个大换血，将原来的文件全部清除。先在这里做个记录，方便下次升级！<br />
1、根据WOOOH的样式修改了模板库内default.html,b_article_comment.html,b_article_commentpost.html,b_article-multi.html的模板文件，目前的程序&#8230;<br />
[FONT-COLOR=Red]UPDATE：太晚了，先记录到此&#8230;&#8230;.[/FONT-COLOR]<br />
<span id="more-247"></span><br />
今天花了三四小时的时间将Z-BLOG程序从1.3升级到现在的1.4_sp1。之前的升级只是修改了需要修改的文件，这样下来难免会产生垃圾代码，程序也慢了很多。这次的1.4SP1,作者做了不小的调整，所兴这次来个大换血，将原来的文件全部清除。先在这里做个记录，方便下次升级！<br />
1、根据WOOOH的样式修改了模板库内default.html,b_article_comment.html,b_article_commentpost.html,b_article-multi.html的模板文件，目前的程序只需要修改模板文件不用再动程序本身，相对来说方便了不少，具体的样式等有时间再做修改。</p>
<p>[FONT-COLOR=Red]b_article_comment.html[/FONT-COLOR]<br />
[CODE_LITE]</p>
<ul>
<li>
<a>&#8220;&gt;</a>.<br />
<a>&#8220;&gt;</a></li>
<li></li>
<li></li>
<li> | <a>&#8221; rel=&#8221;nofollow&#8221; target=&#8221;_blank&#8221;&gt;HOME</a></li>
</ul>
<p>[/CODE_LITE]</p>
<p>2、增加了友情连接的插件，不用来回的折腾文件，现在后台直接添加。这个插件省了不少事！</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/247/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>咖啡色的城市</title>
		<link>http://welog.org/blog/196</link>
		<comments>http://welog.org/blog/196#comments</comments>
		<pubDate>Sun, 19 Jun 2005 05:10:37 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/%e5%92%96%e5%95%a1%e8%89%b2%e7%9a%84%e5%9f%8e%e5%b8%82/</guid>
		<description><![CDATA[[IMG]upload/0509.gif[/IMG] 来自唐山音乐人,许明专辑&#62;的作品-caffe city.很不错一首吉它曲,第一次听完全沉醉其中.有兴趣的朋友可以到网上找一下有关他的作品. [IMG]upload/0509.gif[/IMG] 来自唐山音乐人,许明专辑&#62;的作品-caffe city.很不错一首吉它曲,第一次听完全沉醉其中.有兴趣的朋友可以到网上找一下有关他的作品. [MEDIA]http://www.worldtone.cn/long/0509_a.wma[/MEDIA] [IMG]upload/0509_a.jpg[/IMG]]]></description>
			<content:encoded><![CDATA[<p>[IMG]upload/0509.gif[/IMG]<br />
来自唐山音乐人,许明专辑&gt;的作品-caffe city.很不错一首吉它曲,第一次听完全沉醉其中.有兴趣的朋友可以到网上找一下有关他的作品.<br />
<span id="more-196"></span><br />
[IMG]upload/0509.gif[/IMG]<br />
来自唐山音乐人,许明专辑&gt;的作品-caffe city.很不错一首吉它曲,第一次听完全沉醉其中.有兴趣的朋友可以到网上找一下有关他的作品.</p>
<p>[MEDIA]http://www.worldtone.cn/long/0509_a.wma[/MEDIA]</p>
<p>[IMG]upload/0509_a.jpg[/IMG]</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/196/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>AIR &#8211; cherry Blossom Girl</title>
		<link>http://welog.org/blog/188</link>
		<comments>http://welog.org/blog/188#comments</comments>
		<pubDate>Sat, 04 Jun 2005 19:05:03 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/air-cherry-blossom-girl/</guid>
		<description><![CDATA[[IMG]upload/air.jpg[/IMG] 目前在法国以外的地区，人们了解最多的法国乐队是Air。 他们是一支流行电子乐队，乐风抒情悦耳。 [IMG]upload/air.jpg[/IMG] 目前在法国以外的地区，人们了解最多的法国乐队是Air。 他们是一支流行电子乐队，乐风抒情悦耳。 2001年的专辑《10千赫传奇》（10000HzLegend）将Air愈发成熟、具有惊人的深度和美感的音乐才华展现无遗。 其中既有轻快的曲调，又有阴暗沉郁的声响，是流行乐中的深沉派。 可以说，Air乐队是法国人对当代音乐的一大贡献。 《樱花姑娘》（Cherry Blossom Girl）在木吉他的温暖演奏中有个甜美的女声贯穿其中，但那声音并非出自某位女性，而是乐队成员之一的JB。当他把这首歌的演唱部分录制完成时，突然发现了一个可以转变声音的软件，便拿来在这首歌上试试效果，结果却超乎他们想像的完美。 AIR &#8211; cherry Blossom Girl I don&#8217;t want to be shy Can&#8217;t stand it anymore I just want to say &#8216;Hi&#8217; To the one I love Cherry blossom girl I feel sick all day long From not being with you I just want &#8230; <a href="http://welog.org/blog/188">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>[IMG]upload/air.jpg[/IMG]<br />
目前在法国以外的地区，人们了解最多的法国乐队是Air。<br />
他们是一支流行电子乐队，乐风抒情悦耳。<br />
<span id="more-188"></span><br />
[IMG]upload/air.jpg[/IMG]<br />
目前在法国以外的地区，人们了解最多的法国乐队是Air。<br />
他们是一支流行电子乐队，乐风抒情悦耳。<br />
2001年的专辑《10千赫传奇》（10000HzLegend）将Air愈发成熟、具有惊人的深度和美感的音乐才华展现无遗。<br />
其中既有轻快的曲调，又有阴暗沉郁的声响，是流行乐中的深沉派。<br />
可以说，Air乐队是法国人对当代音乐的一大贡献。<br />
《樱花姑娘》（Cherry Blossom Girl）在木吉他的温暖演奏中有个甜美的女声贯穿其中，但那声音并非出自某位女性，而是乐队成员之一的JB。当他把这首歌的演唱部分录制完成时，突然发现了一个可以转变声音的软件，便拿来在这首歌上试试效果，结果却超乎他们想像的完美。</p>
<p>AIR &#8211; cherry Blossom Girl</p>
<p>I don&#8217;t want to be shy<br />
Can&#8217;t stand it anymore<br />
I just want to say &#8216;Hi&#8217;<br />
To the one I love<br />
Cherry blossom girl</p>
<p>I feel sick all day long<br />
From not being with you<br />
I just want to go out<br />
Ever night for a while<br />
Cherry blossom girl</p>
<p>Tell me why can&#8217;t it be true</p>
<p>I never talk to you<br />
People say that I should<br />
I can pray everyday<br />
For the moment to come<br />
Cherry blossom girl</p>
<p>I just want to be sure<br />
When I will come to you<br />
When the time will be gone<br />
You will be by my side<br />
Cherry Blossom Girl</p>
<p>Tell me why can&#8217;t it be true</p>
<p>I&#8217;ll never love again<br />
Can I say that to you<br />
Will you run away<br />
If I try to be true<br />
Cherry blossom girl</p>
<p>Cherry blossom girl<br />
I&#8217;ll always be there for you<br />
That means no time to waste<br />
Whenever there&#8217;s a chance<br />
Cherry blossom girl</p>
<p>Tell me why can&#8217;t it be true</p>
<p>[MEDIA]http://www.supernb.com/try/cherry_blossom_girl.mp3[/MEDIA]</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/188/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>static、this、super、final用法</title>
		<link>http://welog.org/blog/169</link>
		<comments>http://welog.org/blog/169#comments</comments>
		<pubDate>Thu, 19 May 2005 05:42:52 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/static%e3%80%81this%e3%80%81super%e3%80%81final%e7%94%a8%e6%b3%95/</guid>
		<description><![CDATA[Thinking：Java中static、this、super、final用法 本篇旨在帮助准备学习Java以及刚接触Java的朋友认识、掌握和使用static、this、super、final这几个关键字的使用。Java博大精深，我也是一位正在学习和使用Java的爱好者，文中难免有不妥之处，欢迎指正。 Thinking：Java中static、this、super、final用法 本篇旨在帮助准备学习Java以及刚接触Java的朋友认识、掌握和使用static、this、super、final这几个关键字的使用。Java博大精深，我也是一位正在学习和使用Java的爱好者，文中难免有不妥之处，欢迎指正。 一、static 请先看下面这段程序： public class Hello{ public static void main(String[] args){//(1) System.out.println(&#8220;Hello,world!&#8221;);//(2) } } 看过这段程序，对于大多数学过Java 的从来说，都不陌生。即使没有学过Java，而学过其它的高级语言，例如C，那你也应该能看懂这段代码的意思。它只是简单的输出“Hello,world”，一点别的用处都没有，然而，它却展示了static关键字的主要用法。 在1处，我们定义了一个静态的方法名为main，这就意味着告诉Java编译器，我这个方法不需要创建一个此类的对象即可使用。你还得你是怎么运行这个程序吗？一般，我们都是在命令行下，打入如下的命令(加下划线为手动输入)： javac Hello.java java Hello Hello,world! 这就是你运行的过程，第一行用来编译Hello.java这个文件，执行完后，如果你查看当前，会发现多了一个Hello.class文件，那就是第一行产生的Java二进制字节码。第二行就是执行一个Java程序的最普遍做法。执行结果如你所料。在2中，你可能会想，为什么要这样才能输出。好，我们来分解一下这条语句。（如果没有安装Java文档，请到Sun的官方网站浏览J2SE API）首先，System是位于java.lang包中的一个核心类，如果你查看它的定义，你会发现有这样一行：public static final PrintStream out;接着在进一步，点击 PrintStream这个超链接，在METHOD页面，你会看到大量定义的方法，查找println，会有这样一行： public void println(String x)。好了，现在你应该明白为什么我们要那样调用了，out是System的一个静态变量，所以可以直接使用，而out所属的类有一个println方法。 静态方法 通常，在一个类中定义一个方法为static，那就是说，无需本类的对象即可调用此方法。如下所示： class Simple{ static void go(){ System.out.println(&#8220;Go&#8230;&#8221;); } } public class Cal{ public static void main(String[] args){ Simple.go(); &#8230; <a href="http://welog.org/blog/169">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Thinking：Java中static、this、super、final用法<br />
本篇旨在帮助准备学习Java以及刚接触Java的朋友认识、掌握和使用static、this、super、final这几个关键字的使用。Java博大精深，我也是一位正在学习和使用Java的爱好者，文中难免有不妥之处，欢迎指正。<br />
<span id="more-169"></span><br />
Thinking：Java中static、this、super、final用法<br />
本篇旨在帮助准备学习Java以及刚接触Java的朋友认识、掌握和使用static、this、super、final这几个关键字的使用。Java博大精深，我也是一位正在学习和使用Java的爱好者，文中难免有不妥之处，欢迎指正。<br />
一、static<br />
请先看下面这段程序：<br />
public class Hello{<br />
     public static void main(String[] args){//(1)<br />
          System.out.println(&#8220;Hello,world!&#8221;);//(2)<br />
        }<br />
  }<br />
看过这段程序，对于大多数学过Java 的从来说，都不陌生。即使没有学过Java，而学过其它的高级语言，例如C，那你也应该能看懂这段代码的意思。它只是简单的输出“Hello,world”，一点别的用处都没有，然而，它却展示了static关键字的主要用法。<br />
在1处，我们定义了一个静态的方法名为main，这就意味着告诉Java编译器，我这个方法不需要创建一个此类的对象即可使用。你还得你是怎么运行这个程序吗？一般，我们都是在命令行下，打入如下的命令(加下划线为手动输入)：<br />
javac Hello.java<br />
java Hello<br />
Hello,world!<br />
这就是你运行的过程，第一行用来编译Hello.java这个文件，执行完后，如果你查看当前，会发现多了一个Hello.class文件，那就是第一行产生的Java二进制字节码。第二行就是执行一个Java程序的最普遍做法。执行结果如你所料。在2中，你可能会想，为什么要这样才能输出。好，我们来分解一下这条语句。（如果没有安装Java文档，请到Sun的官方网站浏览J2SE API）首先，System是位于java.lang包中的一个核心类，如果你查看它的定义，你会发现有这样一行：public static final PrintStream out;接着在进一步，点击 PrintStream这个超链接，在METHOD页面，你会看到大量定义的方法，查找println，会有这样一行：<br />
public void println(String x)。好了，现在你应该明白为什么我们要那样调用了，out是System的一个静态变量，所以可以直接使用，而out所属的类有一个println方法。<br />
静态方法<br />
通常，在一个类中定义一个方法为static，那就是说，无需本类的对象即可调用此方法。如下所示：<br />
class Simple{<br />
   static void go(){<br />
        System.out.println(&#8220;Go&#8230;&#8221;);<br />
    }<br />
}<br />
public class Cal{<br />
  public static void main(String[] args){<br />
     Simple.go();<br />
  }<br />
}<br />
调用一个静态方法就是“类名.方法名”,静态方法的使用很简单如上所示。一般来说，静态方法常常为应用程序中的其它类提供一些实用工具所用，在Java的类库中大量的静态方法正是出于此目的而定义的。<br />
静态变量<br />
静态变量与静态方法类似。所有此类实例共享此静态变量，也就是说在类装载时，只分配一块存储空间，所有此类的对象都可以操控此块存储空间，当然对于final则另当别论了。看下面这段代码：<br />
class Value{<br />
 static int c=0;<br />
 static void inc(){<br />
 c++;<br />
  }<br />
}<br />
class Count{<br />
  public static void prt(String s){<br />
    System.out.println(s);<br />
  }<br />
  public static void main(String[] args){<br />
    Value v1,v2;<br />
    v1=new Value();<br />
    v2=new Value();<br />
    prt(&#8220;v1.c=&#8221;+v1.c+&#8221;  v2.c=&#8221;+v2.c);<br />
    v1.inc();<br />
    prt(&#8220;v1.c=&#8221;+v1.c+&#8221;  v2.c=&#8221;+v2.c);<br />
  }<br />
}<br />
结果如下：<br />
v1.c=0  v2.c=0<br />
v1.c=1  v2.c=1<br />
由此可以证明它们共享一块存储区。static变量有点类似于C中的全局变量的概念。值得探讨的是静态变量的初始化问题。我们修改上面的程序：<br />
class Value{<br />
  static int c=0;<br />
  Value(){<br />
    c=15;<br />
  }<br />
  Value(int i){<br />
    c=i;<br />
  }<br />
  static void inc(){<br />
    c++;<br />
  }<br />
}<br />
class Count{<br />
  public static void prt(String s){<br />
    System.out.println(s);<br />
  }<br />
    Value v=new Value(10);<br />
    static Value v1,v2;<br />
    static{<br />
      prt(&#8220;v1.c=&#8221;+v1.c+&#8221;  v2.c=&#8221;+v2.c);<br />
      v1=new Value(27);<br />
      prt(&#8220;v1.c=&#8221;+v1.c+&#8221;  v2.c=&#8221;+v2.c);<br />
      v2=new Value(15);<br />
      prt(&#8220;v1.c=&#8221;+v1.c+&#8221;  v2.c=&#8221;+v2.c);<br />
    }<br />
  public static void main(String[] args){<br />
    Count ct=new Count();<br />
    prt(&#8220;ct.c=&#8221;+ct.v.c);<br />
    prt(&#8220;v1.c=&#8221;+v1.c+&#8221;  v2.c=&#8221;+v2.c);<br />
    v1.inc();<br />
    prt(&#8220;v1.c=&#8221;+v1.c+&#8221;  v2.c=&#8221;+v2.c);<br />
    prt(&#8220;ct.c=&#8221;+ct.v.c);<br />
  }<br />
}<br />
运行结果如下：<br />
v1.c=0  v2.c=0<br />
v1.c=27  v2.c=27<br />
v1.c=15  v2.c=15<br />
ct.c=10<br />
v1.c=10  v2.c=10<br />
v1.c=11  v2.c=11<br />
ct.c=11<br />
这个程序展示了静态初始化的各种特性。如果你初次接触Java，结果可能令你吃惊。可能会对static后加大括号感到困惑。首先要告诉你的是， static定义的变量会优先于任何其它非static变量，不论其出现的顺序如何。正如在程序中所表现的，虽然v出现在v1和v2的前面，但是结果却是 v1和v2的初始化在v的前面。在static{后面跟着一段代码，这是用来进行显式的静态变量初始化，这段代码只会初始化一次，且在类被第一次装载时。如果你能读懂并理解这段代码，会帮助你对static关键字的认识。在涉及到继承的时候，会先初始化父类的static变量，然后是子类的，依次类推。非静态变量不是本文的主题，在此不做详细讨论，请参考Think in Java中的讲解。<br />
静态类<br />
通常一个普通类不允许声明为静态的，只有一个内部类才可以。这时这个声明为静态的内部类可以直接作为一个普通类来使用，而不需实例一个外部类。如下代码所示：<br />
public class StaticCls{<br />
  public static void main(String[] args){<br />
    OuterCls.InnerCls oi=new OuterCls.InnerCls();<br />
  }<br />
}<br />
class OuterCls{<br />
  public static class InnerCls{<br />
    InnerCls(){<br />
      System.out.println(&#8220;InnerCls&#8221;);<br />
    }<br />
   }<br />
}<br />
输出结果会如你所料：<br />
InnerCls<br />
和普通类一样。内部类的其它用法请参阅Think in Java中的相关章节，此处不作详解。<br />
二、this &amp; super<br />
     在上一篇拙作中，我们讨论了static的种种用法，通过用static来定义方法或成员，为我们编程提供了某种便利，从某种程度上可以说它类似于C语言中的全局函数和全局变量。但是，并不是说有了这种便利，你便可以随处使用，如果那样的话，你便需要认真考虑一下自己是否在用面向对象的思想编程，自己的程序是否是面向对象的。好了，现在开始讨论this&amp;super这两个关键字的意义和用法。<br />
在Java中，this通常指当前对象， super则指父类的。当你想要引用当前对象的某种东西，比如当前对象的某个方法，或当前对象的某个成员，你便可以利用this来实现这个目的，当然， this的另一个用途是调用当前对象的另一个构造函数，这些马上就要讨论。如果你想引用父类的某种东西，则非super莫属。由于this与super有如此相似的一些特性和与生俱来的某种关系，所以我们在这一块儿来讨论，希望能帮助你区分和掌握它们两个。<br />
在一般方法中<br />
最普遍的情况就是，在你的方法中的某个形参名与当前对象的某个成员有相同的名字，这时为了不至于混淆，你便需要明确使用this关键字来指明你要使用某个成员，使用方法是 “this.成员名”，而不带this的那个便是形参。另外，还可以用“this.方法名”来引用当前对象的某个方法，但这时this就不是必须的了，你可以直接用方法名来访问那个方法，编译器会知道你要调用的是那一个。下面的代码演示了上面的用法：<br />
public class DemoThis{<br />
  private String name;<br />
  private int age;<br />
  DemoThis(String name,int age){<br />
    setName(name); //你可以加上this来调用方法，像这样：this.setName(name);但这并不是必须的<br />
    setAge(age);<br />
    this.print();<br />
  }<br />
  public void setName(String name){<br />
    this.name=name;//此处必须指明你要引用成员变量<br />
  }<br />
  public void setAge(int age){<br />
    this.age=age;<br />
  }<br />
  public void print(){<br />
    System.out.println(&#8220;Name=&#8221;+name+&#8221; Age=&#8221;+age);//在此行中并不需要用this，因为没有会导致混淆的东西<br />
  }<br />
  public static void main(String[] args){<br />
    DemoThis dt=new DemoThis(&#8220;Kevin&#8221;,&#8221;22&#8243;);<br />
  }<br />
}<br />
这段代码很简单，不用解释你也应该能看明白。在构造函数中你看到用this.print(),你完全可以用print()来代替它，两者效果一样。下面我们修改这个程序，来演示super的用法。<br />
class Person{<br />
  public int c;<br />
  private String name;<br />
  private int age;<br />
  protected void setName(String name){<br />
    this.name=name;<br />
  }<br />
  protected void setAge(int age){<br />
    this.age=age;<br />
  }<br />
  protected void print(){<br />
    System.out.println(&#8220;Name=&#8221;+name+&#8221; Age=&#8221;+age);<br />
  }<br />
}<br />
public class DemoSuper extends Person{<br />
  public void print(){<br />
    System.out.println(&#8220;DemoSuper:&#8221;);<br />
    super.print();<br />
  }<br />
  public static void main(String[] args){<br />
    DemoSuper ds=new DemoSuper();<br />
    ds.setName(&#8220;kevin&#8221;);<br />
    ds.setAge(22);<br />
    ds.print();<br />
  }<br />
}<br />
在DemoSuper中，重新定义的print方法覆写了父类的print方法，它首先做一些自己的事情，然后调用父类的那个被覆写了的方法。输出结果说明了这一点：<br />
DemoSuper:<br />
Name=kevin Age=22<br />
这样的使用方法是比较常用的。另外如果父类的成员可以被子类访问，那你可以像使用this一样使用它，用“super.父类中的成员名”的方式，但常常你并不是这样来访问父类中的成员名的。<br />
在构造函数中<br />
构造函数是一种特殊的方法，在对象初始化的时候自动调用。在构造函数中，this和super也有上面说的种种使用方式，并且它还有特殊的地方，请看下面的例子：<br />
class Person{<br />
  public static void prt(String s){<br />
    System.out.println(s);<br />
  }<br />
  Person(){<br />
    prt(&#8220;A Person.&#8221;);<br />
  }<br />
  Person(String name){<br />
    prt(&#8220;A person name is:&#8221;+name);<br />
  }<br />
}<br />
public class Chinese extends Person{<br />
  Chinese(){<br />
    super();  //调用父类构造函数（1）<br />
    prt(&#8220;A chinese.&#8221;);//(4)<br />
  }<br />
  Chinese(String name){<br />
    super(name);//调用父类具有相同形参的构造函数（2）<br />
    prt(&#8220;his name is:&#8221;+name);<br />
  }<br />
  Chinese(String name,int age){<br />
    this(name);//调用当前具有相同形参的构造函数（3）<br />
    prt(&#8220;his age is:&#8221;+age);<br />
  }<br />
  public static void main(String[] args){<br />
    Chinese cn=new Chinese();<br />
    cn=new Chinese(&#8220;kevin&#8221;);<br />
    cn=new Chinese(&#8220;kevin&#8221;,22);<br />
  }<br />
}<br />
在这段程序中，this和super不再是像以前那样用“.”连接一个方法或成员，而是直接在其后跟上适当的参数，因此它的意义也就有了变化。super后加参数的是用来调用父类中具有相同形式的构造函数，如1和2处。this后加参数则调用的是当前具有相同参数的构造函数，如3处。当然，在Chinese 的各个重载构造函数中，this和super在一般方法中的各种用法也仍可使用，比如4处，你可以将它替换为“this.prt”(因为它继承了父类中的那个方法）或者是“super.prt”（因为它是父类中的方法且可被子类访问），它照样可以正确运行。但这样似乎就有点画蛇添足的味道了。<br />
最后，写了这么多，如果你能对“this通常指代当前对象，super通常指代父类”这句话牢记在心，那么本篇便达到了目的，其它的你自会在以后的编程实践当中慢慢体会、掌握。另外关于本篇中提到的继承，请参阅相关Java教程。<br />
三、final<br />
final 在Java中并不常用，然而它却为我们提供了诸如在C语言中定义常量的功能，不仅如此，final还可以让你控制你的成员、方法或者是一个类是否可被覆写或继承等功能，这些特点使final在Java中拥有了一个不可或缺的地位，也是学习Java时必须要知道和掌握的关键字之一。<br />
final成员<br />
当你在类中定义变量时，在其前面加上final关键字，那便是说，这个变量一旦被初始化便不可改变，这里不可改变的意思对基本类型来说是其值不可变，而对于对象变量来说其引用不可再变。其初始化可以在两个地方，一是其定义处，也就是说在final变量定义时直接给其赋值，二是在构造函数中。这两个地方只能选其一，要么在定义时给值，要么在构造函数中给值，不能同时既在定义时给了值，又在构造函数中给另外的值。下面这段代码演示了这一点：<br />
import java.util.List;<br />
import java.util.ArrayList;<br />
import java.util.LinkedList;<br />
public class Bat{<br />
    final PI=3.14;          //在定义时便给址值<br />
    final int i;            //因为要在构造函数中进行初始化，所以此处便不可再给值<br />
    final List list;        //此变量也与上面的一样<br />
    Bat(){<br />
        i=100;<br />
        list=new LinkedList();<br />
    }<br />
    Bat(int ii,List l){<br />
        i=ii;<br />
        list=l;<br />
    }<br />
    public static void main(String[] args){<br />
        Bat b=new Bat();<br />
        b.list.add(new Bat());<br />
        //b.i=25;<br />
        //b.list=new ArrayList();<br />
        System.out.println(&#8220;I=&#8221;+b.i+&#8221; List Type:&#8221;+b.list.getClass());<br />
        b=new Bat(23,new ArrayList());<br />
        b.list.add(new Bat());<br />
        System.out.println(&#8220;I=&#8221;+b.i+&#8221; List Type:&#8221;+b.list.getClass());<br />
    }<br />
}<br />
此程序很简单的演示了final的常规用法。在这里使用在构造函数中进行初始化的方法，这使你有了一点灵活性。如Bat的两个重载构造函数所示，第一个缺省构造函数会为你提供默认的值，重载的那个构造函数会根据你所提供的值或类型为final变量初始化。然而有时你并不需要这种灵活性，你只需要在定义时便给定其值并永不变化，这时就不要再用这种方法。在main方法中有两行语句注释掉了，如果你去掉注释，程序便无法通过编译，这便是说，不论是i的值或是 list的类型，一旦初始化，确实无法再更改。然而b可以通过重新初始化来指定i的值或list的类型，输出结果中显示了这一点：<br />
I=100 List Type:class java.util.LinkedList<br />
I=23 List Type:class java.util.ArrayList<br />
还有一种用法是定义方法中的参数为final，对于基本类型的变量，这样做并没有什么实际意义，因为基本类型的变量在调用方法时是传值的，也就是说你可以在方法中更改这个参数变量而不会影响到调用语句，然而对于对象变量，却显得很实用，因为对象变量在传递时是传递其引用，这样你在方法中对对象变量的修改也会影响到调用语句中的对象变量，当你在方法中不需要改变作为参数的对象变量时，明确使用final进行声明，会防止你无意的修改而影响到调用方法。<br />
另外方法中的内部类在用到方法中的参变量时，此参变也必须声明为final才可使用，如下代码所示：<br />
public class INClass{<br />
   void innerClass(final String str){<br />
        class IClass{<br />
            IClass(){<br />
                System.out.println(str);<br />
            }<br />
        }<br />
        IClass ic=new IClass();<br />
    }<br />
  public static void main(String[] args){<br />
      INClass inc=new INClass();<br />
      inc.innerClass(&#8220;Hello&#8221;);<br />
  }<br />
}<br />
final方法<br />
将方法声明为final，那就说明你已经知道这个方法提供的功能已经满足你要求，不需要进行扩展，并且也不允许任何从此类继承的类来覆写这个方法，但是继承仍然可以继承这个方法，也就是说可以直接使用。另外有一种被称为inline的机制，它会使你在调用final方法时，直接将方法主体插入到调用处，而不是进行例行的方法调用，例如保存断点，压栈等，这样可能会使你的程序效率有所提高，然而当你的方法主体非常庞大时，或你在多处调用此方法，那么你的调用主体代码便会迅速膨胀，可能反而会影响效率，所以你要慎用final进行方法定义。<br />
final类<br />
当你将final用于类身上时，你就需要仔细考虑，因为一个final类是无法被任何人继承的，那也就意味着此类在一个继承树中是一个叶子类，并且此类的设计已被认为很完美而不需要进行修改或扩展。对于final类中的成员，你可以定义其为final，也可以不是final。而对于方法，由于所属类为final的关系，自然也就成了final型的。你也可以明确的给final类中的方法加上一个final，但这显然没有意义。<br />
下面的程序演示了final方法和final类的用法：<br />
final class final{<br />
      final String str=&#8221;final Data&#8221;;<br />
      public String str1=&#8221;non final data&#8221;;<br />
      final public void print(){<br />
           System.out.println(&#8220;final method.&#8221;);<br />
      }<br />
      public void what(){<br />
             System.out.println(str+&#8221;\n&#8221;+str1);<br />
     }<br />
}<br />
public class FinalDemo{//extends final无法继承<br />
        public static void main(String[] args){<br />
              final f=new final();<br />
               f.what();<br />
               f.print();<br />
    }<br />
}<br />
从程序中可以看出，final类与普通类的使用几乎没有差别，只是它失去了被继承的特性。final方法与非final方法的区别也很难从程序行看出，只是记住慎用。<br />
final在设计模式中的应用<br />
在设计模式中有一种模式叫做不变模式，在Java中通过final关键字可以很容易的实现这个模式，在讲解final成员时用到的程序Bat.java就是一个不变模式的例子。如果你对此感兴趣，可以参考阎宏博士编写的《Java与模式》一书中的讲解。<br />
到此为止，this,static,supert和final的使用已经说完了，如果你对这四个关键字已经能够大致说出它们的区别与用法，那便说明你基本已经掌握。然而，世界上的任何东西都不是完美无缺的，Java提供这四个关键字，给程序员的编程带来了很大的便利，但并不是说要让你到处使用，一旦达到滥用的程序，便适得其反，所以在使用时请一定要认真考虑。<br />
&#8212;&#8211;</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/169/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>八大素质让你前程无忧</title>
		<link>http://welog.org/blog/165</link>
		<comments>http://welog.org/blog/165#comments</comments>
		<pubDate>Wed, 18 May 2005 06:55:02 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/%e5%85%ab%e5%a4%a7%e7%b4%a0%e8%b4%a8%e8%ae%a9%e4%bd%a0%e5%89%8d%e7%a8%8b%e6%97%a0%e5%bf%a7/</guid>
		<description><![CDATA[进取心是使个体具有目标指向性和适度活力的内部能源，认真而持久的工作是个体事业成功的前提，而具有进取特质的个体也就具有了职业成功的心理基石。责任心强的人常能够审时度势选择适度的目标，并持久地、自信地追求这个目标，责任心强的人事业容易成功。 进取心是使个体具有目标指向性和适度活力的内部能源，认真而持久的工作是个体事业成功的前提，而具有进取特质的个体也就具有了职业成功的心理基石。责任心强的人常能够审时度势选择适度的目标，并持久地、自信地追求这个目标，责任心强的人事业容易成功。 　　[B]自信心[/B] 　　自信为个体在逆境中开拓、创新提供了信心和勇气，也为怀疑和批评提供了信心和勇气，自信常常使自己的好梦成真。没有信心的人会变得平庸、怯懦、顺从。喜欢挑战、战胜失败、突破逆境是自信心强的特点。 　　[B]自我力量感[/B] 　　虽然人的能力存在差别，但只要个体具有中等程度的智力，再加上善于总结经验、教训，善于改进方法和策略，那么，经过主观努力之后，许多事情是能够完成的。因此，可以把成功和失败归因于努力水平的高低和工作方法的优劣。 [B]自我认识自我调节[/B] 　　了解自己的优势和短处，与组织环境的关系，善于调节自己的生涯规划、学习时间等。 　　[B]情绪稳定性[/B] 　　稳定的情绪对技术性工作有预测力。冷静、稳定的情绪状态为工作提供了适度的激活水平。焦虑和抑郁会使人无端紧张、烦恼或无力，恐惧和急躁易使人忙中出乱。 　　[B]社会敏感性[/B] 　　对人际交往性质和发展趋势的洞察力和预见力，善于把握人际交往间的逻辑关系。行动之前要思考行为的结果，设身处地的想一想他人处境，乐于与人交往，能设身处地体察他人的感受。 　　[B]社会接纳性[/B] 　　在承认人人有差别和有不足的前提下接纳他人，社会接纳性是建立深厚的个人关系的基矗真诚对他人及他人的言语感兴趣，言语表达时认真倾听并注视对方。 　　[B]社会影响力[/B] 　　有以正直和公正为基础的说服力，有使他人发展和合作的精神，有一致性和耐力。善于沟通和交流。具有自信心、幽默等对情感的感染力，仔细、镇静、沉着等对行为的影响力，仪表、身姿等对视觉的影响力，忠诚和正直等对道德品德的感染力。 &#8212;&#8211;]]></description>
			<content:encoded><![CDATA[<p>进取心是使个体具有目标指向性和适度活力的内部能源，认真而持久的工作是个体事业成功的前提，而具有进取特质的个体也就具有了职业成功的心理基石。责任心强的人常能够审时度势选择适度的目标，并持久地、自信地追求这个目标，责任心强的人事业容易成功。<br />
<span id="more-165"></span><br />
进取心是使个体具有目标指向性和适度活力的内部能源，认真而持久的工作是个体事业成功的前提，而具有进取特质的个体也就具有了职业成功的心理基石。责任心强的人常能够审时度势选择适度的目标，并持久地、自信地追求这个目标，责任心强的人事业容易成功。</p>
<p>　　[B]自信心[/B]</p>
<p>　　自信为个体在逆境中开拓、创新提供了信心和勇气，也为怀疑和批评提供了信心和勇气，自信常常使自己的好梦成真。没有信心的人会变得平庸、怯懦、顺从。喜欢挑战、战胜失败、突破逆境是自信心强的特点。</p>
<p>　　[B]自我力量感[/B]</p>
<p>　　虽然人的能力存在差别，但只要个体具有中等程度的智力，再加上善于总结经验、教训，善于改进方法和策略，那么，经过主观努力之后，许多事情是能够完成的。因此，可以把成功和失败归因于努力水平的高低和工作方法的优劣。</p>
<p>[B]自我认识自我调节[/B]</p>
<p>　　了解自己的优势和短处，与组织环境的关系，善于调节自己的生涯规划、学习时间等。</p>
<p>　　[B]情绪稳定性[/B]</p>
<p>　　稳定的情绪对技术性工作有预测力。冷静、稳定的情绪状态为工作提供了适度的激活水平。焦虑和抑郁会使人无端紧张、烦恼或无力，恐惧和急躁易使人忙中出乱。</p>
<p>　　[B]社会敏感性[/B]</p>
<p>　　对人际交往性质和发展趋势的洞察力和预见力，善于把握人际交往间的逻辑关系。行动之前要思考行为的结果，设身处地的想一想他人处境，乐于与人交往，能设身处地体察他人的感受。</p>
<p>　　[B]社会接纳性[/B]</p>
<p>　　在承认人人有差别和有不足的前提下接纳他人，社会接纳性是建立深厚的个人关系的基矗真诚对他人及他人的言语感兴趣，言语表达时认真倾听并注视对方。</p>
<p>　　[B]社会影响力[/B]</p>
<p>　　有以正直和公正为基础的说服力，有使他人发展和合作的精神，有一致性和耐力。善于沟通和交流。具有自信心、幽默等对情感的感染力，仔细、镇静、沉着等对行为的影响力，仪表、身姿等对视觉的影响力，忠诚和正直等对道德品德的感染力。<br />
&#8212;&#8211;</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/165/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>【狮子王３：Hakuna Matata】。</title>
		<link>http://welog.org/blog/161</link>
		<comments>http://welog.org/blog/161#comments</comments>
		<pubDate>Wed, 11 May 2005 01:31:07 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/%e3%80%90%e7%8b%ae%e5%ad%90%e7%8e%8b%ef%bc%93%ef%bc%9ahakuna-matata%e3%80%91%e3%80%82/</guid>
		<description><![CDATA[[IMG]upload/6.jpg[/IMG] 这部影片去年就出来了，那时候因为忙没来得及看之后也就忘记了，由于前二集的反应非常不错。今天看到了就拉下来欣赏一下！ 这部影片去年就出来了，那时候因为忙没来得及看之后也就忘记了，由于前二集的反应非常不错。今天看到了就拉下来欣赏一下！狮子王３与其说是部‘续集’，倒不如说是部‘外传’ （你要说是‘歪传’也行），本片在美国本地片名叫狮子王１&#189;（The Lion King 1 1/2），其他国家才称为狮子王３，据说迪士尼觉得在许多非英语系国家“分数”并不是普遍被理解的概念，因此海外版才直接称 为第３集。但就如同原名“１&#189;”所传达的，本片既非‘后传’；也非‘前传’，而是部特别的‘传中传’！呵呵 最可气的是他们二个家伙不时的暂停影片，:{ 有些故事细节没做到位。 [IMG]upload/2.jpg[/IMG] [IMG]upload/3.jpg[/IMG] [IMG]upload/4.jpg[/IMG] [IMG]upload/1.jpg[/IMG] [IMG]upload/5.jpg[/IMG] &#8212;&#8211;]]></description>
			<content:encoded><![CDATA[<p>[IMG]upload/6.jpg[/IMG]<br />
这部影片去年就出来了，那时候因为忙没来得及看之后也就忘记了，由于前二集的反应非常不错。今天看到了就拉下来欣赏一下！<br />
<span id="more-161"></span><br />
这部影片去年就出来了，那时候因为忙没来得及看之后也就忘记了，由于前二集的反应非常不错。今天看到了就拉下来欣赏一下！狮子王３与其说是部‘续集’，倒不如说是部‘外传’ （你要说是‘歪传’也行），本片在美国本地片名叫狮子王１&frac12;（The Lion King 1 1/2），其他国家才称为狮子王３，据说迪士尼觉得在许多非英语系国家“分数”并不是普遍被理解的概念，因此海外版才直接称 为第３集。但就如同原名“１&frac12;”所传达的，本片既非‘后传’；也非‘前传’，而是部特别的‘传中传’！呵呵 最可气的是他们二个家伙不时的暂停影片，:{ 有些故事细节没做到位。</p>
<p>[IMG]upload/2.jpg[/IMG]</p>
<p>[IMG]upload/3.jpg[/IMG]</p>
<p>[IMG]upload/4.jpg[/IMG]</p>
<p>[IMG]upload/1.jpg[/IMG]</p>
<p>[IMG]upload/5.jpg[/IMG]</p>
<p>&#8212;&#8211;</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/161/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>基于J2ME手机游戏开发与实现!!!</title>
		<link>http://welog.org/blog/153</link>
		<comments>http://welog.org/blog/153#comments</comments>
		<pubDate>Fri, 29 Apr 2005 03:43:31 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/%e5%9f%ba%e4%ba%8ej2me%e6%89%8b%e6%9c%ba%e6%b8%b8%e6%88%8f%e5%bc%80%e5%8f%91%e4%b8%8e%e5%ae%9e%e7%8e%b0/</guid>
		<description><![CDATA[这段时间一直在忙着这个程序，从布局到最后的实现花了快一个多月，不管怎么说还是达成了自己预定的目标。 由于对J2ME是初次涉及除了API的学习之外环境配置也是一件很头痛的事，不过这次的开发用了Eclips方便了不少。同时也让我了解了一下OPEN的概念，从而让我想起那句“程序员不用说写代码就对了”，看来这句话还是有道理的，OK说得太远了，把程序的实现过程在此总结一下吧！！ 这段时间一直在忙着这个程序，从布局到最后的实现花了快一个多月，不管怎么说还是达成了自己预定的目标。 由于对J2ME是初次涉及除了API的学习之外环境配置也是一件很头痛的事，不过这次的开发用了Eclips方便了不少。同时也让我了解了一下OPEN的概念，从而让我想起那句“程序员不用说写代码就对了”，看来这句话还是有道理的，OK说得太远了，把程序的实现过程在此总结一下吧！！ [B]开发环境[/B] 操作系统：Microsoft Windows 2003 程序语言：Java 2 开发包： Java(TM) 2 Standard Edition (build 1.4.2_04 Sun Micro. J2ME Wireless Tool Kit 2.2 IDE: Eclise 9.0 [B]程序的主要流程[/B] [IMG]upload/tank.JPG[/IMG] [B]程序的实现[/B] Wireless Tool Kit 2.2+Nokia7210 Modo [IMG]upload/tank1.gif[/IMG] [IMG]upload/tank2.gif[/IMG] 程序的开始界面 程序运行时界面 [FONT-COLOR=Green][B]目前发现的bug和未完善的功能列表如下：[/B][/FONT-COLOR] 1. 与敌人对子弹的时候有时候可能会出现当敌人死后，自己若仍在原地，子弹会发不出去。 2. 敌人的人工智能变化较少，不够理想。 3. 子弹和敌人经常会与画面的刷新的线程不同步，造成画面闪烁。 4. 由于每次子弹发射和每次坦克的移动的一个象素都会对所有坦克和所有子弹进行一次循环检查，并由于同时开的线程比较多，使得本来运行效率就不高的KVM运行异常缓慢。即使刷屏没有间隔也不会提高速度。 5. 最好有接宝物的设置，增强可玩性。 6. 当敌人和自己同时死亡时，仍会过关，但gameover字样会出现，下一关坦克不会出现，但可以隐身发炮。 [FONT-COLOR=Blue][B]已经解决的重要bug:[/B][/FONT-COLOR] 1. 当发出子弹到达边界并同时还在草丛中时会抛出数组边界异常。 &#8230; <a href="http://welog.org/blog/153">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>这段时间一直在忙着这个程序，从布局到最后的实现花了快一个多月，不管怎么说还是达成了自己预定的目标。<br />
由于对J2ME是初次涉及除了API的学习之外环境配置也是一件很头痛的事，不过这次的开发用了Eclips方便了不少。同时也让我了解了一下OPEN的概念，从而让我想起那句“程序员不用说写代码就对了”，看来这句话还是有道理的，OK说得太远了，把程序的实现过程在此总结一下吧！！<br />
<span id="more-153"></span><br />
这段时间一直在忙着这个程序，从布局到最后的实现花了快一个多月，不管怎么说还是达成了自己预定的目标。<br />
由于对J2ME是初次涉及除了API的学习之外环境配置也是一件很头痛的事，不过这次的开发用了Eclips方便了不少。同时也让我了解了一下OPEN的概念，从而让我想起那句“程序员不用说写代码就对了”，看来这句话还是有道理的，OK说得太远了，把程序的实现过程在此总结一下吧！！</p>
<p>[B]开发环境[/B]<br />
操作系统：Microsoft Windows 2003<br />
程序语言：Java 2<br />
开发包：  Java(TM) 2 Standard Edition (build 1.4.2_04<br />
         Sun Micro.    J2ME   Wireless Tool Kit 2.2<br />
IDE:     Eclise 9.0</p>
<p>[B]程序的主要流程[/B]<br />
[IMG]upload/tank.JPG[/IMG]</p>
<p>[B]程序的实现[/B]<br />
  Wireless Tool Kit 2.2+Nokia7210 Modo</p>
<p>  [IMG]upload/tank1.gif[/IMG]  [IMG]upload/tank2.gif[/IMG]<br />
                    程序的开始界面                                      程序运行时界面</p>
<p>   [FONT-COLOR=Green][B]目前发现的bug和未完善的功能列表如下：[/B][/FONT-COLOR]<br />
   1.  与敌人对子弹的时候有时候可能会出现当敌人死后，自己若仍在原地，子弹会发不出去。<br />
    2.  敌人的人工智能变化较少，不够理想。<br />
    3.  子弹和敌人经常会与画面的刷新的线程不同步，造成画面闪烁。<br />
    4.  由于每次子弹发射和每次坦克的移动的一个象素都会对所有坦克和所有子弹进行一次循环检查，并由于同时开的线程比较多，使得本来运行效率就不高的KVM运行异常缓慢。即使刷屏没有间隔也不会提高速度。<br />
    5.  最好有接宝物的设置，增强可玩性。<br />
    6.  当敌人和自己同时死亡时，仍会过关，但gameover字样会出现，下一关坦克不会出现，但可以隐身发炮。</p>
<p>    [FONT-COLOR=Blue][B]已经解决的重要bug:[/B][/FONT-COLOR]<br />
   1.  当发出子弹到达边界并同时还在草丛中时会抛出数组边界异常。<br />
    2.  有时会莫名其妙的死机。<br />
    3.  当坦克在草丛中时，对方坦克发出的子弹不能将其击毁。</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/153/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>THINKING IN JAVA 5</title>
		<link>http://welog.org/blog/119</link>
		<comments>http://welog.org/blog/119#comments</comments>
		<pubDate>Sun, 20 Mar 2005 18:28:45 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/thinking-in-java-5/</guid>
		<description><![CDATA[《Java编程思想》(第二版)第5章：隐藏实现细节 [b]让变动的事物与不变的事物彼此隔离，使面向对象设计(OOD)的首要考虑.考虑一下程序库的版本更新吧。[/b] 组件程序库(components&#160;library)的概念以及谁有资格去用其中组件等问题Java是通过关键字package等等来控制的。 《Java编程思想》(第二版)第5章：隐藏实现细节 [b]让变动的事物与不变的事物彼此隔离，使面向对象设计(OOD)的首要考虑.考虑一下程序库的版本更新吧。[/b] 组件程序库(components library)的概念以及谁有资格去用其中组件等问题Java是通过关键字package等等来控制的。 import关键字的用法，package关键字的用法，default package:同一个目录中的所有文件,如果没有明确的package声明,都会被视为该目录的default package. 当你编译数量较少的.java文件后，能够得到数量较多的.class文件。Java的jar压缩工具能将众多.class文件结合起来并予以压缩。 Java中没有类似C/C++的条件编译机制，原因是因为Java认为自己跨平台，而以前的条件编译正是为解决C/C++快平台问题而设计的。但是条件编译也有debug的功效，为了能更好的调试程序，你可以引入了原本在C中常用的断言机制（Assertion)，即建立Assertion类，并另外定义一个空的Assertion类放到不同的名字空间，当要把程序代码从调试版改为出货版的时候只要在原程序中导入空的Assertion类所在的package即可。这个技巧可用于任何类型的条件编译程序代码上。 Java访问权限修饰词(access specifiers): public,protected,private 应该置于class内的每个成员的定义前，无论此成员究竟是数据成员或函数。缺省的访问权限被解释成&#8221;friendly&#8221;。即同一个package内的其他所有classes都可以访问friendly成员，但对package以外的classes则形同private。public充当了访问接口的角色，而private则表示&#8221;不要碰我&#8221;。protecked表示继承类可以访问。 基于两个理由我们需要控制访问权限:1.给客户提供明确的接口，划定界限。2.将接口和实现分离。 Class的访问权限:Java的访问权限也可以用来决定&#8221;程序库中哪些classes可以被程序库使用者所用&#8221;，为classes设定的访问权限，可以控制客户端程序员或者说库使用者是否有权利产生某个class的对象。不过,这里还存在一些限制 1.每个编译单元(文件）都仅能有一个public class . 2.虽然通常不会这么做,但编译单元的确可以不含任何public class.这种情况下你可以任意给定文件名称.注意此时只要拿掉class定义前面的public 关键字即可,因为默认的是friendly,这表示同一个package内的其他classes能够乘胜该class的对象,而package之外则否.不过如果该class有某个static public 成员,那么客户端程序员即使无法生成该class的对象,仍然能够访问这个static成员. 3.class不能是private,protected的.(内隐类inner class除外).如果你不希望任何其他人取用某个class,请将其所有的构造函数申明为private,如此便可以阻止任何人产生其对象.惟有两个例外,class static成员中可以办到,继承类也可以办到.请看下面的例子: //Demonstrates class access specifiers. Make a class effectively private with private constructors class Soup{ private Soup(){} public static Soup makeSoup(){ return new Soup(); } } public &#8230; <a href="http://welog.org/blog/119">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>《Java编程思想》(第二版)第5章：隐藏实现细节</p>
<p>[b]让变动的事物与不变的事物彼此隔离，使面向对象设计(OOD)的首要考虑.考虑一下程序库的版本更新吧。[/b]</p>
<p>组件程序库(components&nbsp;library)的概念以及谁有资格去用其中组件等问题Java是通过关键字package等等来控制的。<br />
<span id="more-119"></span><br />
《Java编程思想》(第二版)第5章：隐藏实现细节</p>
<p>[b]让变动的事物与不变的事物彼此隔离，使面向对象设计(OOD)的首要考虑.考虑一下程序库的版本更新吧。[/b]</p>
<p>组件程序库(components library)的概念以及谁有资格去用其中组件等问题Java是通过关键字package等等来控制的。</p>
<p>import关键字的用法，package关键字的用法，default package:同一个目录中的所有文件,如果没有明确的package声明,都会被视为该目录的default package.</p>
<p>当你编译数量较少的.java文件后，能够得到数量较多的.class文件。Java的jar压缩工具能将众多.class文件结合起来并予以压缩。</p>
<p>Java中没有类似C/C++的条件编译机制，原因是因为Java认为自己跨平台，而以前的条件编译正是为解决C/C++快平台问题而设计的。但是条件编译也有debug的功效，为了能更好的调试程序，你可以引入了原本在C中常用的断言机制（Assertion)，即建立Assertion类，并另外定义一个空的Assertion类放到不同的名字空间，当要把程序代码从调试版改为出货版的时候只要在原程序中导入空的Assertion类所在的package即可。这个技巧可用于任何类型的条件编译程序代码上。</p>
<p>Java访问权限修饰词(access specifiers): public,protected,private 应该置于class内的每个成员的定义前，无论此成员究竟是数据成员或函数。缺省的访问权限被解释成&#8221;friendly&#8221;。即同一个package内的其他所有classes都可以访问friendly成员，但对package以外的classes则形同private。public充当了访问接口的角色，而private则表示&#8221;不要碰我&#8221;。protecked表示继承类可以访问。</p>
<p>基于两个理由我们需要控制访问权限:1.给客户提供明确的接口，划定界限。2.将接口和实现分离。</p>
<p>Class的访问权限:Java的访问权限也可以用来决定&#8221;程序库中哪些classes可以被程序库使用者所用&#8221;，为classes设定的访问权限，可以控制客户端程序员或者说库使用者是否有权利产生某个class的对象。不过,这里还存在一些限制<br />
   1.每个编译单元(文件）都仅能有一个public class .<br />
   2.虽然通常不会这么做,但编译单元的确可以不含任何public class.这种情况下你可以任意给定文件名称.注意此时只要拿掉class定义前面的public 关键字即可,因为默认的是friendly,这表示同一个package内的其他classes能够乘胜该class的对象,而package之外则否.不过如果该class有某个static public 成员,那么客户端程序员即使无法生成该class的对象,仍然能够访问这个static成员.<br />
   3.class不能是private,protected的.(内隐类inner class除外).如果你不希望任何其他人取用某个class,请将其所有的构造函数申明为private,如此便可以阻止任何人产生其对象.惟有两个例外,class static成员中可以办到,继承类也可以办到.请看下面的例子:<br />
//Demonstrates class access specifiers.  Make a class effectively private with private constructors</p>
<p>class Soup{<br />
  private Soup(){}<br />
  public static Soup makeSoup(){<br />
      return new Soup();<br />
  }<br />
}<br />
public class Lunch{<br />
 void test(){<br />
    // Can&#8217;t do this ! Private constructor:<br />
    // Soup priv1=new Soup();<br />
    Soup priv2=Soup.makeSoup();<br />
 }<br />
}<br />
class soup示范如何将所有构造函数都声明为private以防止直接产生某个class对象。<br />
如果你希望在执行Soup之前先尽享某些额外处理,或希望记录(或限制)究竟有多少个Soup对象被产生出来,这种做法十分有用.<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
我的问题：<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>当import java.until.*时 java.until.system.*会不会引入？</p>
<p>当class定义为public，而所有的构造函数定义为private，会有什么效果？</p>
<p>&#8212;&#8211;</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/119/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>THINKING in JAVA 第四章</title>
		<link>http://welog.org/blog/132</link>
		<comments>http://welog.org/blog/132#comments</comments>
		<pubDate>Sun, 20 Mar 2005 18:26:59 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/thinking-in-java-%e7%ac%ac%e5%9b%9b%e7%ab%a0/</guid>
		<description><![CDATA[&#34;[b]每个函数的第一个字母以小写表示[/b]&#34;这种编程风格不适用于构造函数身上，因为构造函数的名称必须完全吻合class名称 在Java（和C++)中，构造函数是&#34;函数名称必须能被重载&#34;的另一个原因。每个重载函数必须拥有独一无二的引数列（argument&#160;list），而不可以以返回值（return&#160;value）作为重载的基准，因为有时候我们是以f（）来执行函数调用的，但是此时并没有返回值的任何信息，编译器会束手无策。 Default构造函数会不会被编译器主动提供则类似于C++：当您没有定义任何构造函数的时候编译器会自动提供，而当您提供了任何一个构造函数的时候，编译器是不会再给你提供default构造函数的。 &#8220;[b]每个函数的第一个字母以小写表示[/b]&#8220;这种编程风格不适用于构造函数身上，因为构造函数的名称必须完全吻合class名称 在Java（和C++)中，构造函数是&#8221;函数名称必须能被重载&#8221;的另一个原因。每个重载函数必须拥有独一无二的引数列（argument list），而不可以以返回值（return value）作为重载的基准，因为有时候我们是以f（）来执行函数调用的，但是此时并没有返回值的任何信息，编译器会束手无策。 Default构造函数会不会被编译器主动提供则类似于C++：当您没有定义任何构造函数的时候编译器会自动提供，而当您提供了任何一个构造函数的时候，编译器是不会再给你提供default构造函数的。 有时候为了方便我们需要在构造函数中调用构造函数。下面的例子告诉我们一些行为规则： // Calling constructors with &#8220;this&#8221; public class Flower{ int petalCount=0; String s=new String(&#8220;null&#8221;); Flower(int petals){ petalCount=petals; } Flower(String ss){ s=ss; } Flower(String s,int petals){ this(petals); //! this(s); //Can&#8217;t call twice! this.s=s; } Flower(){ this(&#8220;hi&#8221;,47); } void print(){ //! this (11); //Not inside non-constructor! } public static &#8230; <a href="http://welog.org/blog/132">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>&quot;[b]每个函数的第一个字母以小写表示[/b]&quot;这种编程风格不适用于构造函数身上，因为构造函数的名称必须完全吻合class名称</p>
<p>在Java（和C++)中，构造函数是&quot;函数名称必须能被重载&quot;的另一个原因。每个重载函数必须拥有独一无二的引数列（argument&nbsp;list），而不可以以返回值（return&nbsp;value）作为重载的基准，因为有时候我们是以f（）来执行函数调用的，但是此时并没有返回值的任何信息，编译器会束手无策。</p>
<p>Default构造函数会不会被编译器主动提供则类似于C++：当您没有定义任何构造函数的时候编译器会自动提供，而当您提供了任何一个构造函数的时候，编译器是不会再给你提供default构造函数的。<br />
<span id="more-132"></span><br />
&#8220;[b]每个函数的第一个字母以小写表示[/b]&#8220;这种编程风格不适用于构造函数身上，因为构造函数的名称必须完全吻合class名称</p>
<p>在Java（和C++)中，构造函数是&#8221;函数名称必须能被重载&#8221;的另一个原因。每个重载函数必须拥有独一无二的引数列（argument list），而不可以以返回值（return value）作为重载的基准，因为有时候我们是以f（）来执行函数调用的，但是此时并没有返回值的任何信息，编译器会束手无策。</p>
<p>Default构造函数会不会被编译器主动提供则类似于C++：当您没有定义任何构造函数的时候编译器会自动提供，而当您提供了任何一个构造函数的时候，编译器是不会再给你提供default构造函数的。</p>
<p>有时候为了方便我们需要在构造函数中调用构造函数。下面的例子告诉我们一些行为规则：</p>
<p>// Calling constructors with &#8220;this&#8221;</p>
<p>public class Flower{<br />
 int petalCount=0;<br />
 String s=new String(&#8220;null&#8221;);<br />
 Flower(int petals){<br />
  petalCount=petals;<br />
 }<br />
 Flower(String ss){<br />
  s=ss;<br />
 }<br />
 Flower(String s,int petals){<br />
  this(petals);<br />
  //!   this(s);  //Can&#8217;t call twice!<br />
  this.s=s;<br />
 }<br />
 Flower(){<br />
  this(&#8220;hi&#8221;,47);<br />
 }<br />
 void print(){<br />
  //!  this (11); //Not inside non-constructor!<br />
 }<br />
 public static void main(String[] args){<br />
  Flower x=new Flower();<br />
  x.print();<br />
 }<br />
}</p>
<p>此段程序告诉我们几点：<br />
   1.虽然你能够藉由this调用一个构造函数，却不能以相同手法调用两个。<br />
   2.对另一构造函数的调用动作必须置于最其实除，否则编译器会发出错误消息。<br />
   3.在print（）函数中你可以看出，编译器不允许你在构造函数以外的任何函数内调用构造函数,即构造函数只用于new关键字由系统自动调用。</p>
<p>finalize()第一种用法可以在垃圾回收之前给你做一些特殊的处理，因为垃圾回收只回收内存的，如果你有一些别的资源应该释放或者在对象销毁之前作一些动作比如说擦除以前绘制的图像等等，就应该会用到它。第二种用法：当采用原生函数(native methods)时，可以在finalize中调用free（）来释放先前malloc（）函数分配的内存。</p>
<p>Garbage collector的运作依赖于Java的两个关键技术：单根继承技术（继承自Object),对象完全从堆（heap）中分配内存（而非类成员的基本类型变量则放在stack中分配，为了效率的考虑）</p>
<p>在Java中 定义和初始化是一体的，两者不可能彼此脱离而独立存在。</p>
<p>成员初始化：Java保证，变量绝对会在被使用之前被适当初始化。当变量被定义与函数之内时，Java会运用编译期错误消息来贯彻它的保证。如果某个class的数据成员隶属基本类型，情况则稍有不同。因为所有函数都可以初始化或使用该数据值，所以强迫使用者一定得在使用之前给定适当初始值是不切实际的。不过，放任它持有毫无意义的处置也很危险，所以每个&#8221;隶属基本类别&#8221;的class数据成员都保证一定有初始值，即编译器设定默认初始值了。当然我们也可以方便的直接在class的变量定义出指定其值。构造函数可用来执行初始化操作，此时class中的初始化次序取决于变量在class中的定义次序。对于static的初始化动作之在必要时（一次且只有一次）可才会发生(比如被访问。或者所属的class第一个对象被建立此时，此时该static变量先于所有non-static变量初始化），自此之后，static对象便不会再被初始化。</p>
<p>Array的初始化：任何数组对象都隐含了length成员。在对数据元素存取的时候要做Java会对执行边界检查，而且你无法关闭此功能，牺牲程序的执行效率但是更安全，消除了C/C++数组的弊端，还完全灭杀了buffer overflow 攻击者的生存空间。</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/132/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>如何使用Java中取得Win2000系统当前登录帐户和主文件夹</title>
		<link>http://welog.org/blog/89</link>
		<comments>http://welog.org/blog/89#comments</comments>
		<pubDate>Tue, 15 Mar 2005 07:22:18 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8java%e4%b8%ad%e5%8f%96%e5%be%97win2000%e7%b3%bb%e7%bb%9f%e5%bd%93%e5%89%8d%e7%99%bb%e5%bd%95%e5%b8%90%e6%88%b7%e5%92%8c%e4%b8%bb%e6%96%87%e4%bb%b6%e5%a4%b9/</guid>
		<description><![CDATA[下面是一个小小的例子，它可以取得WIndows2000、WindowsXP系统中当前登录用户的用户名和主文件夹，一下代码Copy过去就可以运行。 Good&#160;Luck&#160;;) 下面是一个小小的例子，它可以取得WIndows2000、WindowsXP系统中当前登录用户的用户名和主文件夹，一下代码Copy过去就可以运行。 Good Luck import java.util.*; import java.io.*; public class CurrentUser { public CurrentUser() { Process p = null; Properties envVars = new Properties(); Runtime r = Runtime.getRuntime(); try { p = r.exec( &#8220;cmd.exe /c set user&#8221; ); BufferedReader br = new BufferedReader ( new InputStreamReader( p.getInputStream() ) ); String line; //第一行是机器名;第二行是当前登陆的用户名，第三个是当前登陆用户的主文件夹 while( (line &#8230; <a href="http://welog.org/blog/89">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>下面是一个小小的例子，它可以取得WIndows2000、WindowsXP系统中当前登录用户的用户名和主文件夹，一下代码Copy过去就可以运行。</p>
<p>Good&nbsp;Luck&nbsp;;)<br />
<span id="more-89"></span><br />
下面是一个小小的例子，它可以取得WIndows2000、WindowsXP系统中当前登录用户的用户名和主文件夹，一下代码Copy过去就可以运行。</p>
<p>Good Luck <img src='http://welog.org/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p>import java.util.*;<br />
import java.io.*;</p>
<p>public class CurrentUser {<br />
  public CurrentUser() {<br />
    Process p = null;<br />
    Properties envVars = new Properties();<br />
    Runtime r = Runtime.getRuntime();<br />
    try<br />
    {<br />
    p = r.exec( &#8220;cmd.exe /c set user&#8221; );<br />
    BufferedReader br = new BufferedReader ( new InputStreamReader( p.getInputStream() ) );<br />
    String line;<br />
    //第一行是机器名;第二行是当前登陆的用户名，第三个是当前登陆用户的主文件夹<br />
    while( (line = br.readLine()) != null ) {<br />
      int idx = line.indexOf(&#8216;=&#8217;);<br />
      String key = line.substring(0, idx);<br />
      String value = line.substring(idx + 1);<br />
      envVars.setProperty(key, value);<br />
      System.out.println(key + &#8221; = &#8221; + value);<br />
    }<br />
    }<br />
    catch(Exception e)<br />
    {<br />
      e.printStackTrace();<br />
    }<br />
  }<br />
  public static void main(String[] args) {<br />
    CurrentUser currentUser1 = new CurrentUser();<br />
  }<br />
}</p>
<p>&#8212;&#8211;</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/89/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java编程思想读书笔记－5</title>
		<link>http://welog.org/blog/75</link>
		<comments>http://welog.org/blog/75#comments</comments>
		<pubDate>Tue, 15 Mar 2005 06:37:32 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/java%e7%bc%96%e7%a8%8b%e6%80%9d%e6%83%b3%e8%af%bb%e4%b9%a6%e7%ac%94%e8%ae%b0%ef%bc%8d5/</guid>
		<description><![CDATA[第10章&#160;&#160;&#160;&#160;通过异常处理错误 一．&#160;&#160;&#160;&#160;基本异常 第10章 通过异常处理错误 一． 基本异常 1. 抛出异常的原理 1) 像产生一个Java对象那样在heap上以new产生一个异常对象。 2) 停止目前的执行路线，将上述那个异常对象的reference自目前的context丢出。 3) 异常处理机制接手工作，寻找得以继续执行的适当地点。 2. 产生一个异常对象 异常类有两个构造函数：一个default构造函数；一个带String型参数的构造函数，参数的信息可以通过异常类中的各种方法取出。 3. 异常类的结构 [img]http://www.javaresearch.org/members/nepalon/exceptionClass.gif[/img] 1) Error是一些编译期错误或系统错误，一般无需在程序中捕捉到Error异常。 2) Exception是我们能捕捉到的异常，其中Exception异常又分为RuntimeException和non-RuntimeException两大类异常。 二． 异常的捕捉和处理 1. 异常的捕捉 1.1 通过try…catch就可捕捉异常 import java.lang.RuntimeException; import java.lang.NullPointerException; import java.sql.SQLException; import java.io.IOException; class TestException{ public void testSQLException() throws SQLException { throw new SQLException(); } public void testIOException() throws IOException &#8230; <a href="http://welog.org/blog/75">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>第10章&nbsp;&nbsp;&nbsp;&nbsp;通过异常处理错误</p>
<p>一．&nbsp;&nbsp;&nbsp;&nbsp;基本异常<br />
<span id="more-75"></span><br />
第10章    通过异常处理错误</p>
<p>一．    基本异常</p>
<p>1.    抛出异常的原理<br />
1)    像产生一个Java对象那样在heap上以new产生一个异常对象。<br />
2)    停止目前的执行路线，将上述那个异常对象的reference自目前的context丢出。<br />
3)    异常处理机制接手工作，寻找得以继续执行的适当地点。<br />
2.    产生一个异常对象<br />
异常类有两个构造函数：一个default构造函数；一个带String型参数的构造函数，参数的信息可以通过异常类中的各种方法取出。<br />
3.    异常类的结构 </p>
<p>[img]http://www.javaresearch.org/members/nepalon/exceptionClass.gif[/img]</p>
<p>1)    Error是一些编译期错误或系统错误，一般无需在程序中捕捉到Error异常。<br />
2)    Exception是我们能捕捉到的异常，其中Exception异常又分为RuntimeException和non-RuntimeException两大类异常。</p>
<p>二．    异常的捕捉和处理</p>
<p>1.    异常的捕捉<br />
1.1    通过try…catch就可捕捉异常<br />
import java.lang.RuntimeException;<br />
import java.lang.NullPointerException;<br />
import java.sql.SQLException;<br />
import java.io.IOException;<br />
class TestException{<br />
    public void testSQLException() throws SQLException {<br />
        throw new SQLException();<br />
    }<br />
    public void testIOException() throws IOException {}<br />
}<br />
public class Test{<br />
    public static void main(String[] args){<br />
        TestException te = new TestException();<br />
        try{<br />
            te.testSQLException();<br />
            te.testIOException();<br />
        }<br />
        catch(SQLException ex){<br />
            System.out.println(&#8220;catch SQLException in main&#8221;);<br />
        }<br />
        catch(IOException ex){<br />
            System.out.println(&#8220;catch IOException in main&#8221;);<br />
        }<br />
        catch(Exception ex){ //（1）<br />
            System.out.println(&#8220;catch Exception in main&#8221;);<br />
        }<br />
    }<br />
}</p>
<p>运行结果为：catch SQLException in main<br />
只有参数类型与异常类型相同或相近的catch会被执行。<br />
1.2    捕捉所有异常<br />
如果想捕捉所有异常，只要捕捉Exception异常就行，如上面代码的（1）处<br />
2.    异常规格（exception　specification）<br />
1)    在函数定义时可以声明异常规格。如果一个函数在异常规格中声明了non-RuntimeException异常，那么当调用这个函数时，就一定要捕捉异常规格中的non-RuntimeException异常。<br />
import java.lang.RuntimeException;<br />
import java.lang.NullPointerException;<br />
import java.sql.SQLException;<br />
class TestException{<br />
    //（1）异常规格中声明将抛出RuntimeException异常<br />
public void testRuntime() throws RuntimeException {}<br />
//（2）异常规格中声明将抛出NullPointerException异常<br />
public void testNullPointer() throws NullPointerException {}<br />
//（3）异常规格中声明将抛出non-RuntimeException异常<br />
    public void testNonRuntime() throws SQLException {}<br />
}<br />
public class Test{<br />
    public static void main(String[] args){<br />
        TestException te = new TestException();<br />
        te.testRuntime();　//（4）<br />
        te.testNullPointer();　//（5）<br />
        //te.testNonRuntime();　（6）<br />
        try{<br />
            te.testNonRuntime();<br />
        }<br />
        catch(SQLException ex){}<br />
    }<br />
}</p>
<p>在上述代码中，（1）处在异常规格中声明将抛出RuntimeException；（2）在异常规格中声明将抛出NullPointerException，而NullPointerException是RuntimeException的子类，所以在调用这两个函数时，可不捕捉异常，如（4）（5）处的代码一样直接调用。但（3）处在异常规格中声明将抛出SQLException，而SQLException不是RuntimeException的子类，所以必须捕捉SQLException异常。<br />
2)    如果要在一个函数中抛出non-RuntimeException异常，则必须要在异常规格中声明该异常。<br />
import java.sql.SQLException;<br />
import java.io.IOException;<br />
class Test1{<br />
    public void f() throws SQLException{　//（2）<br />
       throw new IOException(&#8220;IOException&#8221;); 　//（1）<br />
    }<br />
}<br />
public class ExplicitStatic{<br />
    public static void main(String[] args){<br />
        Test1 te = new Test1();<br />
        try{<br />
            te.f();<br />
        }<br />
        catch(Exception ex){<br />
            System.out.println(&#8220;catch Exception in main&#8221;);<br />
        }<br />
    }<br />
}</p>
<p>在（1）处抛出了一个没有在异常规格中被声明的non-RuntimeException异常，在编译时会出错。<br />
3.    取得异常中的信息的几个函数<br />
1)    String getMessage()、getLocalizedMessage 、toString<br />
取得异常对象中的信息<br />
import java.lang.RuntimeException;<br />
import java.lang.NullPointerException;<br />
Import java.sql.SQLException;<br />
import java.io.IOException;<br />
class TestException{<br />
            public void tSql() throws SQLException {<br />
                System.out.println(&#8220;Originating the exception in tSql()&#8221;);<br />
                throw new SQLException(&#8220;throw in tSql&#8221;);<br />
            }<br />
}<br />
public class Test{<br />
            public static void main(String[] args){<br />
                TestException te = new TestException();<br />
                try{<br />
                    te.tSql();<br />
                }<br />
                catch(SQLException ex){<br />
                    System.out.println(&#8220;catch SQLException in main&#8221;);<br />
                    System.out.println(&#8220;ex.getMessage()：&#8221; + ex.getMessage());<br />
System.out.println(&#8220;ex.getLocalizedMessage()：&#8221; +<br />
ex.getLocalizedMessage());<br />
                    System.out.println(&#8220;ex.toString()：&#8221; + ex.toString());<br />
                }<br />
                catch(Exception ex){<br />
                    System.out.println(&#8220;catch Exception in main&#8221;);<br />
                }<br />
            }<br />
}</p>
<p>运行结果：<br />
Originating the exception in tSql()<br />
catch SQLException in main<br />
ex.getMessage()：throw in tSql<br />
ex.getLocalizedMessage()：throw in tSql<br />
ex.toString()：java.sql.SQLException: throw in tSql<br />
2)    void printStackTrace()、Throwable fillStackTrace()<br />
printStackTrace打印出Throwable和其call　stack　trace。<br />
FillStackTrace则在调用点设立新的stack　trace信息<br />
import java.sql.SQLException;<br />
class TestException{<br />
    public static void tSql() throws SQLException {<br />
        System.out.println(&#8220;Originating the exception in tSql()&#8221;);<br />
        throw new SQLException(&#8220;throw in tSql&#8221;);<br />
    }<br />
    public void f() throws SQLException{<br />
        try{<br />
            tSql();<br />
        }<br />
        catch(SQLException ex){<br />
            System.out.println(&#8220;In f(), e.printStackTrace()&#8221;);<br />
            ex.printStackTrace();<br />
throw ex;　//（1）<br />
//throw (SQLException)ex.fillInStackTrace();　（2）<br />
        }<br />
    }<br />
}<br />
public class Test{<br />
    public static void main(String[] args){<br />
        TestException te = new TestException();<br />
        try{<br />
            te.f();<br />
        }<br />
        catch(SQLException ex){<br />
            System.out.println(&#8220;catch in main, e.printStackTrace()&#8221;);<br />
            ex.printStackTrace();<br />
        }<br />
        catch(Exception ex){<br />
            System.out.println(&#8220;catch Exception in main&#8221;);<br />
        }<br />
    }<br />
}</p>
<p>结果为：<br />
Originating the exception in tSql()<br />
In f(), e.printStackTrace()<br />
catch in main, e.printStackTrace()<br />
java.sql.SQLException: throw in tSql<br />
    void TestException.tSql()<br />
        Test.java:5<br />
    void TestException.f()<br />
        Test.java:9<br />
    void Test.main(java.lang.String[])<br />
        Test.java:22<br />
java.sql.SQLException: throw in tSql<br />
    void TestException.tSql()<br />
        Test.java:5<br />
    void TestException.f()<br />
        Test.java:9<br />
    void Test.main(java.lang.String[])<br />
        Test.java:22<br />
如果把（1）处代码注释掉，并去年（2）处代码的注释，结果将变成：<br />
Originating the exception in tSql()<br />
In f(), e.printStackTrace()<br />
catch in main, e.printStackTrace()<br />
java.sql.SQLException: throw in tSql<br />
    void TestException.tSql() //（3）<br />
        Test.java:6<br />
    void TestException.f()<br />
        Test.java:10<br />
    void Test.main(java.lang.String[])<br />
        Test.java:24<br />
java.sql.SQLException: throw in tSql<br />
    void TestException.f()　//（4）<br />
        Test.java:16<br />
    void Test.main(java.lang.String[])<br />
        Test.java:24<br />
由于在代码（2）处设立新的stack　trace信息，所以异常会被认为是在f()中发出的，所以在main()中得到的异常原始抛出点为f()（见（3）），而在f()中为tSql()（见（6））。<br />
3)    如果重新抛出一个不同类型的异常，也能产生fillStackTrace()函数的效果。如果把上面代码的f()函数修改成下面的样子：<br />
public void f() throws SQLException,IOException{<br />
try{<br />
        tSql();<br />
    }<br />
    catch(SQLException ex){<br />
        System.out.println(&#8220;In f(), e.printStackTrace()&#8221;);<br />
        ex.printStackTrace();<br />
        throw new IOException(); //（1）<br />
    }<br />
}</p>
<p>则结果为：<br />
Originating the exception in tSql()<br />
In f(), e.printStackTrace()<br />
catch Exception in main<br />
java.sql.SQLException: throw in tSql<br />
    void TestException.tSql()<br />
        Test.java:6<br />
    void TestException.f()<br />
        Test.java:10<br />
    void Test.main(java.lang.String[])<br />
        Test.java:25<br />
java.io.IOException<br />
    void TestException.f()<br />
        Test.java:17<br />
    void Test.main(java.lang.String[])<br />
        Test.java:25<br />
由于在（1）处抛出了一个新的类型的异常，那么在main()中捕捉到的是新的异常，所以在main()中捕捉到的异常的原始抛出点为f()。<br />
4.    RuntimeException异常<br />
RuntimeException及其子类所代表的异常我们在程序中不用进行捕捉，如果发生此类异常，Java会自动抛出相应的异常对象，如：<br />
class TestException{<br />
    public static void g(int x) {<br />
        System.out.println(&#8220;10/&#8221; + x + &#8221; = &#8221; + 10/x);<br />
    }<br />
}<br />
public class Test{<br />
    public static void main(String[] args){<br />
        TestException.g(2);<br />
        TestException.g(0);　//（1）<br />
    }<br />
}</p>
<p>上面代码在编译时不会发生错误，只有在运行时（1）处会发生错误。虽然除法可能会存在错误，但我们不用进行捕捉，当发生错误时，Java会自动抛出相应异常。</p>
<p>三．    以finally进行清理</p>
<p>1.    如果某段代码不管是否发生异常都要执行，那可把它改入finally块中。<br />
import java.sql.SQLException;<br />
class TestException{<br />
    public static void tSql() throws SQLException {<br />
        System.out.println(&#8220;Originating the exception in tSql()&#8221;);<br />
        throw new SQLException(&#8220;throw in tSql&#8221;);<br />
    }<br />
    public void f() throws SQLException{<br />
        try{<br />
            tSql();<br />
        }<br />
        catch(SQLException ex){<br />
            System.out.println(&#8220;catch SQLException in f()&#8221;);<br />
            throw ex;　//（1）<br />
        }<br />
        finally{<br />
            System.out.println(&#8220;finally in f()&#8221;);<br />
        }<br />
    }<br />
}<br />
public class Test{<br />
    public static void main(String[] args){<br />
        TestException te = new TestException();<br />
        try{<br />
            te.f();<br />
        }<br />
        catch(SQLException ex){<br />
            System.out.println(&#8220;catch te.f() SQLException in main&#8221;);<br />
        }<br />
        catch(Exception ex){<br />
            System.out.println(&#8220;catch te.f() Exception in main&#8221;);<br />
        }<br />
    }<br />
}</p>
<p>运行结果为：<br />
Originating the exception in tSql()<br />
catch SQLException in f()<br />
finally in f()<br />
catch te.f() SQLException in main<br />
虽然在代码（1）处重新抛出异常，但finally块中的代码仍然会被执行。<br />
2.    finally造成的异常遗失<br />
如果在finally中执行的代码又产生异常，那么在上一层调用中所捕捉到的异常的起始抛出点会是finally所在的函数。<br />
import java.sql.SQLException;<br />
class TestException{<br />
    public static void tSql1() throws SQLException {<br />
        System.out.println(&#8220;Originating the exception in tSql()&#8221;);<br />
        throw new SQLException(&#8220;throw in tSql1&#8243;);<br />
    }<br />
    public static void tSql2() throws SQLException {<br />
        System.out.println(&#8220;Originating the exception in tSql()&#8221;);<br />
        throw new SQLException(&#8220;throw in tSql2&#8243;);<br />
    }<br />
    public void f() throws SQLException{<br />
        try{<br />
            tSql1();<br />
        }<br />
        catch(SQLException ex){<br />
            System.out.println(&#8220;catch SQLException in f()&#8221;);<br />
            throw ex;　//（2）<br />
        }<br />
        finally{<br />
            System.out.println(&#8220;finally in f()&#8221;);<br />
            //tSql2();　（1）<br />
        }<br />
    }<br />
}<br />
public class Test{<br />
    public static void main(String[] args){<br />
        TestException te = new TestException();<br />
        try{<br />
            te.f();<br />
        }<br />
        catch(SQLException ex){<br />
            System.out.println(&#8220;catch te.f() SQLException in main&#8221;);<br />
            System.out.println(&#8220;getMessage：&#8221; + ex.getMessage());<br />
            System.out.println(&#8220;printStackTrace：&#8221;);<br />
            ex.printStackTrace();<br />
        }<br />
    }<br />
}</p>
<p>运行结果为：<br />
Originating the exception in tSql()<br />
catch SQLException in f()<br />
finally in f()<br />
catch te.f() SQLException in main<br />
getMessage：throw in tSql1<br />
printStackTrace：<br />
java.sql.SQLException: throw in tSql1<br />
    void TestException.tSql1()<br />
        Test.java:5<br />
    void TestException.f()<br />
        Test.java:13<br />
    void Test.main(java.lang.String[])<br />
        Test.java:29<br />
从结果可以看出，在main()中能正确打印出所捕捉到的异常的起始抛出点。但如果去掉代码（1）的注释，结果将变为：<br />
Originating the exception in tSql()<br />
catch SQLException in f()<br />
finally in f()<br />
Originating the exception in tSql()<br />
catch te.f() SQLException in main<br />
getMessage：throw in tSql2<br />
printStackTrace：<br />
java.sql.SQLException: throw in tSql2<br />
    void TestException.tSql2()<br />
        Test.java:9<br />
    void TestException.f()<br />
        Test.java:21<br />
    void Test.main(java.lang.String[])<br />
        Test.java:29<br />
从结果可以看出，在main()中捕捉到的异常是finally中产生的异常，代码（2）中抛出的异常丢失了。</p>
<p>四．    继承中异常</p>
<p>1.    关于构造函数中的异常<br />
1.1    构造函数中的异常规则<br />
某个derived　class构造函数的“异常规格接口“可以比其所调用的父类的构造函数的异常规格接口宽，但决不能变窄。<br />
1)    derived　class的构造函数必须在自己的异常规格中声明所有base　class构造函数的异常规格中所声明的异常。<br />
2)    在derived　class的构造函数的异常规格中还可以声明新的异常，即声明在base　class构造函数的异常规格中没有声明的异常。<br />
1.2    原因<br />
当在产生一个derived　class的对象时，会在derived　class的构造函数中调用base　class的构造函数（初始化过程请见第6章），所以在derived　class的构造函数中可能会抛出base　class构造函数的异常规格中声明的异常，因此要在derived　class的异常规格中声明base　class构造函数的异常规格中声明的异常。<br />
＊＊：如果调用的函数的异常规格中声明了异常，那么在调用该函数的时候要捕捉它的异常规格中声明的异常。但在derived　class构造函数中却无法捕捉其base　class构造函数所掷出的异常。<br />
2.    关于非构造函数的异常规则<br />
2.1    某个函数的“异常规格接口“在继承和重载中可以变窄，但决不能变宽<br />
要覆写base　class的函数时，如果被覆写函数（base　class中的函数）的异常规格中声明了异常，那么覆写函数（derived　class中覆写了base　class中的函数的那个函数）的异常规格中可以声明（1）与被覆写函数完全相同的异常；（2）被覆写函数异常规格中的部分异常或其子类异常；（3）不声明异常规格。<br />
2.2    原因<br />
这么做是为了满足“能处理被覆写函数的代码，不用做任何修改就能处理覆写函数的代码”的原则。<br />
如果覆写函数的异常规格中声明了在被覆写函数的异常规格中不存在的异常，那么能处理被覆写函数的代码就不能处理覆写函数，因为没有捕捉覆写函数中不存在于被覆写函数中的异常声明。<br />
import java.sql.SQLException;<br />
class BaseClass{<br />
            public void f(){}<br />
}<br />
class DerivedClass1 extends BaseClass{<br />
            //public void f() throws SQLException {}　（1）<br />
            public void f() {}　//（2）<br />
}<br />
public class Test{<br />
            public static void f(BaseClass bc) { bc.f(); }<br />
            /*　（3）<br />
public static void f(BaseClass bc) {<br />
                try{<br />
                    bc.f();<br />
                }<br />
                catch(SQLException ex){}<br />
}<br />
*/<br />
            public static void main(String[] args){<br />
                BaseClass bc = new BaseClass();<br />
                f(bc);<br />
                DerivedClass1 dc = new DerivedClass1();<br />
                f(bc);<br />
            }<br />
}</p>
<p>如果允许“异常接口“变宽，我们看看上面代码会出现什么结果。首先，我们可以将代码（1）的注释去掉，并注释掉代码（2）。由于BaseClass　class中的被覆写f()函数没有声明异常规格，而代码（1）中覆写f()函数声明了，那么Test　class中的f(BaseClass bc)虽然能处理被覆写f()函数的调用，但不能处理覆写f()函数的调用，因为代码覆写f()函数声明了异常规格，而f(BaseClass bc)没有进行捕捉。那么为了处理覆写f()函数，我们还要编写代码（3）那样的处理函数。<br />
2.3    产生对象的异常规则<br />
在产生一个对象时，捕捉的是产生对象时所调用的构造函数中所声明的异常。<br />
2.4    函数调用时的异常规则<br />
1)    当把一个对象向上转型为它的base　class时，并通过转型后的reference进行函数调用时，我们要捕捉的是其base　class的异常声明。<br />
2)    当用对象的原始类型来调用函数时，只需捕捉所调用的覆写函数的异常<br />
2.5    继承中的异常规则的一个实例<br />
import java.lang.Exception;<br />
class BaseException extends Exception {}<br />
class Derived1Exception extends BaseException {}<br />
class Derived2Exception extends BaseException {}<br />
class Derived11Exception extends Derived1Exception {}<br />
class BaseClass{<br />
    BaseClass() throws Derived1Exception {}<br />
    BaseClass(int i) throws BaseException {}<br />
    BaseClass(int i, int j) {}<br />
    //在覆写f()时不能声明异常规格<br />
    public void f() {}<br />
//在覆写g()时可以不声明异常或声明BaseException异常或声明<br />
//BaseException异常的子类<br />
    public void g() throws BaseException {}<br />
    //在覆写u()时可以不声明异常<br />
    public void u() throws Derived1Exception, Derived2Exception {}<br />
}<br />
class DerivedClass1 extends BaseClass{<br />
    //base　class构造函数中声明了异常的处理方法<br />
    //声明与base　class构造函数中的异常完全相同的异常<br />
    DerivedClass1(int i) throws Derived1Exception {}<br />
    //声明base　class构造函数中的异常的父类异常<br />
    DerivedClass1() throws BaseException {}<br />
    //声明base　class构造函数中的异常和新的异常<br />
    DerivedClass1(String s) throws Derived1Exception,  Derived2Exception{}<br />
    //声明base　class构造函数中的异常父类异常和新的异常<br />
    DerivedClass1(String s, int i) throws BaseException,  Derived2Exception{}<br />
    DerivedClass1(int i, int j) { super(i, j); }<br />
    //注意下面这两句<br />
    DerivedClass1(int i, String s) throws BaseException { super(i); }<br />
    //！DerivedClass1(int i, String s) throws Derived1Exception { super(i);}<br />
    public void f() {}<br />
    //下面覆写g()的几种方式<br />
    //不声明<br />
    //public void g() {}<br />
    //public void g() throws BaseException {} 声明完全相同<br />
    //声明子类异常<br />
public void g() throws Derived1Exception {}<br />
//声明子类异常<br />
    //public void g() throws Derived1Exception, Derived11Exception {}　<br />
    //下面覆写u()的几种方式<br />
    //public void u() {}　不声明<br />
    //public void u() throws Derived11Exception {}　声明部分异常的异常<br />
    //public void u() throws Derived1Exception {}　声明部分异常<br />
    //声明完全相同<br />
//public void u() throws Derived1Exception, Derived2Exception {}　<br />
//声明子类异常<br />
    //public void u() throws Derived1Exception, Derived11Exception {}　<br />
}<br />
public class Test{<br />
    public static void main(String[] args){<br />
        //捕捉的是相应的构造函数的异常<br />
        try{<br />
            BaseClass bc1 = new DerivedClass1();<br />
        }<br />
        catch(BaseException be) {}<br />
        try{<br />
            BaseClass bc2 = new DerivedClass1(&#8220;bc2&#8243;);<br />
        }<br />
        catch(Derived1Exception be1) {}<br />
        catch(Derived2Exception be2) {}<br />
        //通过向上转型来调用函数<br />
        BaseClass bc3 = new DerivedClass1(1, 1);<br />
        /*捕捉的是父类中被覆写的函数的异常，而这里捕捉的是子类中<br />
         * 被覆写的函数的异常，所以编译错误<br />
        try{<br />
            bc3.g();<br />
        }<br />
        catch(Derived1Exception be) {}<br />
        */<br />
        //捕捉了被覆写函数的异常，是正确的<br />
        try{<br />
            bc3.g();<br />
        }<br />
        catch(BaseException be) {}<br />
        //用对象的原始类型来调用函数<br />
        DerivedClass1 dc1 = new DerivedClass1(1, 1);<br />
        //只需捕捉所调用的覆写函数的异常<br />
        try{<br />
            dc1.g();<br />
        }<br />
        catch(Derived1Exception be) {}<br />
    }<br />
}</p>
<p>&#8212;&#8211;</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/75/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java编程思想读书笔记－4</title>
		<link>http://welog.org/blog/69</link>
		<comments>http://welog.org/blog/69#comments</comments>
		<pubDate>Tue, 15 Mar 2005 06:28:32 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/java%e7%bc%96%e7%a8%8b%e6%80%9d%e6%83%b3%e8%af%bb%e4%b9%a6%e7%ac%94%e8%ae%b0%ef%bc%8d4/</guid>
		<description><![CDATA[（第9章-2HashMap的工作原理及其实现）&#160;&#160; 4．&#160;&#160;&#160;&#160;自己实现一个简单的HashMap及其原理 （第9章-2HashMap的工作原理及其实现） 4． 自己实现一个简单的HashMap及其原理 4.1 在put()方法中： 1) 首先通过key得出要插入的key-value　pair的hash　code，并这个hash　code作为索引在数组bucket中找出key所对应的元素。 2) 把要插入的key-value　pair封装成实现了Map.Entry接口的类的一个对象。 3) 在操作1）所找出的数组元素（也是一个LinkedList）中查看是否有与要插入的key-value　pair的key相同的元素，如果有，则对之进行更新；如果无，则把要插入的key-value　pair数组元素中。 4.2 在get()方法中 1) 首先通过key得出要查找的key-value　pair的hash　code，并这个hash　code作为索引在数组bucket中找出key所对应的元素。 2) 把要查找的key-value　pair的key封装成实现了Map.Entry接口的类的一个对象。 3) 在操作1）所找出的数组元素（也是一个LinkedList）中查看是否有与要插入的key-value　pair的key相同的元素，如果有，则返回key所对应的value；如果无，则返回一个null。 4.3 一个实例 import java.util.*; /** * MPair类实现了Map.Entry */ class MPair implements Map.Entry, Comparable{ Object key, value; MPair(Object k, Object v){ key = k; value = v; } public Object getKey() { return key; } &#8230; <a href="http://welog.org/blog/69">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>（第9章-2HashMap的工作原理及其实现）&nbsp;<br />&nbsp;</p>
<p>4．&nbsp;&nbsp;&nbsp;&nbsp;自己实现一个简单的HashMap及其原理<br />
<span id="more-69"></span><br />
（第9章-2HashMap的工作原理及其实现） </p>
<p>4．    自己实现一个简单的HashMap及其原理</p>
<p>4.1    在put()方法中：<br />
1)    首先通过key得出要插入的key-value　pair的hash　code，并这个hash　code作为索引在数组bucket中找出key所对应的元素。<br />
2)    把要插入的key-value　pair封装成实现了Map.Entry接口的类的一个对象。<br />
3)    在操作1）所找出的数组元素（也是一个LinkedList）中查看是否有与要插入的key-value　pair的key相同的元素，如果有，则对之进行更新；如果无，则把要插入的key-value　pair数组元素中。<br />
4.2    在get()方法中<br />
1)    首先通过key得出要查找的key-value　pair的hash　code，并这个hash　code作为索引在数组bucket中找出key所对应的元素。<br />
2)    把要查找的key-value　pair的key封装成实现了Map.Entry接口的类的一个对象。<br />
3)    在操作1）所找出的数组元素（也是一个LinkedList）中查看是否有与要插入的key-value　pair的key相同的元素，如果有，则返回key所对应的value；如果无，则返回一个null。<br />
4.3    一个实例<br />
import java.util.*;<br />
/**<br />
 * MPair类实现了Map.Entry<br />
 */<br />
class MPair<br />
    implements Map.Entry, Comparable{<br />
    Object key, value;<br />
    MPair(Object k, Object v){<br />
        key = k;<br />
        value = v;<br />
    }<br />
    public Object getKey() { return key; }<br />
    public Object getValue() { return value; }<br />
    public Object setValue(Object v){<br />
        Object result = value;<br />
        value = v;<br />
        return result;<br />
}<br />
                /**<br />
                  * 当比较两个MPair对象时，比较的是它们的key值<br />
                  */<br />
    public boolean equals(Object o){<br />
        return key.equals(((MPair)o).key);<br />
    }<br />
    public int compareTo(Object rv){<br />
        return (((Comparable)key).compareTo(((MPair)rv).key));<br />
    }<br />
}<br />
class SimpleHashMap extends AbstractMap{<br />
    private final static int SZ = 997;<br />
    private LinkedList[] bucket = new LinkedList[SZ];<br />
    /**<br />
     * 把key和value封装成Map.Entry的实现类后插入到array中<br />
     */<br />
    public Object put(Object key, Object value){<br />
        Object result = null;<br />
        //通过key得到要插入的key-value　pair的hash　code<br />
        int index = key.hashCode() % SZ;<br />
        if(index  0.5;<br />
            public String toString(){<br />
                if(shadow)<br />
                    return &#8220;Six more weeks of Winter!&#8221;;<br />
                else<br />
                    return &#8220;Early Spring!&#8221;;<br />
            }<br />
}<br />
public class Test{<br />
            public static void main(String[] args){<br />
                HashMap hm = new HashMap();<br />
                for(int i = 1; i  0.5;<br />
            public String toString(){<br />
                if(shadow)<br />
                    return &#8220;Six more weeks of Winter!&#8221;;<br />
                else<br />
                    return &#8220;Early Spring!&#8221;;<br />
            }<br />
}<br />
public class Test{<br />
            public static void main(String[] args){<br />
                HashMap hm = new HashMap();<br />
                for(int i = 1; i </p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/69/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java编程思想读书笔记－3</title>
		<link>http://welog.org/blog/68</link>
		<comments>http://welog.org/blog/68#comments</comments>
		<pubDate>Tue, 15 Mar 2005 06:26:42 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/java%e7%bc%96%e7%a8%8b%e6%80%9d%e6%83%b3%e8%af%bb%e4%b9%a6%e7%ac%94%e8%ae%b0%ef%bc%8d3/</guid>
		<description><![CDATA[（第9章-1容器的使用及其工作原理）&#160;第9章&#160;&#160;&#160;&#160;持有你的对象 （第9章-1容器的使用及其工作原理） 第9章 持有你的对象 一. 容器简介 1. 容器的分类 1.1. Collection：一组各自独立的元素，即其内的每个位置仅持有一个元素。 1) List：以元素安插的次序来放置元素，不会重新排列。 2) Set：不接爱重复元素，它会使用自己内部的一个排列机制 1.2. Map：一群成对的key-value对象，即所持有的是key-value pairs。 Map中不能有重复的key，它拥有自己的内部排列机制。 2. 容器中的元素类型都为Object。从容器取得元素时，必须把它转换成原来的类型。 二. 容器的详细介绍 1． Collection Collection不提供get()方法。如果要遍历Collectin中的元素，就必须用Iterator。 1.1. List 1.1.1 List（interface）：List为Collectin加入了一些函数，使它可以在List内进行安插和移除动作。List会产生ListIterator，通过它可以从两个方向来对List进行走访，也可以在List之内进行元素的安插和移除。 1.1.2 ArrayList：可以快速随机访问；但当元素的安插或移除发生在List中央位置时，效率很差。不宜用ArrayList来进行安插和移除操作。 1.1.3 LinkedList：与ArrayList相反，适合用来进行安插和移除，但随机访问的速度较慢。此外，可以通过LinkedList来实现stack、queue、deque。 1) LinkedList中的addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast()函数未定义于任何一个interface或base　class中，所以只能用于LinkedList中。 1.2. Set 1.2.1 Set（interface）：Set具有和Collection一模一样的interface（区别：List加入了自己的函数），所以Set就是一个Collection，只不过其行为不同罢了。加至Set内的每个元素都必须独一无二，不与其他元素重复；Set不允许持有重复元素，每个元素都必须定义equals()以判断所谓的独一性。 1.2.2 HashSet：一种把查找时间看得很重要的Sets。所有元素都必须定义hashCode()。 1.2.3 TreeSet：底层结构为tree的一种有序的Set。 2． Map 2.1. Map：维护key-value的关联性，使你可以使用key来查找value。 1) KeySet()函数和values()函数 import java.util.*; public class ExplicitStatic{ public &#8230; <a href="http://welog.org/blog/68">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>（第9章-1容器的使用及其工作原理）&nbsp;<br />第9章&nbsp;&nbsp;&nbsp;&nbsp;持有你的对象</p>
<p><span id="more-68"></span><br />
（第9章-1容器的使用及其工作原理）<br />
第9章    持有你的对象</p>
<p>一.    容器简介</p>
<p>1.    容器的分类<br />
1.1.    Collection：一组各自独立的元素，即其内的每个位置仅持有一个元素。<br />
1)    List：以元素安插的次序来放置元素，不会重新排列。<br />
2)    Set：不接爱重复元素，它会使用自己内部的一个排列机制<br />
1.2.    Map：一群成对的key-value对象，即所持有的是key-value pairs。<br />
Map中不能有重复的key，它拥有自己的内部排列机制。<br />
2.    容器中的元素类型都为Object。从容器取得元素时，必须把它转换成原来的类型。</p>
<p>二.    容器的详细介绍</p>
<p>1．    Collection<br />
Collection不提供get()方法。如果要遍历Collectin中的元素，就必须用Iterator。<br />
1.1.    List<br />
1.1.1    List（interface）：List为Collectin加入了一些函数，使它可以在List内进行安插和移除动作。List会产生ListIterator，通过它可以从两个方向来对List进行走访，也可以在List之内进行元素的安插和移除。<br />
1.1.2    ArrayList：可以快速随机访问；但当元素的安插或移除发生在List中央位置时，效率很差。不宜用ArrayList来进行安插和移除操作。<br />
1.1.3    LinkedList：与ArrayList相反，适合用来进行安插和移除，但随机访问的速度较慢。此外，可以通过LinkedList来实现stack、queue、deque。<br />
1)    LinkedList中的addFirst()、addLast()、getFirst()、getLast()、removeFirst()、removeLast()函数未定义于任何一个interface或base　class中，所以只能用于LinkedList中。<br />
1.2.    Set<br />
1.2.1    Set（interface）：Set具有和Collection一模一样的interface（区别：List加入了自己的函数），所以Set就是一个Collection，只不过其行为不同罢了。加至Set内的每个元素都必须独一无二，不与其他元素重复；Set不允许持有重复元素，每个元素都必须定义equals()以判断所谓的独一性。<br />
1.2.2    HashSet：一种把查找时间看得很重要的Sets。所有元素都必须定义hashCode()。<br />
1.2.3    TreeSet：底层结构为tree的一种有序的Set。<br />
2．    Map<br />
2.1.    Map：维护key-value的关联性，使你可以使用key来查找value。<br />
1)    KeySet()函数和values()函数<br />
import java.util.*;</p>
<p>public class ExplicitStatic{<br />
    public static void printKeys(Map m){<br />
        System.out.print(&#8220;Size = &#8221; + m.size());<br />
System.out.println(&#8221; , Keys: &#8221; + m.keySet());<br />
    }<br />
    public static void printValues(Map m){<br />
        System.out.println(&#8220;Values: &#8221; + m.values());<br />
    }<br />
    public static void test(Map m){<br />
        for( int i=1; i</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/68/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Java编程思想读书笔记－2</title>
		<link>http://welog.org/blog/67</link>
		<comments>http://welog.org/blog/67#comments</comments>
		<pubDate>Tue, 15 Mar 2005 06:25:51 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/java%e7%bc%96%e7%a8%8b%e6%80%9d%e6%83%b3%e8%af%bb%e4%b9%a6%e7%ac%94%e8%ae%b0%ef%bc%8d2/</guid>
		<description><![CDATA[[b]第8章&#160;&#160;&#160;&#160;接口与内隐类[/b] 一.&#160;&#160;&#160;&#160;接口 [b]第8章 接口与内隐类[/b] 一. 接口 1． 如果实现接口的class未实现接口中的所有函数，则这个class必须被声明为abstract　class，而接口中未被实现的函数在这个class中为abstract　class。 interface Interface{ public void f(); public void g(); } abstract class First implements Interface{ public void f(){} } class Second extends First{ public void g(){} } public class ExplicitStatic{ public static void main(String[] args){ Interface f = new Second(); f.f(); f.g(); } } 2． 接口中的所有函数自动具有public访问权限，所以实现某个接口时，必须将承袭自该接口的所有函数都定义为public interface MyInterface &#8230; <a href="http://welog.org/blog/67">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>[b]第8章&nbsp;&nbsp;&nbsp;&nbsp;接口与内隐类[/b]</p>
<p>一.&nbsp;&nbsp;&nbsp;&nbsp;接口<br />
<span id="more-67"></span><br />
[b]第8章    接口与内隐类[/b]</p>
<p>一.    接口</p>
<p>1．    如果实现接口的class未实现接口中的所有函数，则这个class必须被声明为abstract　class，而接口中未被实现的函数在这个class中为abstract　class。<br />
interface Interface{<br />
    public void f();<br />
    public void g();<br />
}<br />
abstract class First implements Interface{<br />
    public void f(){}<br />
}<br />
class Second extends First{<br />
    public void g(){}<br />
}<br />
public class ExplicitStatic{<br />
    public static void main(String[] args){<br />
        Interface f = new Second();<br />
        f.f();<br />
        f.g();<br />
    }<br />
}</p>
<p>2．    接口中的所有函数自动具有public访问权限，所以实现某个接口时，必须将承袭自该接口的所有函数都定义为public<br />
interface MyInterface {<br />
    public void f();<br />
    void g();<br />
}<br />
class First implements MyInterface {<br />
    public void f(){}<br />
    //！void g(){}出错，应定义为public<br />
}</p>
<p>3．    接口中的数据成员自动成为static和final<br />
interface MyInterface{<br />
    int i = 5;<br />
    void f();<br />
    void g();<br />
}<br />
class First implements MyInterface {<br />
    public void f(){}<br />
    public void g(){}<br />
}<br />
public class ExplicitStatic{<br />
    public static void main(String[] args){<br />
        MyInterface x = new First();<br />
        // MyInterface的数据成员I为static，可直接调用<br />
        System.out.println(&#8220;MyInterface.i = &#8221; + MyInterface.i + &#8221; , x.i = &#8221; + x.i);<br />
        // MyInterface的数据成员I为final，不能修改<br />
        //x.i++;<br />
        // MyInterface.i++;<br />
    }<br />
}</p>
<p>4．    多重继承<br />
1)    devriced　class可以同时继承多个interface和一个abstract或concrete　base　class。如果同时继承了base　class和interface，那么要先写下具象类的名称，然后才是interfaces的名称。<br />
2)    如果derived　class所继承的具象类具有与interfaces相同的函数，则可在derived　class不实现那个函数。<br />
interface CanFight{<br />
    void fight();<br />
}<br />
interface CanSwim{<br />
    void swim();<br />
}<br />
class ActionCharacter{<br />
    public void fight(){}<br />
}<br />
class Hero extends ActionCharacter<br />
    implements CanFight, CanSwim{<br />
    public void swim(){};<br />
}<br />
public class ExplicitStatic{<br />
    static void f(CanFight x) { x.fight(); }<br />
    static void s(CanSwim x) { x.swim(); }<br />
    static void a(ActionCharacter x) { x.fight(); }<br />
    static void h(Hero x){<br />
        x.fight();  x.swim();<br />
    }<br />
    public static void main(String[] args){<br />
        Hero h = new Hero();<br />
        f(h); s(h); a(h); h(h);<br />
    }<br />
}</p>
<p>因为在ActionCharacter　class中有与接口CanFight完全相同的函数fight()，所以在Hero　class可以不实现fight()方法。当要调用x.fight()时，会调用ActionCharacter　class中的fight()函数。<br />
3)    接口的合并时的名称冲突问题<br />
interface I1 { void f(); }<br />
interface I2 { int f(int i); }<br />
interface I3 { int f(); }<br />
class C { public int f() { return 1; } }</p>
<p>class C2 implements I1, I2{<br />
    public void f() {}<br />
    public int f(int i) { return 1; }<br />
}<br />
class C3 extends C implements I2{<br />
    public int f(int i) { return 1; }<br />
}<br />
class C4 extends C implements I3{<br />
    public int f() { return 1; }<br />
}<br />
//class C5 extends C implements I1{}　（a）<br />
//class C6 extends C implements I1{ public void f(){} }　（b）<br />
interface I4 extends I1, I3{}　//（c）<br />
class C7 implements I4{<br />
    public void f() {}<br />
    public int f() { return 1; }<br />
}</p>
<p>（a）处代码会产生以下错误： method f() in class C cannot implement method f() in interface I1 with different return type, was void。<br />
（b）处代码也是错误的： method f() in class C6 cannot override method f() in class C with different return type, was int。由（b）处代码也可看出，虽然你试图实现接口I1中的函数，但由于extends C在前，所以编译器会把C6中的函数看成是覆写class　C中的函数，而不是象你想象中的作为实现接口中的函数的函数。<br />
（c）处代码在原书中（P253）说会出错，但我在测试时并没发生错误。但当你试图通过C7来实现接口I4时，是无论如何也不可能编译通过的。<br />
4)    Java中唯一可以使用多重继承的地方<br />
Java是不允许通过关键字extends来实现多重继承的，但除了通过多重继承来扩充接口除外。<br />
interface I1{<br />
    void f1();<br />
}<br />
interface I2{<br />
    void f2();<br />
}<br />
interface Ie1 extends I2{<br />
    void fe1();<br />
}<br />
class Ce1 implements Ie1{<br />
    public void f2() {}<br />
    public void fe1() {}<br />
}<br />
interface Ie2 extends Ie1, I1{<br />
    void fe2();<br />
}<br />
class Ce2 implements Ie2{<br />
    public void fe2() {}<br />
    public void f2() {}<br />
    public void fe1() {}<br />
    public void f1() {}<br />
}</p>
<p>接口Ie2继承了两个接口。<br />
5．    嵌套的interfaces<br />
嵌套的interfaces可以在定义该内部接口的外部类（接口）之外被使用（但内隐类不行）。<br />
1)    当接口嵌套于class中<br />
a)    不论接口为public、friendly或private，都可被实现为public、friendly、private三种嵌套类。<br />
b)    被声明为private的接口不能在class外被使用。<br />
class A{<br />
    private interface B{<br />
        void f();<br />
    }<br />
    public class BImp implements B{<br />
        public void f() {}<br />
    }<br />
    private class BImp2 implements B{<br />
        public void f() {}<br />
    }<br />
    public B getB() { return new BImp(); }<br />
    private B dRef;<br />
    public void recivedD(B d){<br />
        dRef = d;<br />
        dRef.f();;<br />
    }<br />
}<br />
public class ExplicitStatic{<br />
    public static void main(String[] args){<br />
        A a = new A(); //（a）<br />
        //A.B ab = a.getB();　（b）<br />
        //A.BImp = a.getB();　（c）<br />
        a.recivedD(a.getB());<br />
    }<br />
}</p>
<p>虽然A　class含有接口，但它仍可被实例化，如（a）。<br />
由于接口B为private，所以在（b）处调用接口B时会出错。但当把接口B声明为public时，（b）将通过编译。但（c）处依然会出错，因为内隐类的作用域为定义该内隐类的外部类内（见内隐类）。<br />
2)    当接口嵌套于接口中<br />
1)    嵌套于接口中的接口自动为public，且只能为public。<br />
2)    当实现某个接口时，无需实现其中嵌套的接口。<br />
3)    Private接口无法在其所定义的class之外被实现。</p>
<p>二.    Inner classes（内隐类）</p>
<p>1．    内隐类的基本用法<br />
1)    如果要在外围class的non-static函数之外产生一个inner class对象，得以OuterClassName.InnerClassName的形式指定该对象的型别。而在non-static函数内则不用。<br />
public class ExplicitStatic{<br />
    class Contents{<br />
        private int i = 11;<br />
        public int value() { return i; }<br />
    }<br />
    class Destination{<br />
        private String label;<br />
        Destination(String wh&#101;reTo){<br />
            label = wh&#101;reTo;<br />
        }<br />
        String readLabel() { return label; }<br />
    }<br />
    public Destination to(String s){<br />
    //在outer class的non-static函数中可直接产生inner class对象<br />
        return new Destination(s); //（1）<br />
    }<br />
    public Contents cont(){<br />
        return new Contents(); //（1）<br />
    }<br />
    public void ship(String dest){<br />
//在outer class的non-static函数中可直接通过InnerClassName<br />
//来指定对象型别<br />
        Contents c = cont();<br />
        Destination d = to(dest);<br />
        System.out.println(d.readLabel());<br />
    }<br />
    public static void main(String[] args){<br />
        ExplicitStatic p = new ExplicitStatic();<br />
        p.ship(&#8220;Tanzania&#8221;);<br />
        ExplicitStatic q = new ExplicitStatic();<br />
   //在outer class的非non-static函数内产生inner class对象<br />
        ExplicitStatic.Contents c = q.cont();<br />
        ExplicitStatic.Destination d = q.to(&#8220;Borneo&#8221;);<br />
  //不能在static函数直接生成inner class对象<br />
        // new Contents();<br />
    }<br />
}</p>
<p>2)    对于non-static　inner　class，在外围class的non-static函数可以通过new产生一个inner class对象，如上面的（1）处。但要在非non-static函数产生一个inner class对象，则一定要关联到其enclosing　class的某个对象。<br />
3)    inner class的向上转型<br />
当把一个inner class对象向上转型成为interface时，我们得到的只是一个reference。<br />
interface Destination{<br />
    String readLabel();<br />
}<br />
interface Contents{<br />
    int value();<br />
}<br />
class Parcel3{<br />
    private class PContents implements Contents{<br />
        private int i = 11;<br />
        public int value() { return i; }<br />
    }<br />
    protected class PDestination implements Destination{<br />
        private String label;<br />
        PDestination(String wh&#101;reTo){<br />
            label = wh&#101;reTo;<br />
        }<br />
        public String readLabel() { return label; }<br />
    }<br />
    public Destination to(String s){<br />
        return new PDestination(s);<br />
    }<br />
    public Contents cont(){<br />
        return new PContents();<br />
    }<br />
}<br />
public class ExplicitStatic{<br />
    public static void main(String[] args){<br />
        Parcel3 p = new Parcel3();<br />
        //把inner class对象向上转型<br />
        Contents c = p.cont();<br />
        Destination d = p.to(&#8220;Borneo&#8221;);<br />
    }<br />
}</p>
<p>虽然我们不能在ExplicitStatic class无法调用Pcontents class，但我们把一个Pcontents　class对象向上转型为Contents，就可对之进行调用。<br />
4)    inner　class的作用域为定义该inner　class的scope内。但inner　class可在它的作用域之外被继承（见4）。<br />
interface Contents{<br />
    int value();<br />
}<br />
class Parcel3{<br />
    //PContents1　class的作用域为Parcel3　class内<br />
    private class PContents1 implements Contents{<br />
        private int i = 11;<br />
        public int value() { return i; }<br />
    }<br />
    public Contents cont1(){<br />
        return new PContents1();<br />
    }<br />
    public Contents cont2(){<br />
        //PContents2　class的作用域为函数cont2内<br />
        class PContents2 implements Contents{<br />
            private int i = 11;<br />
            public int value() { return i; }<br />
        }<br />
        return new PContents2();<br />
    }<br />
    //不能在函数cont2外使用PContents2　class<br />
    /*<br />
    public Contents cont22(){<br />
        return new PContents2();<br />
    }<br />
    */<br />
    public Contents cont3(boolean b){<br />
        if(b){<br />
            //PContents3　class的作用域为当前if内<br />
            class PContents3 implements Contents{<br />
                private int i = 11;<br />
                public int value() { return i; }<br />
            }<br />
            return new PContents3();<br />
        }<br />
        //不能在if外使用PContents3　class<br />
        //return new PContents3();<br />
        return null;<br />
    }<br />
}<br />
public class ExplicitStatic{<br />
    public static void main(String[] args){<br />
        Parcel3 p = new Parcel3();<br />
        Contents c1 = p.cont1();<br />
        Contents c2 = p.cont2();<br />
        Contents c3 = p.cont3(true);<br />
    }<br />
}</p>
<p>2．    内隐类与外围enclosing  class的连接关系<br />
2.1　non-static　inner　class<br />
1)    inner　class可以访问enclosing　class的所有成员（包括private成员），就像inner　class自己拥有这些成员一样。即inner　class天生具有对enclosing　class的所有成员的访问权力。<br />
2)    Inner　class对象被产生时，一定要关联到其enclosing　class的某个对象（这个enclosing　class对象就是Inner　class对象的制造者）。建构inner　class对象的同时，得有其enclosing　class对象的reference才行。<br />
原因：因为inner　class可以访问enclosing　class的所有成员，那么当产生一个inner　class时，编译器会自动为inner　class对象添加一个指向enclosing　class对象的reference（这个reference是隐藏的）。所以Inner　class被产生时，一定要关联到其enclosing　class的某个对象。<br />
3)    同一个enclosing　class对象产生出来的inner　class对象访问的是同一个enclosing　class对象中的成员。<br />
interface Destination{<br />
    String readLabel();<br />
}<br />
interface Contents{<br />
    int value();<br />
}<br />
class Parcel3{<br />
    int i1 = 10;<br />
    private String s1 = &#8220;Parcel3_&#8221;;<br />
    Parcel3(String s){<br />
        s1 += s;<br />
    }<br />
    private class PContents implements Contents{<br />
        //可调用enclosing　class的成员　（1）<br />
        private int i2 = i1;<br />
        private String s2 = s1;<br />
        PContents(int num){<br />
         System.out.println(&#8220;&#8221; + num + &#8220;： i2 = &#8221; + i2 + &#8220;，s2 = &#8221; + s2);<br />
        }<br />
        public int value() { return 1; }<br />
    }<br />
    public Contents cont(int i){<br />
        return new PContents(i);<br />
    }<br />
}<br />
public class ExplicitStatic{<br />
    public static void main(String[] args){<br />
        Parcel3 p1 = new Parcel3(&#8220;1&#8243;);<br />
        Contents c1 = p1.cont(1);<br />
        Contents c2 = p1.cont(2);<br />
        Parcel3 p2 = new Parcel3(&#8220;2&#8243;);<br />
        c2 = p2.cont(3);<br />
        c2 = p1.cont(4);<br />
    }<br />
}</p>
<p>结果为：<br />
1： i2 = 10，s2 = Parcel3_1<br />
2： i2 = 10，s2 = Parcel3_1<br />
3： i2 = 10，s2 = Parcel3_2<br />
4： i2 = 10，s2 = Parcel3_1<br />
在（1）在inner　class调用了enclosing　class的成员。结果表明，同一个enclosing　class对象p1产生的inner　class对象调用的是同一个enclosing　class对象中的成员，如结果中的1、2、4。<br />
        2.2　 Static inner classes（静态内隐类）<br />
1)    产生Static inner classes对象时，不需要同时存在一个enclosing　class对象<br />
2)    只能在Static inner classes对象中访问enclosing　class中的静态成员。<br />
interface Contents{<br />
    int value();<br />
}<br />
class Parcel1{<br />
private static String s1 = &#8220;Parcel3_&#8221;;<br />
private String s11 = “Parcel3_”;<br />
    Parcel1(String s){<br />
        s1 += s;<br />
    }<br />
protected static class PContents implements Contents{<br />
    //只能访问enclosing class中的s1<br />
        String s2 = s1;<br />
        //s11不是static成员，不能访问<br />
        //String 22 = s11;<br />
        PContents(int num){<br />
            System.out.println(&#8220;&#8221; + num + &#8220;：s2 = &#8221; + s2);<br />
        }<br />
        public int value() { return 1; }<br />
    }<br />
    public static  Contents cont(int i){<br />
        return new PContents(i);<br />
    }<br />
}<br />
public class ExplicitStatic{<br />
    public static void main(String[] args){<br />
        Parcel1 p1 = new Parcel1(&#8220;1&#8243;);<br />
        Contents c1 = p1.cont(1);<br />
        c1 = Parcel1.cont(2); 　//（1）<br />
        Parcel1 p2 = new Parcel1(&#8220;2&#8243;);<br />
        c1 = p2.cont(3);<br />
        c1 = Parcel1.cont(4);　//（1）<br />
    }<br />
}</p>
<p>因为内隐类Pcontents　class是静态的，所以在（1）处不通过enclosing　class对象而是通过静态函数来直接产生其对象。<br />
2.3    无论inner　class被嵌套置放的层次有多深，且所有outer　class的成员都可<br />
被它访问。<br />
class MNA{<br />
    private void f() {}<br />
    class A{<br />
        private void g() {}<br />
        class B{<br />
            void h(){<br />
                g();<br />
                f();<br />
            }<br />
        }<br />
    }<br />
}</p>
<p>3．    如何产生inner　class对象的总结<br />
3.1　non-static内隐类<br />
1)    在enclosing　class的non-static函数中可以直接通过new来产生<br />
2)    在enclosing　class的static函数或其它的class中，必须同时存在一个enclosing　class对象（原因在上面2.1已说明）。<br />
interface Contents{<br />
    int value();<br />
}<br />
class Parcel1{<br />
    protected class PContents implements Contents{<br />
        public int value() { return 1; }<br />
    }<br />
    public Contents cont(){<br />
      //在non-static函数中直接通过new来产生PContents class对象<br />
        return new PContents();<br />
    }<br />
    public static void test(String[] args){<br />
        Parcel1 p1 = new Parcel1();<br />
        //在static函数中通过外部类Parcel1对象来产生<br />
        Contents c1 = p1.cont();  //调用函数<br />
        c1 = p1.new PContents();　//通过new<br />
    }<br />
}<br />
public class ExplicitStatic{<br />
    public static void main(String[] args){<br />
        //通过外部类Parcel1对象来产生<br />
        Parcel1 p1 = new Parcel1();<br />
        Contents c1 = p1.cont();  //调用函数<br />
        c1 = p1.new PContents();  //通过new<br />
    }<br />
}</p>
<p>3.2　static内隐类<br />
1)    除了可用产生non-static内隐类对象的方法来产生之外，也可以不通过已存在一个enclosing　class对象来产生。<br />
interface Contents{<br />
    int value();<br />
}<br />
class Parcel1{<br />
    protected static class PContents implements Contents{<br />
        public int value() { return 1; }<br />
    }<br />
    public Contents cont(){<br />
      //在non-static函数中直接通过new来产生PContents class对象<br />
        return new PContents();<br />
    }<br />
    public static Contents cont1(){<br />
        //在static函数中直接通过new来产生PContents class对象<br />
        return new PContents(); //（1）<br />
    }<br />
    public static void test(String[] args){<br />
        Parcel1 p1 = new Parcel1();<br />
        //在static函数中通过外部类Parcel1对象来产生<br />
        Contents c1 = p1.cont();  //调用函数<br />
        c1 = p1.new PContents();  //通过new<br />
        //在static函数中直接通过new来产生PContents class对象<br />
        c1 = new PContents();  //（1）<br />
    }<br />
}<br />
public class ExplicitStatic{<br />
    public static void main(String[] args){<br />
        //通过外部类Parcel1对象来产生<br />
        Parcel1 p1 = new Parcel1();<br />
        Contents c1 = p1.cont();  //调用函数<br />
        c1 = p1.new PContents();  //通过new<br />
        //直接产生<br />
        c1 = Parcel1.cont1();  //（2）<br />
    }<br />
}</p>
<p>上面的（1）和9（2）中的代码只有在Pcontents　class为static时才能通过。（1）不能通过的原因见2.1。<br />
4．    inner　class的继承<br />
1)    inner　class可被继承。inner　class的drived　class的drfault构造函数必须传入一个reference指向outer　object，并在构造函数中调用outer　class的构造函数。<br />
class WithInner{<br />
            class Inner{}<br />
}<br />
class InheritInner extends WithInner.Inner<br />
{<br />
            //InheritInner(){}  编译错误<br />
            InheritInner(WithInner wi) { wi.super(); }<br />
}<br />
public class ExplicitStatic{<br />
            public static void main(String[] args){<br />
                WithInner wi = new WithInner();<br />
                InheritInner ii = new InheritInner(wi);<br />
            }<br />
}</p>
<p>2)    覆写inner　class不具备多态特性。<br />
class Egg{<br />
    class Yolk{<br />
        public Yolk(){<br />
            System.out.println(&#8220;Egg.Yolk()&#8221;);<br />
        }<br />
    }<br />
    private Yolk y;<br />
    public Egg(){<br />
        System.out.println(&#8220;New Egg()&#8221;);<br />
        y = new Yolk(); //（1）<br />
    }<br />
}<br />
class BigEgg extends Egg{<br />
    //（2）尝试覆写inner　class<br />
    class Yolk{<br />
        public Yolk(){<br />
            System.out.println(&#8220;BigEgg.Yolk()&#8221;);<br />
        }<br />
    }<br />
}<br />
public class ExplicitStatic{<br />
    public static void main(String[] args){<br />
        new BigEgg(); //（3）<br />
    }<br />
}</p>
<p>结果为：<br />
    New Egg()<br />
Egg.Yolk()<br />
在（2）中我们尝试覆写inner　class。当通过（3）产生一个BigEgg时，会调用Egg的构造函数。在Egg的构造函数的（1）处产生的是Egg.Yolk　class对象，而不是子类BigEgg.Yolk　class对象。<br />
＊＊：如上所示，上述两个inner　class是完全独立的个体，各有其专属的命名空间。<br />
&#8212;&#8211;</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/67/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Java编程思想读书笔记－1</title>
		<link>http://welog.org/blog/66</link>
		<comments>http://welog.org/blog/66#comments</comments>
		<pubDate>Tue, 15 Mar 2005 06:23:11 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/java%e7%bc%96%e7%a8%8b%e6%80%9d%e6%83%b3%e8%af%bb%e4%b9%a6%e7%ac%94%e8%ae%b0%ef%bc%8d1/</guid>
		<description><![CDATA[第2章&#160;&#160;&#160;&#160;万事万物皆对象 一．所有对象都必须由你建立 第2章 万事万物皆对象 一．所有对象都必须由你建立 1． 存储在哪里 1. 寄存器：我们在程序中无法控制 2. stack：存放基本类型的数据和对象的reference，但对象本身不存放在stack中，而是存放在Heap中 3. Heap：存放用new产生的数据 4. Static storage：存放在对象中用static定义的静态成员 5. Constant storage：存放常量 6. NON-RAM：硬盘等永久存储空间 2． 特例：基本型别 基本类型数据存放在Stack中，存放的是数据。而产生对象时，只把对象的reference存放在stack中，用于指向某个对象，对象本身存放在Heap中。 3． Java中的数组 当你产生某个存储对象的数组时，真正产生的其实是存储reference的数组。引数组建立后，其中的每一个reference都会被自动设为null，表示“不指向任何对象”。 二．建立新的数据型别：Class 1． 数据成员和函数 1.1 基本成员的缺省值 1） 当class的某个成员属于基本型别时，即使你没有为它提供初值，Java仍保证它有一个缺省值。 2） 只有当变量身份是“class内的成员时，Java才保证为该变量提供初值。 三．函数（Mehtods），引数（arguments），返回值（return values） 1． 引数列 当引数传递的是对象时，传递的是对象的reference。 四．注解用内嵌式文档 Java提供两种注解风格：/*XXXX*/、//XXXX 第3章 控制程序流程 一．使用Java运算符 1.关系运算符 1.） 当对两个对象运用关系运算符进行比较时，比较的是object reference，如： Integer n1 = new Integer(3); &#8230; <a href="http://welog.org/blog/66">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>第2章&nbsp;&nbsp;&nbsp;&nbsp;万事万物皆对象</p>
<p>一．所有对象都必须由你建立<br />
<span id="more-66"></span><br />
第2章    万事万物皆对象</p>
<p>一．所有对象都必须由你建立<br />
1．    存储在哪里<br />
1.    寄存器：我们在程序中无法控制<br />
2.    stack：存放基本类型的数据和对象的reference，但对象本身不存放在stack中，而是存放在Heap中<br />
3.    Heap：存放用new产生的数据<br />
4.    Static storage：存放在对象中用static定义的静态成员<br />
5.    Constant storage：存放常量<br />
6.    NON-RAM：硬盘等永久存储空间<br />
2．    特例：基本型别<br />
基本类型数据存放在Stack中，存放的是数据。而产生对象时，只把对象的reference存放在stack中，用于指向某个对象，对象本身存放在Heap中。<br />
3．    Java中的数组<br />
当你产生某个存储对象的数组时，真正产生的其实是存储reference的数组。引数组建立后，其中的每一个reference都会被自动设为null，表示“不指向任何对象”。<br />
二．建立新的数据型别：Class<br />
1．    数据成员和函数<br />
1.1    基本成员的缺省值<br />
1）    当class的某个成员属于基本型别时，即使你没有为它提供初值，Java仍保证它有一个缺省值。<br />
2）    只有当变量身份是“class内的成员时，Java才保证为该变量提供初值。<br />
三．函数（Mehtods），引数（arguments），返回值（return values）<br />
1．    引数列<br />
当引数传递的是对象时，传递的是对象的reference。<br />
四．注解用内嵌式文档<br />
Java提供两种注解风格：/*XXXX*/、//XXXX</p>
<p>第3章    控制程序流程</p>
<p>一．使用Java运算符<br />
1.关系运算符<br />
1.） 当对两个对象运用关系运算符进行比较时，比较的是object reference，如：<br />
Integer n1 = new Integer(3);<br />
Integer n2 = new Integer(3);<br />
System.out.println(n1==n2);</p>
<p>结果为false，因为两个object reference（n1和n2）值是不同的<br />
2） quals()的缺省行为也是拿referenct来比较。不过Java中的class覆写了equals方法，如：<br />
Integer n1 = new Integer(3);<br />
Integer n2 = new Integer(3);<br />
System.out.println(n1.quals(n2));//值为true</p>
<p>2．    逻辑运算符<br />
1）    只能将an&#100;、or、not施用于boolean值身上。如果逻辑运算符两边的值存在non-boolean值，将会出错，如：<br />
int test1 = 1;<br />
System.out.println((test &amp;&amp; 1</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/66/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>构造函数的继承问题</title>
		<link>http://welog.org/blog/64</link>
		<comments>http://welog.org/blog/64#comments</comments>
		<pubDate>Tue, 15 Mar 2005 06:20:46 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/%e6%9e%84%e9%80%a0%e5%87%bd%e6%95%b0%e7%9a%84%e7%bb%a7%e6%89%bf%e9%97%ae%e9%a2%98/</guid>
		<description><![CDATA[&#160;构造函数的继承问题(静水流深第一版） &#160;&#160;&#160;&#160;这是我的读书笔记，希望能够对大家学习java有所帮助。 构造函数的继承问题(静水流深第一版） 这是我的读书笔记，希望能够对大家学习java有所帮助。 所有代码都经过测试，测试环境： java version &#8220;1.4.0-rc&#8221; Java(TM) 2 Runtime Environment, Stan&#100;ard Edition (build 1.4.0-rc-b91) Java HotSpot(TM) Client VM (build 1.4.0-rc-b91, mixed mode) 如大家发现任何错误，或有任何意见请不吝赐教。 缺省构造函数的问题：base类是父类，derived类是子类，首先要 说明的是由于先有父类后有子类，所以生成子类之前要首先有父类。 class是由class的构造函数constructor产生的，每一个class都有 构造函数，如果你在编写自己的class时没有编写任何构造函数，那么 编译器为你自动产生一个缺省default构造函数。这个default构造函数 实质是空的，其中不包含任何代码。但是一牵扯到继承，它的问题就出现 了。 如果父类base class只有缺省构造函数，也就是编译器自动为你产生的。 而子类中也只有缺省构造函数，那么不会产生任何问题，因为当你试图产生 一个子类的实例时，首先要执行子类的构造函数，但是由于子类继承父类， 所以子类的缺省构造函数自动调用父类的缺省构造函数。先产生父类的实例， 然后再产生子类的实例。如下： class base{ } class derived extends base{ public static void main(String[] args){ derived d=new derived(); } } &#8230; <a href="http://welog.org/blog/64">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>&nbsp;<br />构造函数的继承问题(静水流深第一版）</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;这是我的读书笔记，希望能够对大家学习java有所帮助。<br />
<span id="more-64"></span><br />
构造函数的继承问题(静水流深第一版）</p>
<p>    这是我的读书笔记，希望能够对大家学习java有所帮助。<br />
所有代码都经过测试，测试环境：<br />
java version &#8220;1.4.0-rc&#8221;<br />
Java(TM) 2 Runtime Environment, Stan&#100;ard Edition (build 1.4.0-rc-b91)<br />
Java HotSpot(TM) Client VM (build 1.4.0-rc-b91, mixed mode)<br />
    如大家发现任何错误，或有任何意见请不吝赐教。</p>
<p>    缺省构造函数的问题：base类是父类，derived类是子类，首先要<br />
说明的是由于先有父类后有子类，所以生成子类之前要首先有父类。<br />
class是由class的构造函数constructor产生的，每一个class都有<br />
构造函数，如果你在编写自己的class时没有编写任何构造函数，那么<br />
编译器为你自动产生一个缺省default构造函数。这个default构造函数<br />
实质是空的，其中不包含任何代码。但是一牵扯到继承，它的问题就出现<br />
了。</p>
<p>    如果父类base class只有缺省构造函数，也就是编译器自动为你产生的。<br />
而子类中也只有缺省构造函数，那么不会产生任何问题，因为当你试图产生<br />
一个子类的实例时，首先要执行子类的构造函数，但是由于子类继承父类，<br />
所以子类的缺省构造函数自动调用父类的缺省构造函数。先产生父类的实例，<br />
然后再产生子类的实例。如下：</p>
<p>class base{<br />
}<br />
class derived extends base{<br />
  public static void main(String[] args){<br />
    derived d=new derived();<br />
  }<br />
}</p>
<p>下面我自己显式地加上了缺省构造函数：<br />
class base{<br />
  base(){<br />
    System.out.println(&#8220;base constructor&#8221;);<br />
  }<br />
}<br />
class derived extends base{<br />
  derived(){<br />
    System.out.println(&#8220;derived constructor&#8221;);<br />
  }<br />
  public static void main(String[] args){<br />
    derived d=new derived();<br />
  }<br />
}</p>
<p>执行结果如下：说明了先产生base class然后是derived class。<br />
base constructor<br />
derived constructor</p>
<p>我要说明的问题出在如果base class有多个constructor<br />
而derived class也有多个constructor,这时子类中的构造函数缺省<br />
调用那个父类的构造函数呢？答案是调用父类的缺省构造函数。<br />
但是不是编译器自动为你生成的那个缺省构造函数而是你自己显式地<br />
写出来的缺省构造函数。</p>
<p>class base{<br />
  base(){<br />
    System.out.println(&#8220;base constructor&#8221;);<br />
  }<br />
  base(int i){<br />
    System.out.println(&#8220;base constructor int i&#8221;);<br />
  }<br />
}<br />
class derived extends base{<br />
  derived(){<br />
    System.out.println(&#8220;derived constructor&#8221;);<br />
  }<br />
  derived(int i){<br />
    System.out.println(&#8220;derived constructor int i&#8221;);<br />
  }<br />
  public static void main(String[] args){<br />
    derived d=new derived();<br />
    derived t=new derived(9);<br />
  }<br />
}</p>
<p>D:\java\thinking\think6&gt;java derived<br />
base constructor<br />
derived constructor<br />
base constructor<br />
derived constructor int i</p>
<p>如果将base 类的构造函数注释掉，则出错。</p>
<p>class base{<br />
//  base(){<br />
//    System.out.println(&#8220;base constructor&#8221;);<br />
//  }<br />
  base(int i){<br />
    System.out.println(&#8220;base constructor int i&#8221;);<br />
  }<br />
}<br />
class derived extends base{<br />
  derived(){<br />
    System.out.println(&#8220;derived constructor&#8221;);<br />
  }<br />
  derived(int i){<br />
    System.out.println(&#8220;derived constructor int i&#8221;);<br />
  }<br />
  public static void main(String[] args){<br />
    derived d=new derived();<br />
    derived t=new derived(9);<br />
  }<br />
}</p>
<p>D:\java\thinking\think6&gt;javac derived.java<br />
derived.java:10: cannot resolve symbol<br />
symbol  : constructor base  ()<br />
location: class base<br />
  derived(){<br />
           ^<br />
derived.java:13: cannot resolve symbol<br />
symbol  : constructor base  ()<br />
location: class base<br />
  derived(int i){<br />
                ^<br />
2 errors</p>
<p>说明子类中的构造函数找不到显式写出的父类中的缺省<br />
构造函数，所以出错。</p>
<p>那么如果你不想子类的构造函数调用你显式写出的父类中的缺省<br />
构造函数怎么办呢？<br />
如下例：</p>
<p>class base{<br />
//  base(){<br />
//    System.out.println(&#8220;base constructor&#8221;);<br />
//  }<br />
  base(int i){<br />
    System.out.println(&#8220;base constructor int i&#8221;);<br />
  }<br />
}<br />
class derived extends base{<br />
  derived(){<br />
    super(8);<br />
    System.out.println(&#8220;derived constructor&#8221;);<br />
  }<br />
  derived(int i){<br />
    super(i);<br />
    System.out.println(&#8220;derived constructor int i&#8221;);<br />
  }<br />
  public static void main(String[] args){<br />
    derived d=new derived();<br />
    derived t=new derived(9);<br />
  }<br />
}</p>
<p>D:\java\thinking\think6&gt;java derived<br />
base constructor int i<br />
derived constructor<br />
base constructor int i<br />
derived constructor int i</p>
<p>super(i)表示父类的构造函数base(i)请大家注意<br />
一个是super(i)一个是super(8)。<br />
大家想想是为什么？？</p>
<p>结论：子类如果有多个构造函数的时候，父类要么没有构造函数，<br />
      让编译器自动产生，那么在执行子类构造函数之前先执行编<br />
      译器自动产生的父类的缺省构造函数；要么至少要有一个显<br />
      式的缺省构造函数可以让子类的构造函数调用。<br />
&#8212;&#8211;</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/64/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>新一代Java技术即将出现</title>
		<link>http://welog.org/blog/42</link>
		<comments>http://welog.org/blog/42#comments</comments>
		<pubDate>Sat, 12 Mar 2005 08:23:18 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/%e6%96%b0%e4%b8%80%e4%bb%a3java%e6%8a%80%e6%9c%af%e5%8d%b3%e5%b0%86%e5%87%ba%e7%8e%b0/</guid>
		<description><![CDATA[【日经BP社报道】&#160;Java技术自问世时光已经过去了9个年头。作为一名一直关注其成长的记者，曾经一段时间有过这样的想法：“Java技术已经成熟，是不是发展速度该放慢一些了呢”。然而，这种想法错了。近来Java技术的进化相当显著。Java技术正在迎来“又一次革命”的风暴。这就是本文的结论。&#160;&#160; 　　“又一次”指的是什么？“革命”指的又是什么？光看结论的话肯定是一头雾水。其实，笔者要讲的并不是变化这样一个事实，而是“促进变化的原动力”。是什么让Java技术发生变化？让我们从这一角度出发，先看一下Java的变化历程。&#160;&#160; Java正处于转变期&#160;&#160; 【日经BP社报道】 Java技术自问世时光已经过去了9个年头。作为一名一直关注其成长的记者，曾经一段时间有过这样的想法：“Java技术已经成熟，是不是发展速度该放慢一些了呢”。然而，这种想法错了。近来Java技术的进化相当显著。Java技术正在迎来“又一次革命”的风暴。这就是本文的结论。 　　“又一次”指的是什么？“革命”指的又是什么？光看结论的话肯定是一头雾水。其实，笔者要讲的并不是变化这样一个事实，而是“促进变化的原动力”。是什么让Java技术发生变化？让我们从这一角度出发，先看一下Java的变化历程。 Java正处于转变期 　　回顾Java技术的发展历程，人们一定会感慨：2004年到2005年发生的变化如此之大，可以说“现在”正是Java技术的转换期。Java技术由编程语言（Java语言）、运行环境（JVM：Java虚拟机）、框架（Java API群）组成，目前在每一个层面上都发生着巨大的变化。 （1）编程语言的变化 　　Java语言标准出现明显变化。在2004年9月发布的正式版本J2SE5.0（J2SE:Java2 Stan&#100;ard, Stan&#100;ard Edition，Java技术的核心运行环境）中，对Java语言标准中的Generics与元数据进行了大幅扩展。出现了被认为是“自Java问世以来的最大一次语言标准变化”（美国Sun Microsystems）。这次语言标准的变化给许多Java API带来了影响。许多企业API的新版本都引入了基于元数据的注解（程序中记录的附加信息），以较短的编码记述更多的信息。 （2）Java运行环境的变化 　　在J2SE5.0中，大幅度强化了JVM的管理功能与实用性，换句话说就是具备了Java执行OS（操作系统）的特征。例如，原来在J2EE（Java2 Platform, Enterprise Edition，构筑企业系统的Java技术）领域，标准配备有作为管理功能的应用软件管理框架JMX。不仅如此，还配备有JVM自身监控功能（（JSR 174: Monitoring an&#100; Management Specification for the Java Virtual Machine）。在标准功能架构中可以实时监视JVM运行时的状态，也就是内存使用量、线程状态等。 　　J2SE5.0中新追加的功能中包括并行处理实用程序（JSR 166），其基础是纽约州立大学Doug Lea提供的程序库。也就是说，标准规格中采用了来自民间的程序库。 （3）框架的变化 　　服务器端的Java框架也发生了巨大变化。企业级Java技术&#8211;J2EE的“使用方法”说明文件“J2EE Blueprint”中，提出了将应用软件分为Web层、EJB层（Enterprise JavaBeans，将包括事务处理在内的业务进程模块化的框架）来构筑的思路。这两种层次都迎来了架构更替时期。Web层的新框架为JSF（JavaServer Faces，将模块组合起来构筑Web应用程序的框架），EJB层为标准方案中刚刚公布的下一代EJB规格“EJB3.0”。 　　值得注意的是，促成框架发生变化的正是来自民间的源码开放软件。 　　对JSF产生影响的是作为源码开放的Web层框架得到普及的Apache Struts。JSF是对Struts的思路进行改进的产物，JSF的Spec Lead（规格制定领袖）之一Craig R. McClanahan就是Struts的作者。 　　对EJB3.0造成影响的也是民间源码开放软件。EJB3.0引入了DI（Dependency Injection，依赖注入）容器类（Container）与POJO（Plain Old Java Object）持久类这些新功能，大大减轻了编程的复杂性。这些概念因PicoContainer、Spring等源码开放软件的导入而引人注目。 　　其背景在于用户对“目前的EJB过于复杂”的批评。原本由EJB反对派提出的设计思想与源码开放软件，却变成了EJB3.0的中心概念，显出了巨大的影响力。 （4）脚本语言 　　在Java技术标准中新增加了编程语言Groovy（JSR 241）。这是一种可与Java语言无缝连接的脚本语言，有望以极短的程序完成相关处理。“在Java技术中添加Java以外的语言”，这听起来也许有些别扭，其实以前就有这样的呼声，希望将可以充分利用Java技术资源的脚本作为语言使用。Groovy本来是源码开放软件，最终得到认可，被采纳为标准规格。 　　由上述可以看出，Java技术的构成要素正在发生巨大变化。就在不久以前，一提起服务器Java，“Servlet、JSP、EJB是重要的API”这样的说明还占主流，但现在基于JSF和EJB3.0的应用程序已经变成了“面目全非”的程序。而在运行短程序或测试时，甚至还出现了不仅是Java语言，连脚本语言都开始调用Java框架的情况。 &#8230; <a href="http://welog.org/blog/42">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>【日经BP社报道】&nbsp;Java技术自问世时光已经过去了9个年头。作为一名一直关注其成长的记者，曾经一段时间有过这样的想法：“Java技术已经成熟，是不是发展速度该放慢一些了呢”。然而，这种想法错了。近来Java技术的进化相当显著。Java技术正在迎来“又一次革命”的风暴。这就是本文的结论。&nbsp;&nbsp;</p>
<p>　　“又一次”指的是什么？“革命”指的又是什么？光看结论的话肯定是一头雾水。其实，笔者要讲的并不是变化这样一个事实，而是“促进变化的原动力”。是什么让Java技术发生变化？让我们从这一角度出发，先看一下Java的变化历程。&nbsp;&nbsp;</p>
<p>Java正处于转变期&nbsp;&nbsp;<br />
<span id="more-42"></span><br />
【日经BP社报道】 Java技术自问世时光已经过去了9个年头。作为一名一直关注其成长的记者，曾经一段时间有过这样的想法：“Java技术已经成熟，是不是发展速度该放慢一些了呢”。然而，这种想法错了。近来Java技术的进化相当显著。Java技术正在迎来“又一次革命”的风暴。这就是本文的结论。  </p>
<p>　　“又一次”指的是什么？“革命”指的又是什么？光看结论的话肯定是一头雾水。其实，笔者要讲的并不是变化这样一个事实，而是“促进变化的原动力”。是什么让Java技术发生变化？让我们从这一角度出发，先看一下Java的变化历程。  </p>
<p>Java正处于转变期  </p>
<p>　　回顾Java技术的发展历程，人们一定会感慨：2004年到2005年发生的变化如此之大，可以说“现在”正是Java技术的转换期。Java技术由编程语言（Java语言）、运行环境（JVM：Java虚拟机）、框架（Java API群）组成，目前在每一个层面上都发生着巨大的变化。  </p>
<p>（1）编程语言的变化  </p>
<p>　　Java语言标准出现明显变化。在2004年9月发布的正式版本J2SE5.0（J2SE:Java2 Stan&#100;ard, Stan&#100;ard Edition，Java技术的核心运行环境）中，对Java语言标准中的Generics与元数据进行了大幅扩展。出现了被认为是“自Java问世以来的最大一次语言标准变化”（美国Sun Microsystems）。这次语言标准的变化给许多Java API带来了影响。许多企业API的新版本都引入了基于元数据的注解（程序中记录的附加信息），以较短的编码记述更多的信息。  </p>
<p>（2）Java运行环境的变化  </p>
<p>　　在J2SE5.0中，大幅度强化了JVM的管理功能与实用性，换句话说就是具备了Java执行OS（操作系统）的特征。例如，原来在J2EE（Java2 Platform, Enterprise Edition，构筑企业系统的Java技术）领域，标准配备有作为管理功能的应用软件管理框架JMX。不仅如此，还配备有JVM自身监控功能（（JSR 174: Monitoring an&#100; Management Specification for the Java Virtual Machine）。在标准功能架构中可以实时监视JVM运行时的状态，也就是内存使用量、线程状态等。  </p>
<p>　　J2SE5.0中新追加的功能中包括并行处理实用程序（JSR 166），其基础是纽约州立大学Doug Lea提供的程序库。也就是说，标准规格中采用了来自民间的程序库。  </p>
<p>（3）框架的变化  </p>
<p>　　服务器端的Java框架也发生了巨大变化。企业级Java技术&#8211;J2EE的“使用方法”说明文件“J2EE Blueprint”中，提出了将应用软件分为Web层、EJB层（Enterprise JavaBeans，将包括事务处理在内的业务进程模块化的框架）来构筑的思路。这两种层次都迎来了架构更替时期。Web层的新框架为JSF（JavaServer Faces，将模块组合起来构筑Web应用程序的框架），EJB层为标准方案中刚刚公布的下一代EJB规格“EJB3.0”。  </p>
<p>　　值得注意的是，促成框架发生变化的正是来自民间的源码开放软件。  </p>
<p>　　对JSF产生影响的是作为源码开放的Web层框架得到普及的Apache Struts。JSF是对Struts的思路进行改进的产物，JSF的Spec Lead（规格制定领袖）之一Craig R. McClanahan就是Struts的作者。  </p>
<p>　　对EJB3.0造成影响的也是民间源码开放软件。EJB3.0引入了DI（Dependency Injection，依赖注入）容器类（Container）与POJO（Plain Old Java Object）持久类这些新功能，大大减轻了编程的复杂性。这些概念因PicoContainer、Spring等源码开放软件的导入而引人注目。  </p>
<p>　　其背景在于用户对“目前的EJB过于复杂”的批评。原本由EJB反对派提出的设计思想与源码开放软件，却变成了EJB3.0的中心概念，显出了巨大的影响力。  </p>
<p>（4）脚本语言  </p>
<p>　　在Java技术标准中新增加了编程语言Groovy（JSR 241）。这是一种可与Java语言无缝连接的脚本语言，有望以极短的程序完成相关处理。“在Java技术中添加Java以外的语言”，这听起来也许有些别扭，其实以前就有这样的呼声，希望将可以充分利用Java技术资源的脚本作为语言使用。Groovy本来是源码开放软件，最终得到认可，被采纳为标准规格。  </p>
<p>　　由上述可以看出，Java技术的构成要素正在发生巨大变化。就在不久以前，一提起服务器Java，“Servlet、JSP、EJB是重要的API”这样的说明还占主流，但现在基于JSF和EJB3.0的应用程序已经变成了“面目全非”的程序。而在运行短程序或测试时，甚至还出现了不仅是Java语言，连脚本语言都开始调用Java框架的情况。  </p>
<p>　　这些变化从大的方面来看的话，可以说是进一步发挥了Java面向对象的优势。当然，也包括提高开发效率、提高运行稳定性、简化运行管理等业务上的优势。  </p>
<p>开发者团体是真正的“变革推动者”  </p>
<p>　　那么，这些变化的原动力来自哪里呢？为什么说“目前”正面临着“又一次变革”呢？理由如下：  </p>
<p>　　在Java技术的发展过程中，1999年到2000年是一个大的转折点。J2EE概念于1999年出现。日本国内的J2EE也在随后2～3年内得到正式普及，但这一技术体系早在5年前就已经确立。在我们眼前，新一代Java技术的轮廓正逐渐显现出来。  </p>
<p>　　JCP（Java Community Process）2.0于2000年问世。以会员制的组织形式推进Java技术的规格制订、总体发展方向则以委员会的方式决定。从而形成了不依赖特定企业的规格制订流程。这一组织形式历经近5年的时间，逐渐发展成“变革的推动者”。  </p>
<p>　　J2EE此前一直饱受批评，认为“Web层与EJB层的差距太大”、“EJB过于复杂”，但这也是因为这是一项实际使用的技术。JCP同样也遇到很多批评，称其“没有完全公开”、“制定的技术标准却不可思议地让Sun拥有知识产权”，但JCP却作为一个团体不断发展壮大。  </p>
<p>　　直接推动Java技术变化的当事者为5年前形成的基于团体的标准制订流程&#8211;JCP，但真正将讨论与技术纳入JCP的却是包括Java技术批评者在内的众多Java开发者团体。他们也是早期开展Java技术变革的先行者。由此诞生的下一代技术将会在2～3年后逐渐波及主流企业用户。  </p>
<p>　　Java技术的“变革推动者”为开发者团体。不受制于特定企业，通过众多需要Java的开发者的建议，Java技术正在不断发展进步。（记者：星 晓雄）  </p>
<p>&#8212;&#8211;</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/42/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thinking in Java学习笔记</title>
		<link>http://welog.org/blog/37</link>
		<comments>http://welog.org/blog/37#comments</comments>
		<pubDate>Fri, 11 Mar 2005 22:44:00 +0000</pubDate>
		<dc:creator>Airblue</dc:creator>
				<category><![CDATA[读书]]></category>

		<guid isPermaLink="false">http://demo.thinkevolving.org/archives/thinking-in-java%e5%ad%a6%e4%b9%a0%e7%ac%94%e8%ae%b0/</guid>
		<description><![CDATA[第一章&#160;对象导论 　　其实这章介绍的是oop的思想，知道什么是抽象、接口、继承等等，其实这些我觉得没有必要专门提出来写一章，这个我就不介绍了　　在以后的学习中，这些知识是会在里面融会贯通的。 第一章 对象导论 　　其实这章介绍的是oop的思想，知道什么是抽象、接口、继承等等，其实这些我觉得没有必要专门提出来写一章，这个我就不介绍了 　　在以后的学习中，这些知识是会在里面融会贯通的。 　　第二章 万事万物皆对象 　　在java程序中，万事万物皆对象，即使是java程序本身，也是一个对象 　　一、Reference是操纵对象之钥匙 　　c语言中是使用指针来操纵对象的，但是java呢？用的是reference来操纵对象，我习惯把他叫做句柄，句柄和对象的关系就想是电视遥控器和电视机的关系一样，既然是这样，那么遥控器和电视机都是可以独立出现的 　　例如：String name; 　　这个java语句只会产生句饼（遥控器），并不产生实际的对象（电视机），就想你老婆还没生孩子之前你们就把名字给取好了一样，句柄并没有连接到实际的对象上。这个样子写代码是不推荐的，一个没有指向对象的句柄在调用的时候编译器会抱错，应当使用String name=&#8221;baby&#8221;;，或者使用String name =new String(&#8220;baby&#8221;);这里new的意思是产生一个string类型的对象，并且这个string叫做baby。这2个方法都可以实现对象的建立。 　　二、所有的对象都需要你来建立 　　1、储存在那里 　　a、寄存器 这里是核心的存储空间，我们是没办法操纵的 　　b、栈 （stack ）这里的存取速度快，效率高，因为这里要求被存储的数据有具体大小和存活时间限制，使用弹性小，这里一般存储的是我们的对象句柄，而对象是不存在这里的 　　c、堆 （heap） 这里是通用的存储空间，他比stack好在编译器不需要知道实际在heap中存储数据的大小，也不知道这个空间需要分配多长时间，弹性好，所以用来存储对象，但是速度要比stack慢很多 　　d、静态存储空间（static storage）这里是存放被声明为static的特定成员，java对象本身是不会分配在这里的 　　e、常量储存空间 这里存放的是程序中的常量，常量值不会改变，最安全 　　f、non-ram 流或者是持久话对象 　　2、基本数据类型 　　boolean char byte short int long float double void 基本数据类型的数据是不用new 来创建的，直接int i=0，不使用heap空间，他是被放在stack中的，速度快！但是假如你要是想用heap来存储基本数据类型的话，就要使用该类型的外覆类来实现了 例如Integer i= new Integer(&#8220;0&#8243;); 　　注意！String不是基本数据类型，她是对象！从他的定义方法就可以知道了！ 　　3、数组（array） 　　java中的数组使用和定义上要比c中的数组更安全，当你在定义数组的时候其实产生的是一个储存对象句柄的数组，而每一个句柄所指向的值回被设定为null，也就是不指向任何对象 三、你不需要摧毁对象 &#8230; <a href="http://welog.org/blog/37">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>第一章&nbsp;对象导论</p>
<p>　　其实这章介绍的是oop的思想，知道什么是抽象、接口、继承等等，其实这些我觉得没有必要专门提出来写一章，这个我就不介绍了<br />　　在以后的学习中，这些知识是会在里面融会贯通的。<br />
<span id="more-37"></span><br />
第一章 对象导论</p>
<p>　　其实这章介绍的是oop的思想，知道什么是抽象、接口、继承等等，其实这些我觉得没有必要专门提出来写一章，这个我就不介绍了<br />
　　在以后的学习中，这些知识是会在里面融会贯通的。</p>
<p>　　第二章 万事万物皆对象</p>
<p>　　在java程序中，万事万物皆对象，即使是java程序本身，也是一个对象</p>
<p>　　一、Reference是操纵对象之钥匙</p>
<p>　　c语言中是使用指针来操纵对象的，但是java呢？用的是reference来操纵对象，我习惯把他叫做句柄，句柄和对象的关系就想是电视遥控器和电视机的关系一样，既然是这样，那么遥控器和电视机都是可以独立出现的</p>
<p>　　例如：String name;</p>
<p>　　这个java语句只会产生句饼（遥控器），并不产生实际的对象（电视机），就想你老婆还没生孩子之前你们就把名字给取好了一样，句柄并没有连接到实际的对象上。这个样子写代码是不推荐的，一个没有指向对象的句柄在调用的时候编译器会抱错，应当使用String name=&#8221;baby&#8221;;，或者使用String name =new String(&#8220;baby&#8221;);这里new的意思是产生一个string类型的对象，并且这个string叫做baby。这2个方法都可以实现对象的建立。</p>
<p>　　二、所有的对象都需要你来建立</p>
<p>　　1、储存在那里</p>
<p>　　a、寄存器  这里是核心的存储空间，我们是没办法操纵的</p>
<p>　　b、栈 （stack ）这里的存取速度快，效率高，因为这里要求被存储的数据有具体大小和存活时间限制，使用弹性小，这里一般存储的是我们的对象句柄，而对象是不存在这里的</p>
<p>　　c、堆 （heap） 这里是通用的存储空间，他比stack好在编译器不需要知道实际在heap中存储数据的大小，也不知道这个空间需要分配多长时间，弹性好，所以用来存储对象，但是速度要比stack慢很多</p>
<p>　　d、静态存储空间（static storage）这里是存放被声明为static的特定成员，java对象本身是不会分配在这里的</p>
<p>　　e、常量储存空间 这里存放的是程序中的常量，常量值不会改变，最安全</p>
<p>　　f、non-ram  流或者是持久话对象</p>
<p>　　2、基本数据类型</p>
<p>　　boolean char byte short int long float double void  基本数据类型的数据是不用new 来创建的，直接int i=0，不使用heap空间，他是被放在stack中的，速度快！但是假如你要是想用heap来存储基本数据类型的话，就要使用该类型的外覆类来实现了 例如Integer  i= new Integer(&#8220;0&#8243;);</p>
<p>　　注意！String不是基本数据类型，她是对象！从他的定义方法就可以知道了！</p>
<p>　　3、数组（array）</p>
<p>　　java中的数组使用和定义上要比c中的数组更安全，当你在定义数组的时候其实产生的是一个储存对象句柄的数组，而每一个句柄所指向的值回被设定为null，也就是不指向任何对象<br />
三、你不需要摧毁对象</p>
<p>　　1、基本类型生存范围</p>
<p>　　java中基本类型的生存范围是由一对大括号决定的，在生存空间内定义的变量，只能用于生存空间结束之前</p>
<p> 　　{<br />
　　int i=1;<br />
　　{<br />
　　int i=100;//错误！这样的定义在java总是不允许的！编译器会认为i已经被定义过了<br />
　　}<br />
　　}</p>
<p>　　2、对象的生存范围</p>
<p>　　对象拥有的寿命和基本类型是不一样的，当你使用new来产生一个对象的时候，即使离开了大括号，该对象还是存在的</p>
<p> 　　{<br />
　　String name =new Sting(&#8220;baby&#8221;);<br />
　　}</p>
<p>　　句柄name会在大括号的生存空间之外消失的，但是他所指向的string对象却还在继续占用着内存，但是大家会认为大量的无用对象会占用大量的内存，java中是怎么解决的呢？他使用的是垃圾回收机制，垃圾回收器会在特定的时间检查使用new创建的对象，假如这些对象已经没有句柄指向他们，那么他就回把无用的对象清理掉。</p>
<p>　　四、建立新的数据类型 class</p>
<p>　　java中既然一切全是对象，那么是什么来限制对象的属性呢？通过使用类。java中使用class关键字来自己定义一个类</p>
<p>　　例如：class women{ //class body}这样你就定义一个women 类，当然这个类没有任何属性</p>
<p>　　1、数据成员和方法</p>
<p>　　一个类中，存在2中成员，一个是数据成员，一个是方法。数据成员可以是基本数据类型，也可以是对象，而基本数据类型在声明的时候系统会自动的给他赋予一个初始值</p>
<p>　　五、方法、参数、返回值</p>
<p>　　一个合法的方法包括名称、参数、返回类型、方法体 例如</p>
<p> 　　void name(int i)<br />
　　{<br />
　　return;</p>
<p>　　}其中 名称name()      参数int i       返回类型 void     方法体 {}，对于一个class而言，名称+参数的组合必须是唯一的，参数也可以是空的，有一个叫test的对象允许你调用一个返回值为string的方法getTest(),则 String name = test.getTest(); name的类型一定要和返回值的类型相同。</p>
<p>　　在向一个方法传递一个对象的时候，其实传递的是该对象的句柄（基本数据类型除外），而传递的对象类型一定要和方法中接受参数的参数类型相同。当你不需要方法给你返回什么东西的时候，你可以把该方法的返回类型设置为void，而此时方法中的return就是用来离开方法的，不需要等到他执行完毕，如果方法的返回类型不为void的时候，你可以使用return 返回一个和返回类型一样的值</p>
]]></content:encoded>
			<wfw:commentRss>http://welog.org/blog/37/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

