摘要: 提起Java內(nèi)部類(Inner Class)可能很多人不太熟悉,實(shí)際上類似的概念在C++里也有,那就是嵌套類(Nested Class),關(guān)于這兩者的區(qū)別與聯(lián)系,在下文中會(huì)有對(duì)比。內(nèi)部類從表面上看,就是在類中又定義了一個(gè)類(下文會(huì)看到,內(nèi)部類可以在很多地方定義),而實(shí)際上并沒(méi)有那么簡(jiǎn)單,乍看上去內(nèi)部類似乎有些多余,它的用處對(duì)于初學(xué)者來(lái)說(shuō)可能并不是那么顯著,但是隨著對(duì)它的深入了解,你會(huì)發(fā)現(xiàn)Java的...
閱讀全文
posted @
2010-06-30 14:26 J2EE學(xué)習(xí)筆記 閱讀(307) |
評(píng)論 (0) |
編輯 收藏
在JScript的眾多運(yùn)算符里,提供了三個(gè)邏輯運(yùn)算符&&、||和!,噢?! 是高級(jí)語(yǔ)言都提供的
。按我們對(duì)邏輯運(yùn)算的正常認(rèn)識(shí),邏輯運(yùn)算的結(jié)果因該是ture或者false。但是JScript的邏輯運(yùn)算卻不完全是這么定義的,這里只有!運(yùn)算符總是返回true|false,而||和&&運(yùn)算比較的好玩。
JScript對(duì)于邏輯運(yùn)算的true|false是這么定義的:
- 所有對(duì)象都被認(rèn)為是 true。
- 字符串當(dāng)且僅當(dāng)為空(""或'')時(shí)才被認(rèn)為是 false。
- null 和未定義的均被認(rèn)為是 false。
- 數(shù)字當(dāng)且僅當(dāng)為 0 時(shí)才是 false。
可是邏輯運(yùn)算符||和&&雖然遵循上面的定義規(guī)則,但是它們返回的值卻很有意思。
對(duì)于&&運(yùn)算,按照上面的規(guī)則,表達(dá)式 if ( 'abc' && '123' && new Date() ) 是執(zhí)行true分支,可是這個(gè)表達(dá)式如果寫(xiě)成:
var value = 'abc' && '123' && new Date();
結(jié)果value=Fri Jan 21 00:01:17 UTC+0800 2005,原它從左到右檢測(cè),如果到了最后一個(gè)表達(dá)式也是為true的,就返回那個(gè)表達(dá)式。
對(duì)于||運(yùn)算同理,對(duì)于下面的表達(dá)式:
var value1 = 'abc' || '123' || null || false;
var value2 = null || '' || false || 'ok';
結(jié)果value1='abc',value2='ok'。這是因?yàn)閨|運(yùn)算會(huì)有"短路"特性,他也是從左向右檢測(cè),只不過(guò)它是一但發(fā)現(xiàn)有為true的值,就立即返回該表達(dá)式。
這樣的特性可以幫組我們寫(xiě)出精簡(jiǎn)的代碼,可是同時(shí)也帶來(lái)代碼不便于閱讀維護(hù)的問(wèn)題。
由于我手頭暫時(shí)沒(méi)有NS和moz什么的瀏覽器,不知道標(biāo)準(zhǔn)JavaScript是否也是這樣支持的?如果您方便的話,請(qǐng)告如我運(yùn)行后的結(jié)果
posted @
2010-05-13 15:11 J2EE學(xué)習(xí)筆記 閱讀(188) |
評(píng)論 (0) |
編輯 收藏
有時(shí)你可能需要對(duì)變量進(jìn)行類型檢查,或者判斷變量是否已定義。有兩種方法可以使用:typeof函數(shù)與constructor屬性。
typeof函數(shù)的用法可能不用我多說(shuō),大家都知道怎么用。而constructor屬性大家可能就陌生點(diǎn)。在《精通JavaScript》這本書(shū)中有提到construct的用法,但我用自己的幾個(gè)瀏覽器(IE7.0 / Firefox1.9 / Opera9.50)測(cè)試的結(jié)果卻和書(shū)上說(shuō)的不一樣。但是仍然是有辦法通過(guò)constructor屬性來(lái)檢查變量類型的。
這里先補(bǔ)充一下,為什么明明有typeof函數(shù)可以很方便地用來(lái)檢測(cè)類型,還要用constructor呢?
因?yàn)閠ypeof會(huì)把所有的數(shù)組類型以及用戶自定義類型判斷為object,從而無(wú)法知道更確切的信息。而constructor卻可以解決這個(gè)問(wèn)題。
ok,明白了我們?yōu)槭裁匆胏onstructor,現(xiàn)在讓我?guī)Т蠹乙徊讲秸J(rèn)識(shí)一下typeof和constructor用法之間的差異吧~
首先我們運(yùn)行一下下面這段代碼:
var i;
alert(typeof(i));
alert(i.constructor);
這3行代碼告訴你什么情況下可以用constructor。
你可以看到第2行返回了字符串'undefined',而第三行則發(fā)生了錯(cuò)誤,原因是i變量還沒(méi)有類型定義,自然也沒(méi)有constructor的存在。
從這一點(diǎn)上看,typeof可以檢查到變量是否有定義,而construct只能檢查已定義變量的類型。
再運(yùn)行一下下面這段代碼:
var i = 2;
alert(typeof(i));
alert(i.constructor);
alert(typeof(i.constructor));
你會(huì)看到第2行返回了字符串'number’,第3行返回了一串類似函數(shù)定義的代碼字符串(這就是跟《精通JavaScript》一書(shū)中介紹的不一樣的地方)。
我們?cè)儆胻ypeof檢查一下constructor到底是個(gè)什么樣類型的屬性,第4行返回結(jié)果'function',也就是說(shuō),實(shí)際上constructor是一個(gè)函數(shù),更確切地說(shuō)是一個(gè)構(gòu)造函數(shù)。這時(shí)你就可以知道,為什么constructor可以檢查出各種類型了。
有經(jīng)驗(yàn)的程序員看到這里應(yīng)該知道要怎么利用constructor來(lái)檢查變量類型了。方法有多種,這里提供一種比較容易理解的方法。
其實(shí)想法很簡(jiǎn)單,就是把construcor轉(zhuǎn)化為字符串,通過(guò)尋找匹配字符串(function名)來(lái)確定是否指定類型。如下例子:

