2008年12月2日
#
public class QuenDemo {
public static void main(String[] args){
//public class Queue extends Collection
Queue<Integer> queue=new LinkedList<Integer>();
Random rand = new Random(47);
for(int i=0;i<10;i++){
queue.offer(rand.nextInt(i+10));
}
System.out.println("1111"+queue.toString());
printQ(queue);
//public class LinkedList extends AbstractSequentialList implements List,Queue,Cloneable,Serializable
Queue<Character> qc=new LinkedList<Character>();
for(char c:"guoxzh".toCharArray()){
qc.offer(c);
System.out.println("qc=="+qc.toString());
}
printQ(qc);
}
public static void printQ(Queue queue){
while(queue.peek()!=null){
//peek和element都是在不移除的情況下返回對頭,但是peek在隊列為空的情況下返回null,element方法會拋出NoSuchElementException異常
System.out.println(queue.remove());
//remove和poll方法都是在移除并返回對頭,但是poll在為空時返回null,而remove會拋出NoSucheElementException異常
System.out.println("2222"+queue.toString());
}
}
}
package src;
import java.io.UnsupportedEncodingException;
public class ChangeCharset {
/** 7位ASCII字符,也叫作ISO646-US、Unicode字符集的基本拉丁塊 */
public static final String US_ASCII = "US-ASCII";
/** ISO 拉丁字母表 No.1,也叫作 ISO-LATIN-1 */
public static final String ISO_8859_1 = "ISO-8859-1";
/** 8 位 UCS 轉換格式 */
public static final String UTF_8 = "UTF-8";
/** 16 位 UCS 轉換格式,Big Endian(最低地址存放高位字節)字節順序 */
public static final String UTF_16BE = "UTF-16BE";
/** 16 位 UCS 轉換格式,Little-endian(最高地址存放低位字節)字節順序 */
public static final String UTF_16LE = "UTF-16LE";
/** 16 位 UCS 轉換格式,字節順序由可選的字節順序標記來標識 */
public static final String UTF_16 = "UTF-16";
/** 中文超大字符集 */
public static final String GBK = "GBK";
/**
* 將字符編碼轉換成US-ASCII碼
*/
public String toASCII(String str) throws UnsupportedEncodingException{
return this.changeCharset(str, US_ASCII);
}
/**
* 將字符編碼轉換成ISO-8859-1碼
*/
public String toISO_8859_1(String str) throws UnsupportedEncodingException{
return this.changeCharset(str, ISO_8859_1);
}
/**
* 將字符編碼轉換成UTF-8碼
*/
public String toUTF_8(String str) throws UnsupportedEncodingException{
return this.changeCharset(str, UTF_8);
}
/**
* 將字符編碼轉換成UTF-16BE碼
*/
public String toUTF_16BE(String str) throws UnsupportedEncodingException{
return this.changeCharset(str, UTF_16BE);
}
/**
* 將字符編碼轉換成UTF-16LE碼
*/
public String toUTF_16LE(String str) throws UnsupportedEncodingException{
return this.changeCharset(str, UTF_16LE);
}
/**
* 將字符編碼轉換成UTF-16碼
*/
public String toUTF_16(String str) throws UnsupportedEncodingException{
return this.changeCharset(str, UTF_16);
}
/**
* 將字符編碼轉換成GBK碼
*/
public String toGBK(String str) throws UnsupportedEncodingException{
return this.changeCharset(str, GBK);
}
/**
* 字符串編碼轉換的實現方法
* @param str 待轉換編碼的字符串
* @param newCharset 目標編碼
* @return
* @throws UnsupportedEncodingException
*/
public String changeCharset(String str, String newCharset)
throws UnsupportedEncodingException {
if (str != null) {
//用默認字符編碼解碼字符串。
byte[] bs = str.getBytes();
//用新的字符編碼生成字符串
return new String(bs, newCharset);
}
return null;
}
/**
* 字符串編碼轉換的實現方法
* @param str 待轉換編碼的字符串
* @param oldCharset 原編碼
* @param newCharset 目標編碼
* @return
* @throws UnsupportedEncodingException
*/
public String changeCharset(String str, String oldCharset, String newCharset)
throws UnsupportedEncodingException {
if (str != null) {
//用舊的字符編碼解碼字符串。解碼可能會出現異常。
byte[] bs = str.getBytes(oldCharset);
//用新的字符編碼生成字符串
return new String(bs, newCharset);
}
return null;
}
public static void main(String[] args) throws UnsupportedEncodingException {
ChangeCharset test = new ChangeCharset();
String str = "This is a 中文的 String!";
System.out.println("str: " + str);
String gbk = test.toGBK(str);
System.out.println("轉換成GBK碼: " + gbk);
System.out.println();
String ascii = test.toASCII(str);
System.out.println("轉換成US-ASCII碼: " + ascii);
gbk = test.changeCharset(ascii,ChangeCharset.US_ASCII, ChangeCharset.GBK);
System.out.println("再把ASCII碼的字符串轉換成GBK碼: " + gbk);
System.out.println();
String iso88591 = test.toISO_8859_1(str);
System.out.println("轉換成ISO-8859-1碼: " + iso88591);
gbk = test.changeCharset(iso88591,ChangeCharset.ISO_8859_1, ChangeCharset.GBK);
System.out.println("再把ISO-8859-1碼的字符串轉換成GBK碼: " + gbk);
System.out.println();
String utf8 = test.toUTF_8(str);
System.out.println("轉換成UTF-8碼: " + utf8);
gbk = test.changeCharset(utf8,ChangeCharset.UTF_8, ChangeCharset.GBK);
System.out.println("再把UTF-8碼的字符串轉換成GBK碼: " + gbk);
System.out.println();
String utf16be = test.toUTF_16BE(str);
System.out.println("轉換成UTF-16BE碼:" + utf16be);
gbk = test.changeCharset(utf16be,ChangeCharset.UTF_16BE, ChangeCharset.GBK);
System.out.println("再把UTF-16BE碼的字符串轉換成GBK碼: " + gbk);
}
}
JAVA里面關于byte數組和String之間的轉換問題
把byte轉化成string,必須經過編碼。
例如下面一個例子:
import java.io.UnsupportedEncodingException;
public class test{
public static void main(String g[]) {
String s = "12345abcd";
byte b[] = s.getBytes();
String t = b.toString();
System.out.println(t);
}
}
輸出字符串的結果和字符串s不一樣了.
經過以下方式轉碼就可以正確轉換了:
public class test{
public static void main(String g[]) {
String s = "12345abcd";
byte b[] = s.getBytes();
try {
String t = new String(b);
System.out.print(t);
} catch (Exception e) {
e.printStackTrace();
}
}
}
引用:
String str = "String";
byte[] byte1 = str.getBytes();
String str1 = new String(byte1);
byte[] byte2 = str1.getBytes();
String str2 = new String(byte2);
System.out.println("str<<<" + str);
System.out.println("byte1<<<" + byte1);
System.out.println("str1<<<" + str1);
System.out.println("byte2<<<" + byte2);
System.out.println("str2<<<" + str2);
-------------------------------------
輸出結果
str<<<String
byte1<<<[B@192d342
str1<<<String
byte2<<<[B@6b97fd
str2<<<String
想請教為什么兩個byte輸出的不一樣呢?
String str = "String";
byte[] byte1 = str.getBytes();
String str1 = new String(byte1);
byte[] byte2 = str1.getBytes();
----------
注意byte1是str得到的byte數組,而byte2是另一個字符串str1得到的數組
他們本身也是兩個對象
直接打印實際上調用的是toString()方法,而toString()的默認實現是打印對象類型+hashCode()
[B表示byte數組 @表示之后的是地址 后面跟著的是hashCode,其實就是其虛擬機地址
從大的方面來講,JVM的內存模型分為兩大塊:
永久區內存( Permanent space)和堆內存(heap space)。
棧內存(stack space)一般都不歸在JVM內存模型中,因為棧內存屬于線程級別。
每個線程都有個獨立的棧內存空間。
Permanent space里存放加載的Class類級對象如class本身,method,field等等。
heap space主要存放對象實例和數組。
heap space由Old Generation和NewGeneration組成,OldGeneration存放生命周期長久的實例對象,而新的對象實例一般放在NewGeneration。
New Generation還可以再分為Eden區(圣經中的伊甸園)、和Survivor區,新的對象實例總是首先放在Eden區,Survivor區作為Eden區和Old區的緩沖,可以向Old區轉移活動的對象實例。
一般,我們常見的OOM(out of memory)內存溢出異常,就是堆內存空間不足以存放新對象實例時導致。
永久區內存溢出相對少見,一般是由于需要加載海量的Class數據,超過了非堆內存的容量導致。通常出現在Web應用剛剛啟動時,因此Web應用推薦使用預加載機制,方便在部署時就發現并解決該問題。
棧內存也會溢出,但是更加少見。
堆內存優化:
調整JVM啟動參數-Xms -Xmx -XX:newSize -XX:MaxNewSize,如調整初始堆內存和最大對內存 -Xms256M -Xmx512M。 或者調整初始New Generation的初始內存和最大內存-XX:newSize=128M -XX:MaxNewSize=128M。
永久區內存優化:
調整PermSize參數 如 -XX:PermSize=256M-XX:MaxPermSize=512M。
棧內存優化:
調整每個線程的棧內存容量 如 -Xss2048K
最終,一個運行中的JVM所占的內存= 堆內存 + 永久區內存 + 所有線程所占的棧內存總和 。
財務公司的背景:
財務公司有兩種模式:
1.美國模式財務公司是以搞活商品流通、促進商品銷售為特色的非銀行金融機構,它依附于制造商,是一些大型耐用品而設立的受控子公司,這類財務公司主要是為零售商提供融資服務的,主要分布在美國、加拿大和德國。
2.英國模式財務公司基本上依附于商業銀行,其組建的目的在于規避政府對商業銀行的監管,因為政府規定,商業銀行不得從事證券投資業務,而財務公司不屬于銀行,所以不受此限制,這種模式主要分布在英國、日本和中國香港。
中國財務公司概況
財務公司又稱金融公司,是為了企業技術改造,新產品開發及產品銷售提供金融服務的,以中長期金融業務為主的非銀行機構,各國的名稱不同,業務內容也不一樣。
財務公司是中國企業體制改革和融資體制改革的產物,國家為了增強國有大中型企業的活力,盤活企業內部資金,增強企業集團的融資能力,支持企業集團的發展,促進產業結構和產品結果的調整,以及探索具有中國特色的產品資本與金融資本相結合的道路,于1987年成立了中國第一家企業集團財務公司,即東風汽車工業集團財務公司。
財務公司---公司主體
財務公司是根據《公司法》和《企業集團財務公司管理辦法》設立的,為企業集團成員單位技術改造、新產品開發及產品銷售提供金融服務,以中長期金融業務為主的非銀行機構。
財務公司一般分企業附屬財務公司和非企業附屬財務公司,企業附屬財務公司由企業設立,為本企業服務,但是服務范圍不僅局限于本企業;非企業附屬財務公司包括銀行附屬財務公司、引起合資財務公司和獨立財務公司。
1.銀行附屬財務公司是由銀行控股,因規避監管、實現金融創新和彌補銀行的不足而設立的,同時也為企業和個人提供金融服務。
2.銀行合資財務公司是銀行和企業出于金融創新規避監管或促進產融合作的考慮而設立,為企業和個人提供金融服務,
3.獨立財務公司一般是沒有母公司的財務公司,規模較小,比較靈活,在某一方面提供融資服務。
財務公司的業務范圍
1.經中國人民銀行批準,中國財務公司可從事下列部分或全部業務:
2.吸收成員單位3個月以上定期存款。
3.發行財務公司債券。
4.同業拆借。
5.對成員單位辦理貸款及融資租賃。
6.辦理集團成員單位產品的消費信貸、買方信貸及融資租賃。
7.辦理成員單位商業匯票的承兌及貼現。
8.辦理成員單位的委托貸款及委托投資。
9.有價證券、金融機構股權及成員單位股權投資。
10.承銷成員單位的企業債券。
11.對成員單位辦理財務顧問、信用鑒證及其他咨詢代理業務。
12.對成員單位提供擔保。
13.境外外匯借款。
14.經中國人民銀行批準的其他業務。
財務公司的主要作用
1.業務范圍比較廣,但是以企業集團為限。
主要業務有存款、貸款、結算、擔保和代理等一般銀行業務,還可以經人民銀行批準,開展證券、信托投資等業務。
2.資金來源于集團公司,用于集團公司,對集團公司的依附性強,
財務公司的資金主要來源于兩個方面:a、集團公司和集團成員公司投入的資本金;b、集團公司成員企業在財務公司的存款。
3.接受企業集團和人民銀行的雙重監管。
財務公司是企業內部的金融機構,期股東大都是集團公司成員企業,因而其景榮活動必然受到集團公司的監督,同時,財務公司所從事的是金融業務,其金融活動必須接受人民銀行監管
4.堅持服務與效益相結合、服務優先的經營原則。雖然財務公司作為獨立的法人,但是是企業集團內部的機構,且集團公司成員企業大都是財務公司的股東,所以財務公司在經營中一般都應較好地處理服務與效益的關系,在堅持為集團公司成員企業提供良好金融服務的前提下,努力實現利潤的最大化,
財務公司的作用
1.在資金管理方面和使用上,促使企業從粗放型向集約型轉變,
沒有財務公司之前,集團公司成員企業不能直接發生信貸關系,有些單位資金閑置,有些單位資金緊張,財務公司成立以后,成員單位成為財務公司的股東,在一定程度上集中了各成員單位的資本來進行一體化經營,財務公司應用金融手段將集團公司內企業的閑散資金集中起來,統籌安排使用,這樣不僅可以加快集團成員企業間資金結算的速度,而且總整體上降低了集團財務費用,提高就然公司資金的使用效率,加速集團公司資產一體化經營的進程,
2.財務公司以資金為紐帶,以服務為手段,增強了集團公司的凝聚力。
股本金將成員單位聯接在一起,另一方面財務公司吸納的資金又成為集團公司企業信貸資金的一個來源,從而集團公司成員企業進一步緊密的聯結在一起,形成了一種相互支持,相互促進,共同發展的局面。
3.及時解決了企業集團急需的資金,保證企業生產經營的正常進行。
4.增強了企業集團的融資功能,促進了集團公司的發展壯大,
5.有利于打破現有銀行體制資金規模按行政區域分割的局面,促進大集團公司跨地域、跨行業發展,
6.促進了金融業的競爭,有利于金融機構提高服務質量和效益,有利于金融體制改革的深化。
1、“我請客”:覺得我們常用pay這個詞,如Let me pay it for you。這里列舉三種說法:I am buying;This is on me;This is all my bill。
2、“收買某人”:有個比較正式的詞叫bribe,名詞時為“賄賂”的意思,動詞時就有“收買”之意。既然提到了“買”,那么我們能不能用上buy呢?當然,那就是buy sb off。
3、“向前看!”:我們會說Look forward!而美語里有個更貼切的說法是Eyes front!“眼睛朝前”,是不是很生動?
4、“頭等大事”:你會怎么翻譯呢?The most important thing嗎?看這個吧“It's on the top of my list”。
5、“看在主的份上,你就……”:兩種說法,其一是For the love of God,另外For God's sake(sake的意思是緣故、關系)二者之中,后者更常用
6、“我不是傻子!”:I am not a fool?對,語法完全正確。但再看這個I am no fool。比上面的只少兩個字母,但是不是感覺不一樣?同樣的道理,我們常說I have no idea,而不常說I dont have any idea。
7、short hairs:是說“短頭發”嗎?呵呵,它就是我們說的“小辮子”!
8、one-time thing:帥哥跟一美女過了一夜,回來后室友問帥哥:Do you really love her?帥哥回答:Oh, it was just a one-time thing!那么one-time thing是什么呢?我就不羅嗦嘍!
9、She knew red was her color。“她知道紅色是她的顏色”?恰當的翻譯是:她知道自己和紅色很相配。Then, what's your color?
10、“停電”:No electricity?恩,夠直白!其實提到“電”,老外更多是用power,停電就可以是Ther is a power failure或Power goes out
有一次編網頁的時候,把base 標簽給刪掉了,超鏈接怎么也行不通,老是路徑不對,原來是base 標簽在做怪:
<base>標記定義了文檔的基礎URL地址,在文檔中所有的相對地址形式的URL都是相對于這里定義的URL而言的。一篇文檔中的<base>標記不能多于一個,必須放于頭部,并且應該在任何包含URL地址的語句之前。
(1)href 屬性
href屬性指定了文檔的基礎URL地址,該屬性在<base>標記中是必須存在的。
例如:如果希望將文檔的基礎URL定義為“www.abc.com”,則可以使用如下語句:
<base href = "www.abc.com"> 當定義了基礎URL地址之后,文檔中所有引用的URL地址都從該基礎URL地址開始,例如,對于上面的語句,如果文檔中一個超級鏈接指向gsl/welcome.htm,則它實際上指向的是如下URL地址:www.abc.com/gsl/welcome.htm
(2)target
target屬性同框架一起使用,它定義了當文檔中的鏈接被點擊后,在哪一個框架中展開頁面。如果文檔中超級鏈接沒有明確指定展開頁面的目標框架集,則就使用這里定義的地址代替。常用的target的屬性值有:
_blank,表明在新窗口中打開鏈接指向的頁面。
_self,在當前文檔的框架中打開頁面。
_parent,在當前文檔的父窗口中打開頁面。
_top,在鏈接所在的完整窗口中展開頁面。
1、增加一個虛似硬盤
如果是在vmware里面安裝的windows系統,添加個硬盤很容易,
(1)先打開要添加硬盤的虛擬系統(不要啟動該系統),選擇虛擬機菜單---設置-----選添加,
(2)然后在彈出添加硬件向導窗口中------選擇硬盤-------一路next就好了,后面的操作和新建一個虛擬機的時候配置硬盤是一樣的。
(3)添加了新的硬盤后,啟動windows進到系統中,在控制面板中找“管理工具”->“計算機管理”,然后選“磁盤管理”,添加新磁盤就好了。
其實很簡單的..如果想繼續給VMware增加硬盤的話,重復上述動作。
2、改變原虛擬硬盤的大小
界面中并沒有提供增加硬盤容量的方法。
只能在命令行形式下執行。
安裝所在盤的c:\Program Files\VMware\VMware Workstation下有一個vmware-vdiskmanager.exe,就是它。
命令參數如下:
------------------------------------------------------------------
Usage: vmware-vdiskmanager.exe OPTIONS <disk-name> | <mount-point>
Offline disk manipulation utility
Options:
-c : create disk; need to specify other create options
-d : defragment the specified virtual disk
-k : shrink the specified virtual disk
-n <source-disk> : rename the specified virtual disk; need to
specify destination disk-name
-p : prepare the mounted virtual disk specified by
the drive-letter for shrinking
-q : do not log messages
-r <source-disk> : convert the specified disk; need to specify
destination disk-type
-x <new-capacity> : expand the disk to the specified capacity
Additional options for create and convert:
-a <adapter> : (for use with -c only) adapter type (ide, buslogic o
r lsilogic)
-s <size> : capacity of the virtual disk
-t <disk-type> : disk type id
Disk types:
0 : single growable virtual disk
1 : growable virtual disk split in 2Gb files
2 : preallocated virtual disk
3 : preallocated virtual disk split in 2Gb files
The capacity can be specified in sectors, Kb, Mb or Gb.
The acceptable ranges:
ide adapter : [100.0Mb, 950.0Gb]
scsi adapter: [100.0Mb, 950.0Gb]
ex 1: vmware-vdiskmanager.exe -c -s 850Mb -a ide -t 0 myIdeDisk.vmdk
ex 2: vmware-vdiskmanager.exe -d myDisk.vmdk
ex 3: vmware-vdiskmanager.exe -r sourceDisk.vmdk -t 0 destinationDisk.vm
dk
ex 4: vmware-vdiskmanager.exe -x 36Gb myDisk.vmdk
ex 5: vmware-vdiskmanager.exe -n sourceName.vmdk destinationName.vmdk
ex 6: vmware-vdiskmanager.exe -k myDisk.vmdk
ex 7: vmware-vdiskmanager.exe -p <mount-point>
(A virtual disk first needs to be mounted at <mount-point>)
-----------------------------------------------------------------
其中的-x參數就是用來擴容的……
如這個:vmware-vdiskmanager.exe -x 36Gb myDisk.vmdk
解析: vmware-vdiskmanager.exe -x 大小 虛擬硬盤文件
-------------------------------------------------------
我的執行過程:
D:\Program files\VMware\VMware Workstation>vmware-vdiskmanager.exe -x 12GB "F:\Windows Server 2003 Enterprise Edition\Windows Server 2003 Enterprise Edition.vmdk"
==================================================================
總結一下:
1。文件名應該用雙引號括起來。
2。vmdk文件名要連同路徑。
3。GB,MB,別忘了B。
什么是金融債券?金融債券有哪些種類?
金融債券是由銀行和非銀行金融機構發行的
債券。在英、美等歐美國家,金融機構發行的債券歸類于
公司債券。在我國及日本等國家,金融機構發行的債券稱為金融債券。 金融債券能夠較有效地解決銀行等金融機構的資金來源不足和期限不匹配的矛盾。
一般來說,銀行等金融機構的資金有三個來源,即吸收存款、向其他機構借款和發行債券。
存款資金的特點之一,是在經濟發生動蕩的時候,易發生儲戶爭相提款的現象,從而造成資金來源不穩定;
向其他商業銀行或中央銀行借款所得的資金主要是短期資金,而金融機構往往需要進行一些期限較長的投融資,這樣就出現了資金來源和資金運用在期限上的矛盾,發行金融債券比較有效地解決了這個矛盾。債券在到期之前一般不能提前兌換,只能在市場上轉讓,從而保證了所籌集資金的穩定性。同時,金融機構發行債券時可以靈活規定期限,比如為了一些長期項目投資,可以發行期限較長的債券。因此,發行金融債券可以使金融機構籌措到穩定且期限靈活的資金,從而有利于優化資產結構,擴大長期投資業務。由于銀行等金融機構在一國經濟中占有較特殊的地位,政府對它們的運營又有嚴格的監管,因此,金融債券的資信通常高于其他非金融機構債券,違約風險相對較小,具有較高的安全性。所以,金融債券的利率通常低于。般的企業債券,但高于風險更小的國債和銀行儲蓄存款利率。
按不同標準,金融債券可以劃分為很多種類。最常見的分類有以下兩種:
(1) 根據利息的支付方式 金融債券可分為附息金融債券和貼現全融債券。如果金融債券上附有多期息票,發行人定期支付利息,則稱為附息金融債券;如果金融債券是以低于面值的價格貼現發行,到期按面值還本付息,利息為發行價與面佰的差額,則稱為貼現債券。比如票面金額為1000元,期限為1年的貼現金融債券,發行價格為900元,1年到期時支付給投資者1000元,那么利息收入就是100元,而實際年利率就是11.11%(即<1 000-900>/900* 100%〕。按照國外通常的做法,貼現金融債券的利息收入要征稅,并且不能在證券交易所上市交易。
(2) 根據發行條件 金融債券可分為普通金融債券和累進利息金融債券。普通金融債券按面值發行,到期一次還本付息,期限一般是1年、2年和3年。普通金融債券類似于銀行的定期存款,只是利率高些。累進利息金融債券的利率不固定,在不同的時間段有不同的利率,并且一年比一年高,也就是說,債券的利率隨著債券期限的增加累進,比如面值1000無、期限為5年的金融債券,第回年利率為9%,第二年利率為10%,第三年為11%,第四年為12%,第五年為13%。投資者可在第一年至第五年之間隨時去銀行兌付,并獲得規定的利息。
此外,金融債券也可以像
企業債券一樣,根據期限的長短劃分為短期債券、中期債券和長期債券;根據是否記名劃分為記名債券和不記名債券;根據擔保情況劃分為信用債券和擔保債券;根據可否提前贖回劃分為可提前贖回債券和不可提前贖回債券;根據債券票面利率是否變動劃分為
固定利率債券、
浮動利率債券和
累進利率債券;根據發行人是否給予投資者選擇權劃分為附有選擇權的債券和不附有選擇權的偵券等。
學習資源:
http://www.cnblogs.com/jimmyzhang/archive/2007/10/24/936151.html (花上1-2個小時仔細學習,然后反復實踐,能夠很快上手)
正則表達式工具:
我首推RegexBuddy了。下面這個地址里有RegexBuddy3.2.1完整版的下載地址(如果你仔細瀏覽這個網站,會發現此人是一個正則表達式狂熱分子):
http://iregex.org/blog/regexbuddy321.html
1、<script language="javascript">
window.onbeforeunload = function()
{
if(((event.clientX > document.body.clientWidth - 43) && (event.clientY < 23)) || event.altKey) {
window.event.returnValue = '關閉。';
}
}
</script>
2、<script language="javascript">
window.onbeforeunload = function()
{
var n = window.event.screenX - window.screenLeft;
var b = n > document.documentElement.scrollWidth-20;
if(b && window.event.clientY < 0 || window.event.altKey)
{
alert("是關閉而非刷新");
window.open(this.location);
//return false;
//window.event.returnValue = ""; }
}
</script>
本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/ajaxchen_615/archive/2009/07/06/4325917.aspx
如果你的頁面對IE7兼容沒有問題,又不想大量修改現有代碼,同時又能在IE8中正常使用,微軟聲稱,開發商僅需要在目前兼容IE7的網站上添加一行代碼即可解決問題,此代碼如下:
CODE:
<meta http-equiv="x-ua-compatible" content="ie=7" />
從今天開始學習.net開發,java開發工作暫放一放,不過在學習.net的過程中,會結合java對比,在學習新知識的同時也鞏固和復習一下java的知識,在學習中提升,在學習中成長,加油!
1.對象和屬性
對象是一種復核數據類型,它們將多個數據值幾種在一個單元中,而且允許使用名字來存取這些值,即對象是一個無序的屬性集合,這個屬性都有自己的名字和值,存儲在對象中的以命名的值可以是數字和字符串這樣的原始值,也可以是對象。
2.對象的創建
對象是由運算符new來創建的,在這個運算符之后必須有用于初始化對象的構造函數名。
創建一個空對象(即沒有屬性的對象)
var o = new Object();
js還支持內部構造函數,它們以另一種簡潔的方式初始化新創建的對象
var now = new Date();
var new_year = new Date(2009,09,19);
3.屬性的設置和查詢
4.屬性的枚舉
for/in循環列出的屬性并沒有特定順序,而且它只能枚舉出所有用戶定義的屬性,但是卻不能枚舉出那些預定義的屬性或方法,并且它可以
枚舉出被設為undefined的屬性,但是它不能列出被delete刪除的屬性。
5.未定義的屬性
如果要讀取一個不存在屬性的值,那么得到的結果是一個特殊的js值,undefined
可以使用delete來刪除一個對象的屬性,注意:刪除一個屬性并不僅僅是把該屬性設置為undefined,而是真正從對象中移除了該屬性。
6.構造函數
它由new運算符調用,傳遞給它的是一個新創建的空對象引用,將該引用作為關鍵字this的值,而且它還要對新創建的對象進行適當的初始化。
注意:構造函數如何使用它的參數來初始化this關鍵字所引用的對象的屬性,記住,構造函數只是初始化了特定的對象,但并不返回這個對象。
構造函數通常沒有返回值,他們只是初始化由this值傳遞進來的對象,并且什么也不返回..但是,構造函數可以返回一個對象值,如果這樣做,被返回的對象就成了new表達式的值了,在這種情況下,
this值所引用的對象就被丟棄了。
7.方法
方法有一個非常重要的屬性,即在方法主體內部,關鍵字this的值變成了調用該方法的對象。
方法和函數的區別,其實他們沒有什么技術上的差別,真正的區別存在于設計和目的上,方法是用來對this對象進行操作的,而函數通常是獨立的,并不需要使用this對象。
8.原型對象和繼承
js對象都“繼承”原型對象的屬性,每個對象都有原型對象,原型對象的所有屬性是以它為原型的對象的屬性,也就是說,每個對象都繼承原型對象的所有屬性,
一個對象的原型是有創建并初始化該對象的構造函數定義的,js中的所有函數都有prototype屬性,它引用一個對象,雖然原型對象初始化時是空的,但是你在其中定義的任何屬性都會被構造函數創建
的所有對象繼承。
構造函數定義了對象的類,并初始化了類中狀態變量的屬性,因為原型對象和構造函數關聯在一起,所以類的每個成員都從原型對象繼承了相同的屬性,這說明原型對象是存放方法和其他常量屬性的理
想場所。
繼承是在查詢一個屬性值時自動發生的,屬性并非從原型對象賦值到新的對象的,他們只不過看起來像是那些對象的屬性,有兩點重要的含義,一是:使用原型對象可以大量減少每個對象對內存的需求
量,因為對象可以繼承許多屬性;而且即使屬性在對象被創建之后才添加屬性到它的原型對象中,對象也能夠繼承這些屬性。
屬性的繼承只發生在讀屬性值時,而在寫屬性值時不會發生。
因為原型對象的屬性被一個類的所有對象共享,所以通常只用他們來定義類中所有對象的相同的屬性,這使得原型對象適合于方法定義,另外原型對象還適合于具有常量的屬性的定義,
a.原型和內部類
不只是用戶定義的類有原型對象,像內部類同樣具有原型對象,也可以給他們賦值,
e.g String.prototype.endsWith = function(o){
return (e == this,charAt(this.length-1));
}
9.面向對象的js
在面向對象的程序設計中,共有的概念是強類型和支持以類為基礎的繼承機制,根據這個評判標準,就可以證明js不是面向對象語言。
js對象可以具有大量的屬性,而且還可以動態的將這些屬性添加到對象中,這是對面對象c++和java做不到的,
雖然js沒有類的概念,但是它用構造函數和原型對象模擬了類。
js和以類為基礎的面向對象語言中,同一個類可以具有多個對象,對象是它所屬的那個類的實力,所以任何類都可以有多個實例,js中的命名延勇了java中的命名約定,即命名類時以大寫字母開頭,命名對象時以小寫字母開頭,類幫助我們區分代碼中的類和對象。
實例屬性
每個對象都有它自己單據的實力屬性的副本,為了模擬面向對象的程序設計語言,js中的實例屬性是那些在對象中用構造函數創建的或初始化的屬性。
實例方法
實例方法和實例數據非常的相似,實例方法是由特定對象或實例調用的,實例方法使用了關鍵字this來引用他們要操作的對象或實例,但是和實例屬性不同額一點是每個實例方法都是由類的所有實例共享的,在js中,給類定義一個實例方法,是通過把構造函數的原型對象中的一個屬性設置為函數值類實現的,這樣,由那個構造函數創建的所有對象都會共享一個以繼承的對函數的引用,而且使用上面素數的方法調用語法就能夠調用這個函數。
類屬性
類屬性是一個與類相關聯的變量,而不是和類的每個實例相關聯的變量,每個類屬性只有一個副本,它是通過類存取的,可以簡單的定義了構造函數自身的一個屬性來定義類屬性
類方法
類方法是一個與類關聯在一起的方法,而不是和類的實例關聯在一起的方法,要調用類方法,就必須使用類本身,而不是使用類的特定實例。由于類方法不能通過一個特定對象調用,所以使用關鍵字this對它來說沒有意義,和類屬性一樣,類方法是全局性的,
超類和子類
面向對象語言中有類層次的概念,每個類都有一個超類,他們從超類中繼承屬性和方法,類還可以被擴展,或者說子類化,這樣其他子類就能繼承它的行為,js中繼承是以原型為基礎的,而不是以類基礎的繼承機制,但是我們仍舊能夠總結出累世的類層次圖,在js中,類Object是最通用的類,其他所有類都是專用化了的版本,或者說的是Object的子類,另一種解釋方法是Object是所有內部類的超類,所有類都繼承了Object的基本方法。
舉例說明:
類Complex的對象就繼承了Complex.prototype對象的屬性,而后者又繼承了Object.prototype的屬性,由此可以推出,對象Complex繼承了兩個對象的屬性,在Complex對象中查詢某個屬性時,首先查詢的是這個對象本身,如果在這個對喜愛那個中沒有發現要查詢的屬性,就查詢Complex.prototype對象,最后,如果在那個對象中還沒有最后按到要查詢的屬性,就查詢Object.prototype對象,注意類層次關系中的屬性隱藏。參考P153
10.作為關聯數組的對象
運算符“.”類存取一個對象屬性,而數組更常用的存取書香運算賦是[],下面的兩行代碼是等價的:
obj.property ====== obj["property"],他們的語法區別是,前者的屬性名是標識符,后者的屬性名卻是一個字符串,
在c、c++、java和其他類似的強類型語言中,一個對象的屬性數是固定,而且必須預定義這些屬性的名字,由于js是一種弱類型語言,它并沒有采用這一規則,所以在用js編寫的程序,可以為對象創建任意數目的屬性,但是當你采用“.”運算符來存取一個對象的屬性時,屬性名時是用標識符表示的,而js程序性中,標識符必須被逐字的輸入,他們不是一種數據類型,因此程序不能對他們進行操作。
constructor屬性
每個對象都有constructor屬性,它引用的是用來初始化該對象的構造函數。但是并不是所有的對象都具有自己唯一的constructor屬性,相反,如果這個屬性是從原型對象繼承來的。
js會為我們定義的每一個構造函數都創建一個原型對象,并且將那個對象賦給構造函數的prototype屬性。但是之前沒有說明原型對象初始時是非空的,在原型對象創建之初,它包括一個constructor屬性, 用來引用構造函數,也就是說,如果有一個函數f,那么屬性f.prototype.constructor就總是等于f的。
由于構造函數定義了一個對象的類,所以屬性construtor在確定給定對象的類型時是一個功能強大的工具。
并不能保證constructor屬性總是存在的,例如,一個類的創建者可以用一個全新的對象來替換構造函數的原型對象,而新對象可能不具有有效的constructor屬性。
toString()方法
toLocaleString()方法
valueOf()方法
js需要將一個對象轉化成字符創之外的原型類型時,就調用它,這個函數返回的是能代表關鍵字this所引用的對象的值的數據。
hasOwnProperty()
如果兌現局部定義了一個非繼承的屬性,屬性名是由一個字符串實際參數指定的,那么該方法就返回true,否則,它將返回false。
propertyIsEnumerable()
如果對象定義了一個屬性,屬性名是由一個字符串實際參數指定的,而且該屬性可以用for/in循環枚舉出來,那么該方法返回true,否則返回false。
注意:該方法只考慮對象直接定義的屬性,而不考慮繼承的屬性,因為返回false可能是因為那個屬性是不可枚舉的,也可能是因為它雖然是可以枚舉的,但卻是個繼承的屬性。
怎么判斷一個屬性是可枚舉的?
isPrototypeOf()
如果調用對象是實際參數指定的對象的原型對象,該方法返回true,否則返回false,該方法的用途和對象的constructoe屬性相似。
1.函數
注意:定義函數時可以使用個數可變的參數,而且函數既可以有return語句,也可以沒有return語句;如果函數不包含return語句,它就只執行函數體中的每條語句,然后返回給調用者undefined。
使用運算符typeof來檢測參數的數據類型,使用if(!param)return;來判斷是否存在該參數,因為js是一種無類型語言,所以你不能給函數的參數制定一個數據類型,而且js也不會檢測傳遞的數據是不是那個函數所需要的類型,如果參數很重要時,就使用前面介紹的運算符進行檢測。
不可變參數js的處理:如果傳遞的參數比函數需要的個數多,那么多余的幾個參數被忽略掉,如果傳遞的參數比函數需要的個數少,那么多余的幾個參數就會被賦予undefined,在大多數情況下,這回使得函數產生錯誤。
2.嵌套函數
a,函數定義中可以嵌套其他函數的定義,但是只能在在頂層全局代碼和頂層函數代碼中,不能出現在循環或條件語句中,并且這些限制只應用于由function語句聲明的函數,函數直接量可以出現在任何js表達式中。
3.Function()構造函數
可以使用Function()構造函數和new運算符動態地定義函數, var f = new Function("x","y","return x*y;");它等價于:function f(x,y){return x*y;}
Function構造函數可以接受任意多個字符串參數,它的最后一個參數是函數的主體,其中可以包含任何js語句,語句之間用分號分隔。由于傳遞給構造函數Function()的參數中沒有一個用于說明它要創建的函數名,用Function()構造函數創建的未命名函數有時被稱作為“匿名函數”。
Function()函數存在的意義:因為Function()構造函數允許我們動態地建立和編譯一個函數,它不會將我們限制在function語句預編譯的函數體中;另一個原因是它能將函數定義為js表達式的一部分,而不是將其定義為一個語句;缺點是:這樣做每次調用一個函數時,Function()構造函數都要對它進行編譯,
4.函數直接量
函數直接量是一個表達式,它可以定義匿名函數。
function f(x){return x*x;} //function語句
var f = new Function("x","return x*x;"); //Function()構造函數
var f = function(X){return x*x;}; //函數直接量
雖然函數直接量創建的是未命名函數,但是它的語法也規定它可以指定函數名,這在編寫調用自身的遞歸函數時特別的有用,e.g
var f= function fact(x){if(x<=1)return 1; else return x*fact(x-1);}
總結:function()函數可以任意的使用,具有通用性,Function()函數和函數直接量具有很多的相似性,他們都是未命名函數(函數直接量可以有函數名,尤其是在子調用函數中),函數直接量有個重要的有點,函數直接量只被解析和編譯一次,而作為字符串傳遞給Function()構造函數的js代碼則在每次調用構造函數時只需要被解析和編譯一次。
函數最重要的特性就是他們能夠被定義和調用,但是在js中函數并不只是一種語法,還可以是數據,可以把函數賦給變量、存儲在對象的屬性中或存儲在數組的元素中,傳遞給函數。其實函數名并沒有什么實際意義,它只是保存函數的變量的名字,可以將這個函數賦給其他的變量,它仍然以相同的方式起作用,
e.g function square(x){x*x;}
var a = square(4);
var b = square;//這種情況下b引用的函數和square的作用相同
var c = b(5);
除了賦給全局變量之外,還可以將函數賦給對象的屬性,這是稱函數為方法;也可以賦給數組元素。
e.g
var a = new Object; var a = new Object();
a.square = new Function("x","return x*x";);
y = o.square(16);
e.g
var a = new Array(3);
a[0] = function(x){return x*x;};
a[1] = 20;
a[2] = a[0](a[1]);
除這些之外,如何將函數作為參數傳遞給其他函數,
e.g
function add(x,y){return x+y;}
function subtract(x,y){return x-y;}
function multiply(x,y){return x*y;}
function dibide(x,y){return x/y;}
function operate(operator,operand1,operand2){
return operator(operand1,operand2);
}
var i = operate(add,operate(add,2,3),operate(multiply,4,5));
var operators = new Object();
operators["add"] = function(x,y){return x+y;}
operators["multiply"] = function(x,y){return x*y;}
operators["divide"] = function(x,y){return x/y;}
operators["pow"] = Math.pow;
function operate2(op_name,operand1,operand2){
if(operators[op_name] == null)return "unknow operator";
else return operators[op_name](operand1,operand2);
}
var j = operate2('add',"hello",operate2("add","","world"));
var k = operate2('pow',10,2);
5.函數的作用域,調用對象
函數的作用域中除了全局變量、函數內部的局部變量和形式參數外,函數還定義了一個特殊屬性,
arguments,這個屬性應用了另外一個特殊的對象-----Arguments對象,因為arguments屬性是調用對象的一個屬性,所以它的狀態和局部變量以及函數的形式參數是相同的。
所以arguments標識符被看做是保留字,不能將它作為變量名或形式參數名。
6.Arguments對象
arguments它具有特殊的意義,是調用對象的一個特殊屬性,用來引用Arguments對象,Arguments對象就像數組,可以按照數字獲取傳遞給函數的參數值,但是它并非真正的Array對象。
arguments具有length屬性,
可以使用arguments來檢測調用函數使用了正確數目的實際參數,
注意:arguments并非真正的數組,它是一個Arguments對象,Arguments對象有一個非同尋常的特征,當函數具有命名了的參數時,Arguments對象的數組元素是存放函數參數的局部變量的同義詞。
e.g
function(x){
alert(x); //顯示參數的初始值
arguments[0] = null;//改變數組預算也會改變x
alert(x); //現在顯示為“null”
除了數組元素,Arguments對象還定義了callee屬性,用來引用當前正在執行的函數,這對未命名的函數調用自身非常有用。
e.g
function(x){
if(x<-1)return 1;
return x*arguments.callee(x-1);
}
7.函數的屬性和方法
由于函數是對象,所以它具有數據和方法。
函數的length屬性
函數的屬性length和arguments屬性的length不同,arguments數組的length屬性指定了傳遞給該函數的實際參數數目,并且arguments屬性的length只在函數內部起作用,而函數自身的length屬性它是只讀的,返回的是函數需要的實際參數的數目,并且函數的屬性length函數體的內部和外部都在是有效的。
函數的prototype屬性
每個函數都有一個prototype屬性,它引用的是預定義的原型對象,原型對象在使用new運算符把函數作為構造函數時起作用。
函數自定義屬性
有時候定義全局變量比較亂,可以通過自定義函數屬性來解決
函數的apply()和call()方法
他們的第一個參數都是要調用的函數的對象,在函數體內這一參數是關鍵字this的值,call()的剩余參數是傳遞給要調用的函數的值,apply()的剩余參數是由數組指定的參數。
寫出漂亮代碼的七種方法
首先我想說明我本文闡述的是純粹從美學的角度來寫出代碼,而非技術、邏輯等。以下為寫出漂亮代碼的七種方法:
1, 盡快結束 if語句
例如下面這個JavaScript語句,看起來就很恐怖:
- 1 function findShape(flags, point, attribute, list) {
-
- 2 if(!findShapePoints(flags, point, attribute)) {
-
- 3 if(!doFindShapePoints(flags, point, attribute)) {
-
- 4 if(!findInShape(flags, point, attribute)) {
-
- 5 if(!findFromGuide(flags,point) {
-
- 6 if(list.count() > 0 && flags == 1) {
-
- 7 doSomething();
-
- 8 }
-
- 9 }
-
- 10 }
-
- 11 }
-
- 12 }
-
- 13 }
1 function findShape(flags, point, attribute, list) {
2 if(!findShapePoints(flags, point, attribute)) {
3 if(!doFindShapePoints(flags, point, attribute)) {
4 if(!findInShape(flags, point, attribute)) {
5 if(!findFromGuide(flags,point) {
6 if(list.count() > 0 && flags == 1) {
7 doSomething();
8 }
9 }
10 }
11 }
12 }
13 }
但如果這么寫就好看得多:
- 1 function findShape(flags, point, attribute, list) {
-
- 2 if(findShapePoints(flags, point, attribute)) {
-
- 3 return;
-
- 4 }
-
- 5
-
- 6 if(doFindShapePoints(flags, point, attribute)) {
-
- 7 return;
-
- 8 }
-
- 9
-
- 10 if(findInShape(flags, point, attribute)) {
-
- 11 return;
-
- 12 }
-
- 13
-
- 14 if(findFromGuide(flags,point) {
-
- 15 return;
-
- 16 }
-
- 17
-
- 18 if (!(list.count() > 0 && flags == 1)) {
-
- 19 return;
-
- 20 }
-
- 21
-
- 22 doSomething();
-
- 23
-
- 24 }
1 function findShape(flags, point, attribute, list) {
2 if(findShapePoints(flags, point, attribute)) {
3 return;
4 }
5
6 if(doFindShapePoints(flags, point, attribute)) {
7 return;
8 }
9
10 if(findInShape(flags, point, attribute)) {
11 return;
12 }
13
14 if(findFromGuide(flags,point) {
15 return;
16 }
17
18 if (!(list.count() > 0 && flags == 1)) {
19 return;
20 }
21
22 doSomething();
23
24 }
你可能會很不喜歡第二種的表述方式,但反映出了迅速返回if值的思想,也可以理解為:避免不必要的else陳述。
2, 如果只是簡單的布爾運算(邏輯運算),不要使用if語句
例如:
- 1 function isStringEmpty(str){
-
- 2 if(str === "") {
-
- 3 return true;
-
- 4 }
-
- 5 else {
-
- 6 return false;
-
- 7 }
-
- 8 }
1 function isStringEmpty(str){
2 if(str === "") {
3 return true;
4 }
5 else {
6 return false;
7 }
8 }
可以寫為:
- 1 function isStringEmpty(str){
-
- 2 return (str === "");
-
- 3 }
1 function isStringEmpty(str){
2 return (str === "");
3 }
3, 使用空白,這是免費的
例如:
1
- function getSomeAngle() {
-
- 2
-
- 3 radAngle1 = Math.atan(slope(center, point1));
-
- 4 radAngle2 = Math.atan(slope(center, point2));
-
- 5 firstAngle = getStartAngle(radAngle1, point1, center);
-
- 6 secondAngle = getStartAngle(radAngle2, point2, center);
-
- 7 radAngle1 = degreesToRadians(firstAngle);
-
- 8 radAngle2 = degreesToRadians(secondAngle);
-
- 9 baseRadius = distance(point, center);
-
- 10 radius = baseRadius + (lines * y);
-
- 11 p1["x"] = roundValue(radius * Math.cos(radAngle1) + center["x"]);
-
- 12 p1["y"] = roundValue(radius * Math.sin(radAngle1) + center["y"]);
-
- 13 pt2["x"] = roundValue(radius * Math.cos(radAngle2) + center["y"]);
-
- 14 pt2["y"] = roundValue(radius * Math.sin(radAngle2) + center["y");
-
- 15
-
- 16 }
function getSomeAngle() {
2 // Some code here then
3 radAngle1 = Math.atan(slope(center, point1));
4 radAngle2 = Math.atan(slope(center, point2));
5 firstAngle = getStartAngle(radAngle1, point1, center);
6 secondAngle = getStartAngle(radAngle2, point2, center);
7 radAngle1 = degreesToRadians(firstAngle);
8 radAngle2 = degreesToRadians(secondAngle);
9 baseRadius = distance(point, center);
10 radius = baseRadius + (lines * y);
11 p1["x"] = roundValue(radius * Math.cos(radAngle1) + center["x"]);
12 p1["y"] = roundValue(radius * Math.sin(radAngle1) + center["y"]);
13 pt2["x"] = roundValue(radius * Math.cos(radAngle2) + center["y"]);
14 pt2["y"] = roundValue(radius * Math.sin(radAngle2) + center["y");
15 // Now some more code
16 }
很多開發者不愿意使用空白,就好像這要收費一樣。我在此并非刻意地添加空白,粗魯地打斷代碼的連貫性。在實際編寫代碼的過程中,會很容易地發現在什么地方加入空白,這不但美觀而且讓讀者易懂,如下:
- 1 function getSomeAngle() {
-
- 2
-
- 3 radAngle1 = Math.atan(slope(center, point1));
-
- 4 radAngle2 = Math.atan(slope(center, point2));
-
- 5
-
- 6 firstAngle = getStartAngle(radAngle1, point1, center);
-
- 7 secondAngle = getStartAngle(radAngle2, point2, center);
-
- 8
-
- 9 radAngle1 = degreesToRadians(firstAngle);
-
- 10 radAngle2 = degreesToRadians(secondAngle);
-
- 11
-
- 12 baseRadius = distance(point, center);
-
- 13 radius = baseRadius + (lines * y);
-
- 14
-
- 15 p1["x"] = roundValue(radius * Math.cos(radAngle1) + center["x"]);
-
- 16 p1["y"] = roundValue(radius * Math.sin(radAngle1) + center["y"]);
-
- 17
-
- 18 pt2["x"] = roundValue(radius * Math.cos(radAngle2) + center["y"]);
-
- 19 pt2["y"] = roundValue(radius * Math.sin(radAngle2) + center["y");
-
- 20
-
- 21 }
-
-
-
- 4, 不要使用無謂的注釋
-
- 無謂的注釋讓人費神,這實在很討厭。不要標出很明顯的注釋。在以下的例子中,每個人都知道代碼表達的是“students id”,因而沒必要標出。
-
- 1 function existsStudent(id, list) {
-
- 2 for(i = 0; i < list.length; i++) {
-
- 3 student = list[i];
-
- 4
-
- 5
-
- 6 thisId = student.getId();
-
- 7
-
- 8 if(thisId === id) {
-
- 9 return true;
-
- 10 }
-
- 11 }
-
- 12 return false;
-
- 13 }
1 function getSomeAngle() {
2 // Some code here then
3 radAngle1 = Math.atan(slope(center, point1));
4 radAngle2 = Math.atan(slope(center, point2));
5
6 firstAngle = getStartAngle(radAngle1, point1, center);
7 secondAngle = getStartAngle(radAngle2, point2, center);
8
9 radAngle1 = degreesToRadians(firstAngle);
10 radAngle2 = degreesToRadians(secondAngle);
11
12 baseRadius = distance(point, center);
13 radius = baseRadius + (lines * y);
14
15 p1["x"] = roundValue(radius * Math.cos(radAngle1) + center["x"]);
16 p1["y"] = roundValue(radius * Math.sin(radAngle1) + center["y"]);
17
18 pt2["x"] = roundValue(radius * Math.cos(radAngle2) + center["y"]);
19 pt2["y"] = roundValue(radius * Math.sin(radAngle2) + center["y");
20 // Now some more code
21 }
4, 不要使用無謂的注釋
無謂的注釋讓人費神,這實在很討厭。不要標出很明顯的注釋。在以下的例子中,每個人都知道代碼表達的是“students id”,因而沒必要標出。
1 function existsStudent(id, list) {
2 for(i = 0; i < list.length; i++) {
3 student = list[i];
4
5 // Get the student's id
6 thisId = student.getId();
7
8 if(thisId === id) {
9 return true;
10 }
11 }
12 return false;
13 }
5, 不要在源文件中留下已經刪除的代碼,哪怕你標注了
如果你使用了版本控制,那么你就可以輕松地找回前一個版本的代碼。如果別人大費周折地讀了你的代碼,卻發現是要刪除的代碼,這實在太恨人了。
//function thisReallyHandyFunction() {
// someMagic();
// someMoreMagic();
// magicNumber = evenMoreMagic();
// return magicNumber;
//}
6,不要有太長的代碼
看太長的代碼實在太費勁,尤其是代碼本身的功能又很小。如下:
- 1 public static EnumMap<Category, IntPair> getGroupCategoryDistribution(EnumMap<Category, Integer> sizes, int groups) {
-
- 2 EnumMap<Category, IntPair> categoryGroupCounts = new EnumMap<Category,IntPair>(Category.class);
-
- 3
-
- 4 for(Category cat : Category.values()) {
-
- 5 categoryGroupCounts.put(cat, getCategoryDistribution(sizes.get(cat), groups));
-
- 6 }
1 public static EnumMap<Category, IntPair> getGroupCategoryDistribution(EnumMap<Category, Integer> sizes, int groups) {
2 EnumMap<Category, IntPair> categoryGroupCounts = new EnumMap<Category,IntPair>(Category.class);
3
4 for(Category cat : Category.values()) {
5 categoryGroupCounts.put(cat, getCategoryDistribution(sizes.get(cat), groups));
6 }
#
我并不是說非要堅持70個字符以內,但是一個比較理想的長度是控制在120個字符內。如果你把代碼發布在互聯網上,用戶讀起來就很困難。
7,不要在一個功能(或者函數內)有太多代碼行
我的一個老同事曾經說Visual C++很臭,因為它不允許你在一個函數內擁有超過10,000行代碼。我記不清代碼行數的上限,不知道他說的是否正確,但我很不贊成他的觀點。如果一個函數超過了50行,看起來有多費勁你知道么,還有沒完沒了的if循環,而且你還的滾動鼠標前后對照這段代碼。對我而言,超過35行的代碼理解起來就很困難了。我的建議是超過這個數字就把一個函數代碼分割成兩個。
本篇文章為在工作中使用JAVA反射的經驗總結,也可以說是一些小技巧,以后學會新的小技巧,會不斷更新。
在開始之前,我先定義一個測試類Student,代碼如下:
- package chb.test.reflect;
-
- public class Student {
- private int age;
- private String name;
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
-
- public static void hi(int age,String name){
- System.out.println("大家好,我叫"+name+",今年"+age+"歲");
- }
- }<PRE></PRE>
package chb.test.reflect;
public class Student {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public static void hi(int age,String name){
System.out.println("大家好,我叫"+name+",今年"+age+"歲");
}
}
一、JAVA反射的常規使用步驟
反射調用一般分為3個步驟:
-
得到要調用類的class
-
得到要調用的類中的方法(Method)
-
方法調用(invoke)
代碼示例:
- Class cls = Class.forName("chb.test.reflect.Student");
- Method m = cls.getDeclaredMethod("hi",new Class[]{int.class,String.class});
- m.invoke(cls.newInstance(),20,"chb");<PRE></PRE>
Class cls = Class.forName("chb.test.reflect.Student");
Method m = cls.getDeclaredMethod("hi",new Class[]{int.class,String.class});
m.invoke(cls.newInstance(),20,"chb");
二、方法調用中的參數類型
在方法調用中,參數類型必須正確,這里需要注意的是不能使用包裝類替換基本類型,比如不能使用Integer.class代替int.class。
如我要調用Student的setAge方法,下面的調用是正確的:
- Class cls = Class.forName("chb.test.reflect.Student");
- Method setMethod = cls.getDeclaredMethod("setAge",int.class);
- setMethod.invoke(cls.newInstance(), 15);<PRE></PRE>
Class cls = Class.forName("chb.test.reflect.Student");
Method setMethod = cls.getDeclaredMethod("setAge",int.class);
setMethod.invoke(cls.newInstance(), 15);
而如果我們用Integer.class替代int.class就會出錯,如:
- Class cls = Class.forName("chb.test.reflect.Student");
- Method setMethod = cls.getDeclaredMethod("setAge",Integer.class);
- setMethod.invoke(cls.newInstance(), 15);<PRE></PRE>
Class cls = Class.forName("chb.test.reflect.Student");
Method setMethod = cls.getDeclaredMethod("setAge",Integer.class);
setMethod.invoke(cls.newInstance(), 15);
jvm會報出如下異常:
- java.lang.NoSuchMethodException: chb.test.reflect.Student.setAge(java.lang.Integer)
- at java.lang.Class.getDeclaredMethod(Unknown Source)
- at chb.test.reflect.TestClass.testReflect(TestClass.java:23)<PRE></PRE>
java.lang.NoSuchMethodException: chb.test.reflect.Student.setAge(java.lang.Integer)
at java.lang.Class.getDeclaredMethod(Unknown Source)
at chb.test.reflect.TestClass.testReflect(TestClass.java:23)
三、static方法的反射調用
static方法調用時,不必得到對象示例,如下:
- Class cls = Class.forName("chb.test.reflect.Student");
- Method staticMethod = cls.getDeclaredMethod("hi",int.class,String.class);
- staticMethod.invoke(cls,20,"chb");
-
Class cls = Class.forName("chb.test.reflect.Student");
Method staticMethod = cls.getDeclaredMethod("hi",int.class,String.class);
staticMethod.invoke(cls,20,"chb");//這里不需要newInstance
//staticMethod.invoke(cls.newInstance(),20,"chb");
四、private的成員變量賦值
如果直接通過反射給類的private成員變量賦值,是不允許的,這時我們可以通過setAccessible方法解決。代碼示例:
- Class cls = Class.forName("chb.test.reflect.Student");
- Object student = cls.newInstance();
- Field field = cls.getDeclaredField("age");
- field.set(student, 10);
- System.out.println(field.get(student));<PRE></PRE>
Class cls = Class.forName("chb.test.reflect.Student");
Object student = cls.newInstance();//得到一個實例
Field field = cls.getDeclaredField("age");
field.set(student, 10);
System.out.println(field.get(student));
運行如上代碼,系統會報出如下異常:
- java.lang.IllegalAccessException: Class chb.test.reflect.TestClass can not access a member of class chb.test.reflect.Student with modifiers "private"
- at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
- at java.lang.reflect.Field.doSecurityCheck(Unknown Source)
- at java.lang.reflect.Field.getFieldAccessor(Unknown Source)
- at java.lang.reflect.Field.set(Unknown Source)
- at chb.test.reflect.TestClass.testReflect(TestClass.java:20)<PRE></PRE>
java.lang.IllegalAccessException: Class chb.test.reflect.TestClass can not access a member of class chb.test.reflect.Student with modifiers "private"
at sun.reflect.Reflection.ensureMemberAccess(Unknown Source)
at java.lang.reflect.Field.doSecurityCheck(Unknown Source)
at java.lang.reflect.Field.getFieldAccessor(Unknown Source)
at java.lang.reflect.Field.set(Unknown Source)
at chb.test.reflect.TestClass.testReflect(TestClass.java:20)
解決方法:
- Class cls = Class.forName("chb.test.reflect.Student");
- Object student = cls.newInstance();
- Field field = cls.getDeclaredField("age");
- field.setAccessible(true);
- field.set(student, 10);
- System.out.println(field.get(student));<PRE></PRE>
Class cls = Class.forName("chb.test.reflect.Student");
Object student = cls.newInstance();
Field field = cls.getDeclaredField("age");
field.setAccessible(true);//設置允許訪問
field.set(student, 10);
System.out.println(field.get(student));
其實,在某些場合下(類中有get,set方法),可以先反射調用set方法,再反射調用get方法達到如上效果,代碼示例:
- Class cls = Class.forName("chb.test.reflect.Student");
- Object student = cls.newInstance();
-
- Method setMethod = cls.getDeclaredMethod("setAge",Integer.class);
- setMethod.invoke(student, 15);
-
- Method getMethod = cls.getDeclaredMethod("getAge");
- System.out.println(getMethod.invoke(student));
|
Reflection 是 Java 程序開發語言的特征之一,它允許運行中的 Java 程序對自身進行檢查,或者說“自審”,并能直接操作程序的內部屬性。例如,使用它能獲得 Java 類中各成員的名稱并顯示出來。JavaBean 是 reflection 的實際應用之一,它能讓一些工具可視化的操作軟件組件。這些工具通過 reflection 動態的載入并取得 Java 組件(類) 的屬性。
1. 一個簡單的例子
考慮下面這個簡單的例子,讓我們看看 reflection 是如何工作的。
import java.lang.reflect.*;
public class DumpMethods {
public static void main(String args[]) {
try {
Class c = Class.forName(args[0]);
Method m[] = c.getDeclaredMethods();
for (int i = 0; i < m.length; i++)
System.out.println(m[i].toString());
} catch (Throwable e) {
System.err.println(e);
}
}
}
按如下語句執行:
java DumpMethods java.util.Stack
它的結果輸出為:
public java.lang.Object java.util.Stack.push(java.lang.Object)
public synchronized java.lang.Object java.util.Stack.pop()
public synchronized java.lang.Object java.util.Stack.peek()
public boolean java.util.Stack.empty()
public synchronized int java.util.Stack.search(java.lang.Object)
這樣就列出了java.util.Stack 類的各方法名以及它們的限制符和返回類型。
這個程序使用 Class.forName 載入指定的類,然后調用 getDeclaredMethods 來獲取這個類中定義了的方法列表。java.lang.reflect.Methods 是用來描述某個類中單個方法的一個類。還有就是getDeclaredMethod(para1,para2)來獲取這個類中的具體某一個方法,其中para1是一個String類型,具體代表的是方法名,para2是個一個Class類型的數組,其中定義個方法的具體參數類型。
例如:
- Class cls = Class.forName("chb.test.reflect.Student");
- Method m = cls.getDeclaredMethod("方法名",new Class[]{int.class,String.class});
- m.invoke(cls.newInstance(),20,"chb");
總結:
//使用反射類調用某個類中的方法
Class c = Class.forName("com.inspur.reflect.MethodTest");
Method n = c.getDeclaredMethod("show", new Class[]{String.class,int.class});
n.invoke(c.newInstance(), "guoxzh",20);
a.使用Class.forName("類名")來獲取類
b.其次使用getDeclaredMethods()方法獲取該類所有的方法,也可以使用getDeclaredMethod("方法名",new Class[]{int.class,String.class})方法類獲取具體的某一個方法
c.接著可以使用invoke(c.newInstance,param....)來調用具體的方法。
2.詳細介紹開始使用 Reflection
用于 reflection 的類,如 Method,可以在 java.lang.relfect 包中找到。使用這些類的時候必須要遵循三個步驟:第一步是獲得你想操作的類的 java.lang.Class 對象。在運行中的 Java 程序中,用 java.lang.Class 類來描述類和接口等。
下面就是獲得一個 Class 對象的方法之一:
Class c = Class.forName("java.lang.String");
這條語句得到一個 String 類的類對象。還有另一種方法,如下面的語句:
Class c = int.class;
或者
Class c = Integer.TYPE;
它們可獲得基本類型的類信息。其中后一種方法中訪問的是基本類型的封裝類 (如 Integer) 中預先定義好的 TYPE 字段。
第二步是調用諸如 getDeclaredMethods 的方法,以取得該類中定義的所有方法的列表。
一旦取得這個信息,就可以進行第三步了——使用 reflection API 來操作這些信息,如下面這段代碼:
Class c = Class.forName("java.lang.String");
Method m[] = c.getDeclaredMethods();
System.out.println(m[0].toString());
它將以文本方式打印出 String 中定義的第一個方法的原型。
在下面的例子中,這三個步驟將為使用 reflection 處理特殊應用程序提供例證。
模擬 instanceof 操作符
得到類信息之后,通常下一個步驟就是解決關于 Class 對象的一些基本的問題。例如,Class.isInstance 方法可以用于模擬 instanceof 操作符:
class A {
}
public class instance1 {
public static void main(String args[]) {
try {
Class cls = Class.forName("A");
boolean b1 = cls.isInstance(new Integer(37)); //判斷Integer(37)該對象是否是A類的對象
System.out.println(b1);
boolean b2 = cls.isInstance(new A());
System.out.println(b2);
} catch (Throwable e) {
System.err.println(e);
}
}
}
在這個例子中創建了一個 A 類的 Class 對象,然后檢查一些對象是否是 A 的實例。Integer(37) 不是,但 new A() 是。
3.找出類的方法
找出一個類中定義了些什么方法,這是一個非常有價值也非常基礎的 reflection 用法。下面的代碼就實現了這一用法:
package com.inspur.reflect;
import java.lang.reflect.Method;
public class Methodtest1 {
private int abc(Object p,int x) throws NullPointerException{
if(p==null)throw new NullPointerException();
return x;
}
public static void main(String[] args) {
try{
Class cls = Class.forName("com.inspur.reflect.Methodtest1");
Method methodlist[]= cls.getDeclaredMethods();
for(int i = 0;i<methodlist.length;i++){
Method m = methodlist[i];
System.out.println("name=="+m.getName());//得到方法的名稱
System.out.println("decl class=="+m.getDeclaringClass());//得到定義的類名
Class prev[] = m.getParameterTypes(); //取m方法中的所有參數
//遍歷所有的參數
for(int j = 0; j<prev.length;j++){
System.out.println("param["+j+"]=="+prev[j]);
}
Class exec[] = m.getExceptionTypes(); //得到所有的異常
//遍歷所有的異常
for(int k=0;k<exec.length;k++){
System.out.println("execption["+k+"]=="+exec[k]);
}
Class ret = m.getReturnType(); //得到每個方法的返回值
System.out.println("return leixing=="+ret.toString());
}
}catch(Throwable e){
System.err.println(e.getMessage());
}
}
}
這個程序首先取得 method1 類的描述,然后調用 getDeclaredMethods 來獲取一系列的 Method 對象,它們分別描述了定義在類中的每一個方法,包括 public 方法、protected 方法、package 方法和 private 方法等。
如果你在程序中使用 getMethods 來代替 getDeclaredMethods,你還能獲得繼承來的各個方法的信息。同時你也可以使用Modifier.toString(m.getModifiers())來獲取方法的限制屬性。
取得了 Method 對象列表之后,要顯示這些方法的參數類型、異常類型和返回值類型等就不難了。這些類型是基本類型還是類類型,都可以由描述類的對象按順序給出。
輸出的結果如下:
name==main
decl class==class com.inspur.reflect.Methodtest1
param[0]==class [Ljava.lang.String;
return leixing==void
name==abc
decl class==class com.inspur.reflect.Methodtest1
param[0]==class java.lang.Object
param[1]==int
execption[0]==class java.lang.NullPointerException
return leixing==int 4.獲取構造器信息
獲取類構造器的用法與上述獲取方法的用法類似,如:
import java.lang.reflect.*;
public class constructor1 {
public constructor1() {
}
protected constructor1(int i, double d) {
}
public static void main(String args[]) {
try {
Class cls = Class.forName("constructor1");
Constructor ctorlist[] = cls.getDeclaredConstructors();
for (int i = 0; i < ctorlist.length; i++) {
Constructor ct = ctorlist[i];
System.out.println("name = " + ct.getName());
System.out.println("decl class = " + ct.getDeclaringClass());
Class pvec[] = ct.getParameterTypes();
for (int j = 0; j < pvec.length; j++)
System.out.println("param #" + j + " " + pvec[j]);
Class evec[] = ct.getExceptionTypes();
for (int j = 0; j < evec.length; j++)
System.out.println("exc #" + j + " " + evec[j]);
System.out.println("-----");
}
} catch (Throwable e) {
System.err.println(e);
}
}
}
這個例子中沒能獲得返回類型的相關信息,那是因為構造器沒有返回類型。
這個程序運行的結果是:
name = constructor1
decl class = class constructor1
-----
name = constructor1
decl class = class constructor1
param #0 int
param #1 double
-----
5.獲取類的字段(域)
找出一個類中定義了哪些數據字段也是可能的,下面的代碼就在干這個事情:
import java.lang.reflect.*;
public class field1 {
private double d;
public static final int i = 37;
String s = "testing";
public static void main(String args[]) {
try {
Class cls = Class.forName("field1");
Field fieldlist[] = cls.getDeclaredFields();
for (int i = 0; i < fieldlist.length; i++) {
Field fld = fieldlist[i];
System.out.println("name = " + fld.getName());
System.out.println("decl class = " + fld.getDeclaringClass());
System.out.println("type = " + fld.getType());
int mod = fld.getModifiers();
System.out.println("modifiers = " + Modifier.toString(mod));
System.out.println("-----");
}
} catch (Throwable e) {
System.err.println(e);
}
}
}
這個例子和前面那個例子非常相似。例中使用了一個新東西 Modifier,它也是一個 reflection 類,用來描述字段成員的修飾語,如“private int”。這些修飾語自身由整數描述,而且使用 Modifier.toString 來返回以“官方”順序排列的字符串描述 (如“static”在“final”之前)。這個程序的輸出是:
name = d
decl class = class field1
type = double
modifiers = private
-----
name = i
decl class = class field1
type = int
modifiers = public static final
-----
name = s
decl class = class field1
type = class java.lang.String
modifiers =
-----
和獲取方法的情況一下,獲取字段的時候也可以只取得在當前類中申明了的字段信息 (getDeclaredFields),或者也可以取得父類中定義的字段 (getFields) 。
6.根據方法的名稱來執行方法
文本到這里,所舉的例子無一例外都與如何獲取類的信息有關。我們也可以用 reflection 來做一些其它的事情,比如執行一個指定了名稱的方法。下面的示例演示了這一操作:
import java.lang.reflect.*;
public class method2 {
public int add(int a, int b) {
return a + b;
}
public static void main(String args[]) {
try {
Class cls = Class.forName("method2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Method meth = cls.getMethod("add", partypes);
method2 methobj = new method2();
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = meth.invoke(methobj, arglist);
Integer retval = (Integer) retobj;
System.out.println(retval.intValue());
} catch (Throwable e) {
System.err.println(e);
}
}
}
假如一個程序在執行的某處的時候才知道需要執行某個方法,這個方法的名稱是在程序的運行過程中指定的 (例如,JavaBean 開發環境中就會做這樣的事),那么上面的程序演示了如何做到。
上例中,getMethod 用于查找一個具有兩個整型參數且名為 add 的方法。找到該方法并創建了相應的 Method 對象之后,在正確的對象實例中執行它。執行該方法的時候,需要提供一個參數列表,這在上例中是分別包裝了整數 37 和 47 的兩個 Integer 對象。執行方法的返回的同樣是一個 Integer 對象,它封裝了返回值 84。
7.創建新的對象
對于構造器,則不能像執行方法那樣進行,因為執行一個構造器就意味著創建了一個新的對象 (準確的說,創建一個對象的過程包括分配內存和構造對象)。所以,與上例最相似的例子如下:
import java.lang.reflect.*;
public class constructor2 {
public constructor2() {
}
public constructor2(int a, int b) {
System.out.println("a = " + a + " b = " + b);
}
public static void main(String args[]) {
try {
Class cls = Class.forName("constructor2");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Constructor ct = cls.getConstructor(partypes);
Object arglist[] = new Object[2];
arglist[0] = new Integer(37);
arglist[1] = new Integer(47);
Object retobj = ct.newInstance(arglist);
} catch (Throwable e) {
System.err.println(e);
}
}
}
根據指定的參數類型找到相應的構造函數并執行它,以創建一個新的對象實例。使用這種方法可以在程序運行時動態地創建對象,而不是在編譯的時候創建對象,這一點非常有價值。
(這里如果使用無參構造器創建對象的話,這可以直接使用Class.forName("...").newInstance();來創建對象)
8.改變字段(域)的值
reflection 的還有一個用處就是改變對象數據字段的值。reflection 可以從正在運行的程序中根據名稱找到對象的字段并改變它,下面的例子可以說明這一點:
import java.lang.reflect.*;
public class field2 {
public double d;
public static void main(String args[]) {
try {
Class cls = Class.forName("field2");
Field fld = cls.getField("d");
field2 f2obj = new field2();
System.out.println("d = " + f2obj.d);
fld.setDouble(f2obj, 12.34);
System.out.println("d = " + f2obj.d);
} catch (Throwable e) {
System.err.println(e);
}
}
}
這個例子中,字段 d 的值被變為了 12.34。
9.使用數組
本文介紹的 reflection 的最后一種用法是創建的操作數組。數組在 Java 語言中是一種特殊的類類型,一個數組的引用可以賦給 Object 引用。觀察下面的例子看看數組是怎么工作的:
import java.lang.reflect.*;
public class array1 {
public static void main(String args[]) {
try {
Class cls = Class.forName("java.lang.String");
Object arr = Array.newInstance(cls, 10);
Array.set(arr, 5, "this is a test");
String s = (String) Array.get(arr, 5);
System.out.println(s);
} catch (Throwable e) {
System.err.println(e);
}
}
}
例中創建了 10 個單位長度的 String 數組,為第 5 個位置的字符串賦了值,最后將這個字符串從數組中取得并打印了出來。
下面這段代碼提供了一個更復雜的例子:
import java.lang.reflect.*;
public class array2 {
public static void main(String args[]) {
int dims[] = new int[]{5, 10, 15};
Object arr = Array.newInstance(Integer.TYPE, dims);
Object arrobj = Array.get(arr, 3);
Class cls = arrobj.getClass().getComponentType();
System.out.println(cls);
arrobj = Array.get(arrobj, 5);
Array.setInt(arrobj, 10, 37);
int arrcast[][][] = (int[][][]) arr;
System.out.println(arrcast[3][5][10]);
}
}
例中創建了一個 5 x 10 x 15 的整型數組,并為處于 [3][5][10] 的元素賦了值為 37。注意,多維數組實際上就是數組的數組,例如,第一個 Array.get 之后,arrobj 是一個 10 x 15 的數組。進而取得其中的一個元素,即長度為 15 的數組,并使用 Array.setInt 為它的第 10 個元素賦值。
注意創建數組時的類型是動態的,在編譯時并不知道其類型。
摘要: 轉自其他博客《收藏》
(1) 選擇最有效率的表名順序(只在基于規則的優化器中有效):
ORACLE的解析器按照從右到左的順序處理FROM子句中的表名,FROM子句中寫在最后的表(基礎表 driving table)將被最先處理,在FROM子句中包含多個表的情況下,你必須選擇記錄條數最少的表作為基礎表。如果有3個以上的表連接查詢,...
閱讀全文
1,使用Spring 的 ActionSupport
2,使用Spring 的 DelegatingRequestProcessor 類。
3,全權委托。
無論用那種方法來整合第一步就是要為struts來裝載spring的應用環境。 就是在 struts 中加入一個插件。
struts-config.xml中
<plug-in className="org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation" value="/WEB-INF/applicationContext.xml"/>
</plug-in>
|
spring 的配置文件被作為參數配置進來。這樣可以省略對web.xml 文件中的配置。確保你的applicationContext.xml 在WEB-INF目錄下面
1、使用Spring的ActionSupport .
Spring 的ActionSupport 繼承至org.apache.struts.action.Action
ActionSupport的子類可以或得 WebApplicationContext類型的全局變量。通過getWebApplicationContext()可以獲得這個變量。
這是一個 servlet 的代碼:
public class LoginAction extends org.springframework.web.struts.ActionSupport {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
LoginForm loginForm = (LoginForm) form;// TODO Auto-generated method stub
//獲得 WebApplicationContext 對象
WebApplicationContext ctx = this.getWebApplicationContext();
LoginDao dao = (LoginDao) ctx.getBean("loginDao");
User u = new User();
u.setName(loginForm.getName());
u.setPwd(loginForm.getPwd());
if(dao.checkLogin(u)){
return mapping.findForward("success");
}else{
return mapping.findForward("error");
}
}
}
applicationContext.xml 中的配置
<beans>
<bean id="loginDao" class="com.cao.dao.LoginDao"/>
</beans>
|
這中配置方式同直接在web.xml文件配置差別不大。
注意:Action繼承自 org.springframework.web.struts.ActionSupport 使得struts和spring耦合在一起。
但實現了表示層和業務邏輯層的解耦(LoginDao dao = (LoginDao) ctx.getBean("loginDao"))。
2、使用Spring 的 DelegatingRequestProcessor 類
DelegatingRequestProcessor 繼承自 org.apache.struts.action.RequestProcessor 并覆蓋了里面的方法。
sturts-config.xml 中
processorClass="org.springframework.web.struts.DelegatingRequestProcessor"/> 通過 來替代
org.apache.struts.action.RequestProcessor 的請求處理。
public class LoginAction extends Action {
//利用spring來注入這個對象。
private LoginDao dao ;
public void setDao(LoginDao dao) {
System.out.println("執行注入");
this.dao = dao;
}
public LoginDao getDao() {
return dao;
}
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
LoginForm loginForm = (LoginForm) form;// TODO Auto-generated method stub
//這樣一改這行代碼似乎沒有必要了。
//WebApplicationContext ctx = this.getWebApplicationContext();
//LoginDao dao = (LoginDao) ctx.getBean("loginDao");
User u = new User();
u.setName(loginForm.getName());
u.setPwd(loginForm.getPwd());
//直接用dao來調用spring會將這個對象實例化。
if(dao.checkLogin(u)){
return mapping.findForward("success");
}else{
return mapping.findForward("error");
}
}
}
這里的。
LoginAction extends Action 說明 struts沒有和spring 耦合。
看一下
applicationContext.xml 中的配置。
<beans>
<bean id="loginDao" class="com.cao.dao.LoginDao"/>
<bean name="/login" class="com.cao.struts.action.LoginAction">
<property name="dao">
<ref local="loginDao"/>
</property>
</bean>
</beans>
|
這里 name="/login" 與struts 中的path匹配
class="com.cao.struts.action.LoginAction" 與struts 中的type匹配
還要為 LoginAction 提供必要的setXXX方法。 獲得ApplicationCotext和依賴注入的工作都在DelegatingRequestProcessor中完成。
3,全權委托:
Action 的創建和對象的依賴注入全部由IOC容器來完成。使用Spring的DelegatingAcionProxy來幫助實現代理的工作
org.springframework.web.struts.DelegatingActiongProxy繼承于org.apache.struts.action.Action .
全權委托的配置方式同 方式 2 類似 (applcationContext.xml文件的配置和 Action類的實現方式相同)。
<struts-config>
<data-sources />
<form-beans >
<form-bean name="loginForm"
type="com.cao.struts.form.LoginForm" />
</form-beans>
<global-exceptions />
<global-forwards />
<action-mappings >
<!-- type指向的是spring 的代理類 -->
<action
attribute="loginForm"
input="login.jsp"
name="loginForm"
path="/login"
scope="request"
type="org.springframework.web.struts.DelegatingActionProxy" >
<forward name="success" path="/ok.jsp" />
<forward name="error" path="/error.jsp" />
</action>
</action-mappings>
<message-resources parameter="com.cao.struts.ApplicationResources" />
<plug-in className=
"org.springframework.web.struts.ContextLoaderPlugIn">
<set-property property="contextConfigLocation"
value="/WEB-INF/applicationContext.xml"/>
</plug-in>
</struts-config>
不同之處
1, <action>中 type指向的是spring 的代理類
2, 去掉struts-config.xml中 <controller >
|
三種整和方式中我們優先選用 全權委托的方式。
理由:
1,第一種使得過多的耦合了Spring和Action .
2,RequestProcessor類已經被代理 如果要再實現自己的實現方式(如:編碼處理)怕有點麻煩。
總結一下:
整合工作中的步驟:
1,修改struts-config.xml
2, 配置applicationContext.xml
3, 為Action添加get/set方法 來獲得依賴注入的功能。
最近比較忙,但是每天網上還是的堅持學點,不積小流,無以成江河。
今天學jQuery對象訪問:
1.each(callback) 該方法以每一個匹配的元素作為上下文來執行一個函數,
在每次執行函數時,都會給函數傳遞一個表示作為執行環境的元素在匹配的元素集合中所處位置的數字值作為參數(從0開始的int)
返回‘false’將停止循環(相當于普通循環中使用的‘break’)
返回‘true’將跳至下一個循環,(相當于在普通的循環中使用‘continue’)
參數:callback(function)
e.g1
<img/><img/>
jQuery代碼:
$('img').each(function(){
this.src="test"+i+".jpg";
});
e.g2
<button>Change colors</button>
<span></span>
<div></div>
<div></div>
<div></div>
<div></div>
<div id="stop">Stop here</div>
<div></div>
<div></div>
<div></div>
jQuery代碼:
$('button').click(function(){
$('div').each(function(index,domEle){//domEle ==this
$(domEle).css('backgroundColor',"yellow");
if($(this).is("#stop")){
$("span").text("stopped at div index #"+index);
return false;}
});});
2.size() 和length
都可以勇于得到jQuery對象中元素的個數,
返回: Number
e.g1
<img src="test1.jpg"/><img src="test2.jpg"/>
jQuery代碼:
$("img").size();
e.g2
同理:$("img").length;
3.get()取得所有匹配的DOM元素集合
返回:Array<Element>
e.g1
<img src="test1.jpg"/><img src="test2.jpg"/>
jQuery代碼:
$("img").get().reverse();
result:
[<img src="test1.jpg"/><img src="test2.jpg"/>]
4.get(index)
取得其中一個匹配元素,index表示取得第幾個匹配的元素
返回值:Element
HTML代碼:
<img src="test1.jpg"/><img src="test2.jpg"/>
jQuery代碼:
$("img").get(0);
result:
[<img src="test1.jpg"/>]
5.index(subject)
搜索與參數表示的對象匹配的元素,并返回相應元素的索引值,
如果哦找到了匹配的元素,從0開始返回;如果沒有找到匹配的元素,返回-1
返回值;
Number
參數:
subject(Element)
e.g1返回id值為foobar的元素的索引值
<div id="foobar"><div></div><div id="foo"></div></div>
jQuery代碼:
$("div").index($("#foobar")[0]) //0
$("div").index($('#foo')[0]) // 2
$("div").index($('#foo')) // -1
備注:
今天在瀏覽別人博客的時候看到的,收藏。
有時候,我們頁面當中并不需要把要用到的JS全部加載出來,
這會使頁面加載時速度變慢~~~如果能按需加載,那能提高不少性能...也能節約不少流量~~~給用戶帶來好的體驗~~
好比說,當某個JS效果是觸發事件才顯示的...這個效果被封閉在一個JS中,,我想大家經常這樣做吧~~這時候,我們能按需加載那就不必在頁面載入時去加載JS文件~~~這在jquery插件中很多。
用法:
1 , 當在需要的時候再加載所需的javascript和css文件。
$.include('file/test.js')或$.include('file/test.css')
2, 當然若你一次想加載多個文件你也可以這樣寫:
$.include(['file/test.js','file/test.css'])。
3, 因為這兩個文件的路徑相同,所以可以先指定路徑再加載所有文件:
$.ImportBasePath = 'file/';
$.include(['test.css','test.js']);
4, 你還可以加載完文件后執行回調函數
$.include("file/test.css",function(){
alert("加載css后執行");
});
插件下載地址:http://www.94this.com.cn/myCode/jqueryIncludefile/jqueryIncludefile.rar
注:jquery 自帶了有一個異步請求的方法,$.getScript ,可以異步加到JS并執行
jQuery.getScript(url,[callback])
通過 HTTP GET 請求載入并執行一個 JavaScript 文件。
jQuery 1.2 版本之前,getScript 只能調用同域 JS 文件。 1.2中,您可以跨域調用 JavaScript 文件。注意:Safari 2 或更早的版本不能在全局作用域中同步執行腳本。如果通過 getScript 加入腳本,請加入延時函數。
Loads, and executes, a local JavaScript file using an HTTP GET request.
Before jQuery 1.2, getScript was only able to load scripts from the same domain as the original page. As of 1.2, you can now load JavaScript files from any domain. Warning: Safari 2 and older is unable to evaluate scripts in a global context synchronously. If you load functions via getScript, make sure to call them after a delay.
返回值
XMLHttpRequest
參數
url (String) : 待載入 JS 文件地址。
callback (Function) : (可選) 成功載入后回調函數。
示例
載入 jQuery 官方顏色動畫插件 成功后綁定顏色變化動畫。
HTML 代碼:
<button id="go">» Run</button>
<div class="block"></div>
jQuery 代碼:
jQuery.getScript("http://dev.jquery.com/view/trunk/plugins/color/jquery.color.js",
function(){
$("#go").click(function(){
$(".block").animate( { backgroundColor: 'pink' }, 1000)
.animate( { backgroundColor: 'blue' }, 1000);
});
});
加載并執行 test.js。
jQuery 代碼:
$.getScript("test.js");
加載并執行 test.js ,成功后顯示信息。
jQuery 代碼:
$.getScript("test.js", function(){
alert("Script loaded and executed.");
});