function user()
{};
var i = new user();
alert((i.constructor+'').match(/user/) == null);
這僅僅是個(gè)簡(jiǎn)單的例子。如果返回true則變量i不是user類型,返回false則變量是user類型。
當(dāng)然,這樣檢測(cè)是不夠精確的,比如其實(shí)他是一個(gè)myuser類型的時(shí)候,同樣會(huì)被認(rèn)為是user類。所以你需要書(shū)寫(xiě)更精確的正則表達(dá)式去進(jìn)行匹配。
可以這樣簡(jiǎn)單改進(jìn)你的正則表達(dá)式:
/function user\(\)/
替換上面代碼段中的/user/。當(dāng)然,如果你的構(gòu)造函數(shù)原型是user(a),那么應(yīng)該這樣書(shū)寫(xiě)你的正則表達(dá)式:
/function user\(a\)/
到這里你應(yīng)該知道怎樣使用constructor類型去檢查變量類型了吧?
ok,最后再提個(gè)醒,如果你要用基于constructor的方法去檢查一些基本類型,如
Object / Array / Function / String / Number / Boolean
在你的正則表達(dá)式中,一定要將這些單詞的首字母大寫(xiě)!!而如果該類型是自定義類型,則根據(jù)你定義的時(shí)候標(biāo)識(shí)符的寫(xiě)法確定。
posted @
2010-04-14 14:30 J2EE學(xué)習(xí)筆記 閱讀(321) |
評(píng)論 (0) |
編輯 收藏

/** *//**
使用三種Callback接口作為參數(shù)的query方法的返回值不同:
以ResultSetExtractor作為方法參數(shù)的query方法返回Object型結(jié)果,要使用查詢結(jié)果,我們需要對(duì)其進(jìn)行強(qiáng)制轉(zhuǎn)型;
以RowMapper接口作為方法參數(shù)的query方法直接返回List型的結(jié)果;
以RowCallbackHandler作為方法參數(shù)的query方法,返回值為void;
RowCallbackHandler和RowMapper才是我們最常用的選擇
* @author Administrator
*
*/

public class SpringTest
{

/** *//**
* 返回結(jié)果是List里裝Map,使用參數(shù),使用回調(diào) RowMapperResultSetExtractor用于處理單行記錄,
* 它內(nèi)部持有一個(gè)RowMapper實(shí)例的引用,當(dāng)處理結(jié)果集的時(shí)候, 會(huì)將單行數(shù)據(jù)的處理委派給其所持有的RowMapper實(shí)例,而其余工作它負(fù)責(zé)
*/

public void getListRowMapperResultSetExtractor()
{
ApplicationContext context = new FileSystemXmlApplicationContext(
"src/database_config.xml");
// E:\demoworkspace\spring 為工程主目錄
JdbcTemplate jt = new JdbcTemplate((DataSource) context
.getBean("oracleDataSourceTest")); // 測(cè)試用的方法

Object[] arg = new Object[]
{ 10 };
List list = (ArrayList) jt.query("select * from region where rownum<?",

arg, new RowMapperResultSetExtractor(new RowMapper()
{
public Object mapRow(ResultSet rs, int index)

throws SQLException
{
Map u = new HashMap(); //可以是自己的JavaBean值對(duì)象(簡(jiǎn)單Java對(duì)象POJO)
u.put("region_id", rs.getString("region_id"));
u.put("region_name", rs.getString("region_name"));
return u;
}
}));
Iterator it = list.iterator();

while (it.hasNext())
{
Map map = (Map) it.next();
System.out.println(map.toString());
}
}

/** *//**返回結(jié)果是List里裝Map,不使用參數(shù),使用回調(diào)
使用RowMapper比直接使用ResultSetExtractor要方便的多,只負(fù)責(zé)處理單行結(jié)果就行,現(xiàn)在,我們只需要將單行的結(jié)果組裝后返回就行,
剩下的工作,全部都是JdbcTemplate內(nèi)部的事情了。 實(shí)際上,JdbcTemplae內(nèi)部會(huì)使用一個(gè)ResultSetExtractor實(shí)現(xiàn)類來(lái)做其余的工作,
畢竟,該做的工作還得有人做不是?!
*/

public void getListRowMapper()
{
ApplicationContext context = new FileSystemXmlApplicationContext(
"src/database_config.xml");
JdbcTemplate jt = new JdbcTemplate((DataSource) context
.getBean("oracleDataSourceTest"));
List list = jt.query(

"select * from region where rownum<10", new RowMapper()
{
public Object mapRow(ResultSet rs, int index)

throws SQLException
{
Map u = new HashMap();
u.put("region_id", rs.getString("region_id"));
u.put("region_name", rs.getString("region_name"));
return u;
}
});
Iterator it = list.iterator();

while (it.hasNext())
{
Map map = (Map) it.next();
System.out.println(map.toString());
}
}
// 返回記錄集

/** *//**
RowCallbackHandler雖然與RowMapper同是處理單行數(shù)據(jù),不過(guò),除了要處理單行結(jié)果,它還得負(fù)責(zé)最終結(jié)果的組裝和獲取工作,
在這里我們是使用當(dāng)前上下文聲明的List取得最終查詢結(jié)果, 不過(guò),我們也可以單獨(dú)聲明一個(gè)RowCallbackHandler實(shí)現(xiàn)類,
在其中聲明相應(yīng)的集合類,這樣,我們可以通過(guò)該RowCallbackHandler實(shí)現(xiàn)類取得最終查詢結(jié)果
*/

public void getListRowCallbackHandler()
{
ApplicationContext context = new FileSystemXmlApplicationContext(
"src/database_config.xml");
JdbcTemplate jt = new JdbcTemplate((DataSource) context
.getBean("oracleDataSourceTest"));
String sql = "select * from region where region_id>?";
final List<Map> list=new ArrayList<Map>(); //一定要用final定義

Object[] params = new Object[]
{ 0 };

jt.query(sql, params, new RowCallbackHandler()
{

public void processRow(ResultSet rs) throws SQLException
{
Map u = new HashMap();
u.put("region_id", rs.getString("region_id"));
u.put("region_name", rs.getString("region_name"));
list.add(u);
}
});
Iterator it = list.iterator();

while (it.hasNext())
{
Map map = (Map) it.next();
System.out.println(map.toString());
}
}
posted @
2010-03-10 10:27 J2EE學(xué)習(xí)筆記 閱讀(569) |
評(píng)論 (0) |
編輯 收藏
摘要: 1.springJdbcContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
&nb...
閱讀全文
posted @
2010-03-09 19:10 J2EE學(xué)習(xí)筆記 閱讀(2017) |
評(píng)論 (0) |
編輯 收藏
很多朋友在深入的接觸JAVA語(yǔ)言后就會(huì)發(fā)現(xiàn)這樣兩個(gè)詞:反射(Reflection)和內(nèi)省(Introspector),經(jīng)常搞不清楚這到底是怎么回事,在什么場(chǎng)合下應(yīng)用以及如何使用?今天把這二者放在一起介紹,因?yàn)樗鼈兌呤窍噍o相成的。
反射
相對(duì)而言,反射比內(nèi)省更容易理解一點(diǎn)。用一句比較白的話來(lái)概括,反射就是讓你可以通過(guò)名稱來(lái)得到對(duì)象(類,屬性,方法)的技術(shù)。例如我們可以通過(guò)類名來(lái)生成一個(gè)類的實(shí)例;知道了方法名,就可以調(diào)用這個(gè)方法;知道了屬性名就可以訪問(wèn)這個(gè)屬性的值。
還是寫(xiě)兩個(gè)例子讓大家更直觀的了解反射的使用方法:
// 通過(guò)類名來(lái)構(gòu)造一個(gè)類的實(shí)例
Class cls_str = Class.forName( "java.lang.String" );
// 上面這句很眼熟,因?yàn)槭褂眠^(guò) JDBC 訪問(wèn)數(shù)據(jù)庫(kù)的人都用過(guò) J
Object str = cls_str.newInstance();
// 相當(dāng)于 String str = new String();
// 通過(guò)方法名來(lái)調(diào)用一個(gè)方法
String methodName = "length" ;
Method m = cls_str.getMethod(methodName, null );
System.out.println( "length is " + m.invoke(str, null ));
// 相當(dāng)于 System.out.println(str.length());
上面的兩個(gè)例子是比較常用方法。看到上面的例子就有人要發(fā)問(wèn)了:為什么要這么麻煩呢?本來(lái)一條語(yǔ)句就完成的事情干嗎要整這么復(fù)雜?沒(méi)錯(cuò),在上面的例子中確實(shí)沒(méi)有必要這么麻煩。不過(guò)你想像這樣一個(gè)應(yīng)用程序,它支持動(dòng)態(tài)的功能擴(kuò)展,也就是說(shuō)程序不重新啟動(dòng)但是可以自動(dòng)加載新的功能,這個(gè)功能使用一個(gè)具體類來(lái)表示。首先我們必須為這些功能定義一個(gè)接口類,然后我們要求所有擴(kuò)展的功能類必須實(shí)現(xiàn)我指定的接口,這個(gè)規(guī)定了應(yīng)用程序和可擴(kuò)展功能之間的接口規(guī)則,但是怎么動(dòng)態(tài)加載呢?我們必須讓?xiě)?yīng)用程序知道要擴(kuò)展的功能類的類名,比如是test.Func1,當(dāng)我們把這個(gè)類名(字符串)告訴應(yīng)用程序后,它就可以使用我們第一個(gè)例子的方法來(lái)加載并啟用新的功能。這就是類的反射,請(qǐng)問(wèn)你有別的選擇嗎?
內(nèi)省
內(nèi)省是Java語(yǔ)言對(duì)Bean類屬性、事件的一種缺省處理方法。例如類A中有屬性name,那我們可以通過(guò)getName,setName來(lái)得到其值或者設(shè)置新的值。通過(guò)getName/setName來(lái)訪問(wèn)name屬性,這就是默認(rèn)的規(guī)則。Java中提供了一套API用來(lái)訪問(wèn)某個(gè)屬性的getter/setter方法,通過(guò)這些API可以使你不需要了解這個(gè)規(guī)則(但你最好還是要搞清楚),這些API存放于包java.beans中。
一般的做法是通過(guò)類Introspector來(lái)獲取某個(gè)對(duì)象的BeanInfo信息,然后通過(guò)BeanInfo來(lái)獲取屬性的描述器(PropertyDescriptor),通過(guò)這個(gè)屬性描述器就可以獲取某個(gè)屬性對(duì)應(yīng)的getter/setter方法,然后我們就可以通過(guò)反射機(jī)制來(lái)調(diào)用這些方法。下面我們來(lái)看一個(gè)例子,這個(gè)例子把某個(gè)對(duì)象的所有屬性名稱和值都打印出來(lái):

/**//*
* Created on 2004-6-29
*/

package demo;


import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;



/** *//**
* 內(nèi)省演示例子
* @author liudong
*/


public class IntrospectorDemo
{
String name;

public static void main(String[] args) throws Exception
{
IntrospectorDemo demo = new IntrospectorDemo();
demo.setName( "Winter Lau" );

// 如果不想把父類的屬性也列出來(lái)的話,
// 那 getBeanInfo 的第二個(gè)參數(shù)填寫(xiě)父類的信息
BeanInfo bi = Introspector.getBeanInfo(demo.getClass(), Object. class );
PropertyDescriptor[] props = bi.getPropertyDescriptors();

for ( int i=0;i<props.length;i++)
{
System.out.println(props[i].getName()+ "=" +
props[i].getReadMethod().invoke(demo, null ));
}

}


public String getName()
{
return name;
}


public void setName(String name)
{
this .name = name;
}
}
Web開(kāi)發(fā)框架Struts中的FormBean就是通過(guò)內(nèi)省機(jī)制來(lái)將表單中的數(shù)據(jù)映射到類的屬性上,因此要求FormBean的每個(gè)屬性要有g(shù)etter/setter方法。但也并不總是這樣,什么意思呢?就是說(shuō)對(duì)一個(gè)Bean類來(lái)講,我可以沒(méi)有屬性,但是只要有g(shù)etter/setter方法中的其中一個(gè),那么Java的內(nèi)省機(jī)制就會(huì)認(rèn)為存在一個(gè)屬性,比如類中有方法setMobile,那么就認(rèn)為存在一個(gè)mobile的屬性,這樣可以方便我們把Bean類通過(guò)一個(gè)接口來(lái)定義而不用去關(guān)系具體實(shí)現(xiàn),不用去關(guān)系Bean中數(shù)據(jù)的存儲(chǔ)。比如我們可以把所有的getter/setter方法放到接口里定義,但是真正數(shù)據(jù)的存取則是在具體類中去實(shí)現(xiàn),這樣可提高系統(tǒng)的擴(kuò)展性。
總結(jié)
將Java的反射以及內(nèi)省應(yīng)用到程序設(shè)計(jì)中去可以大大的提供程序的智能化和可擴(kuò)展性。有很多項(xiàng)目都是采取這兩種技術(shù)來(lái)實(shí)現(xiàn)其核心功能,例如我們前面提到的Struts,還有用于處理XML文件的Digester項(xiàng)目,其實(shí)應(yīng)該說(shuō)幾乎所有的項(xiàng)目都或多或少的采用這兩種技術(shù)。在實(shí)際應(yīng)用過(guò)程中二者要相互結(jié)合方能發(fā)揮真正的智能化以及高度可擴(kuò)展性。
posted @
2010-02-04 13:42 J2EE學(xué)習(xí)筆記 閱讀(376) |
評(píng)論 (1) |
編輯 收藏
摘要: 原文出處:http://blog.chenlb.com/2008/11/join-or-countdownlatch-make-main-thread-wait-all-sub-thread.html
在編寫(xiě)多線程的工作中,有個(gè)常見(jiàn)的問(wèn)題:主線程(main) 啟動(dòng)好幾個(gè)子線程(task)來(lái)完成并發(fā)任務(wù),主線程要等待所有的子線程完成之后才繼續(xù)執(zhí)行main的其它任務(wù)。
默認(rèn)主線程退出時(shí)其它子線程不...
閱讀全文
posted @
2010-01-26 18:00 J2EE學(xué)習(xí)筆記 閱讀(1207) |
評(píng)論 (0) |
編輯 收藏
這是jQuery里常用的2個(gè)方法。
他們2者功能是完全不同的,而初學(xué)者往往會(huì)被誤導(dǎo)。
首先 我們看.find()方法:
現(xiàn)在有一個(gè)頁(yè)面,里面HTML代碼為:
<div class="css">
<p class="rain">測(cè)試1</p>
</div>
<div class="rain">
<p>測(cè)試2</p>
</div>
如果我們使用find()方法:
var $find = $("div").find(".rain");
alert( $find.html() );
將會(huì)輸出:

如果使用filter()方法:
var $filter = $("div").filter(".rain");
alert( $filter.html() );
將會(huì)輸出:

也許你已經(jīng)看出它們的區(qū)別了。
find()會(huì)在div元素內(nèi) 尋找 class為rain 的元素。
而filter()則是篩選div的class為rain的元素。
一個(gè)是對(duì)它的子集操作,一個(gè)是對(duì)自身集合元素篩選。
另外find()其實(shí)還可以用選擇器表示:
var $select = $("div .rain");
posted @
2009-11-09 16:00 J2EE學(xué)習(xí)筆記 閱讀(376) |
評(píng)論 (0) |
編輯 收藏