??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲人成色4444在线观看,亚洲国产精品无码久久九九大片,日韩精品亚洲专区在线观看http://m.tkk7.com/zhuyongjp/category/37969.htmlzh-cnThu, 06 Aug 2009 17:18:55 GMTThu, 06 Aug 2009 17:18:55 GMT60转义字符http://m.tkk7.com/zhuyongjp/archive/2009/08/05/289957.htmlzhuyongjpzhuyongjpWed, 05 Aug 2009 07:32:00 GMThttp://m.tkk7.com/zhuyongjp/archive/2009/08/05/289957.htmlhttp://m.tkk7.com/zhuyongjp/comments/289957.htmlhttp://m.tkk7.com/zhuyongjp/archive/2009/08/05/289957.html#Feedback0http://m.tkk7.com/zhuyongjp/comments/commentRss/289957.htmlhttp://m.tkk7.com/zhuyongjp/services/trackbacks/289957.html  (tng)HTML?lt;Q?gt;Q?amp;{有Ҏ(gu)含义Q?lt;Q?gt;Q用于链接签Q?amp;用于转义Q,不能直接使用。这些符h不显C在我们最l看到的|页里的Q那如果我们希望在网中昄q些W号Q该怎么办呢Q?

q就要说到HTML转义字符ԌEscape SequenceQ了(jin)?

转义字符?/font> QEscape SequenceQ也U字W实?Character Entity)。在HTML中,定义转义字符串的原因有两个:(x)W一个原因是像?lt;”和?gt;”这cȝ号已l用来表CHTML标签Q因此就不能直接当作文本中的W号来用。ؓ(f)?jin)在HTML文档中用这些符P需要定义它的{义字W串。当解释E序遇到q类字符串时把它解释ؓ(f)真实的字W。在输入转义字符串时Q要严格遵守字母大小写的规则。第二个原因是,有些字符在ASCII字符集中没有定义Q因此需要用{义字W串来表C?

转义字符串的l成

转义字符ԌEscape SequenceQ,卛_W实体(Character EntityQ分成三部分Q第一部分是一?amp;W号Q英文叫ampersandQ第二部分是实体QEntityQ名字或者是#加上实体QEntityQ编PW三部分是一个分受?

比如Q要昄于P<Q,可以写 &lt; 或?&#60; ?

用实体(EntityQ名字的好处是比较好理解Q一看ltQ大概就猜出是less than的意思,但是其劣势在于ƈ不是所有的览器都支持最新的Entity名字。而实?Entity)~号Q各U浏览器都能处理?

提示Q实体名UͼEntityQ是区分大小写的?

备注Q同一个符P可以用“实体名U”和“实体编号”两U方式引用,“实体名U”的优势在于便于记忆Q但不能保证所有的览器都能顺利识别它Q而“实体编号”则没有q种担忧Q但它实在不方便记忆?

如何昄I格Q?/h2>

通常情况下,HTML?x)自动截d余的I格。不你加多空|都被看做一个空根{比如你在两个字之间加了(jin)10个空|HTML?x)截?个空|只保留一个。ؓ(f)?jin)在|页中增加空|你可以?amp;nbsp;表示I格?


HTMLҎ(gu)转义字符列表

最常用的字W实?br />Character Entities

说明 实体名称 实体~号
半方大的I白 &ensp; &#8194;
全方大的I白 &emsp; &#8195;
不断行的I白?/td> &nbsp; &#160;
< &lt; &#60;
> 大于 &gt; &#62;
& &W号 &amp; &#38;
" 双引?/td> &quot; &#34;
© 版权 &copy; &#169;
] 已注册商?/td> &reg; &#174;
?/td> 商标Q美国)(j) ?/td> &#8482;
× 乘号 &times; &#215;
÷ 除号 &divide; &#247;

ISO 8859-1 (Latin-1)字符?/h2>

HTML 4.01 支持 ISO 8859-1 (Latin-1) 字符集?

备注Qؓ(f)?jin)方便v见,以下表格中,“实体名U”简UCؓ(f)“名U”,“实体编号”简UCؓ(f)“编号?

名称 ~号 名称 ~号 名称 ~号 名称 ~号 名称 ~号
 (tng) &nbsp; &#160; ¡ &iexcl; &#161; &cent; &#162; n &pound; &#163; ] &curren; &#164;
&yen; &#165; &brvbar; &#166; &sect; &#167; t &uml; &#168; © &copy; &#169;
ª &ordf; &#170; J &laquo; &#171; R &not; &#172; B &shy; &#173; ] &reg; &#174;
t &macr; &#175; &deg; &#176; u &plusmn; &#177; ̔ &sup2; &#178; &sup3; &#179;
´ &acute; &#180; µ &micro; &#181; &para; &#182; · &middot; &#183; T &cedil; &#184;
¹ &sup1; &#185; º &ordm; &#186; &raquo; &#187; &frac14; &#188; &frac12; &#189;
¾ &frac34; &#190; H &iquest; &#191; À &Agrave; &#192; Á &Aacute; &#193; Â &Acirc; &#194;
à &Atilde; &#195; Ä &Auml; &#196; Å &Aring; &#197; Æ &AElig; &#198; Ç &Ccedil; &#199;
È &Egrave; &#200; É &Eacute; &#201; Ê &Ecirc; &#202; Ë &Euml; &#203; Ì &Igrave; &#204;
Í &Iacute; &#205; Î &Icirc; &#206; Ï &Iuml; &#207; Ð &ETH; &#208; Ñ &Ntilde; &#209;
Ò &Ograve; &#210; Ó &Oacute; &#211; Ô &Ocirc; &#212; Õ &Otilde; &#213; Ö &Ouml; &#214;
× &times; &#215; Ø &Oslash; &#216; Ù &Ugrave; &#217; Ú &Uacute; &#218; Û &Ucirc; &#219;
Ü &Uuml; &#220; Ý &Yacute; &#221; Þ &THORN; &#222; ß &szlig; &#223; à &agrave; &#224;
֙ &aacute; &#225; â &acirc; &#226; ã &atilde; &#227; ä &auml; &#228; å &aring; &#229;
æ &aelig; &#230; ç &ccedil; &#231; ؈ &egrave; &#232; é &eacute; &#233; ^ &ecirc; &#234;
ë &euml; &#235; ì &igrave; &#236; T &iacute; &#237; î &icirc; &#238; ï &iuml; &#239;
ð &eth; &#240; ñ &ntilde; &#241; ò &ograve; &#242; Q(mo) &oacute; &#243; ô &ocirc; &#244;
õ &otilde; &#245; ö &ouml; &#246; ÷ &divide; &#247; ø &oslash; &#248; ù &ugrave; &#249;
ú &uacute; &#250; ](mi) &ucirc; &#251; ü &uuml; &#252; ý &yacute; &#253; V &thorn; &#254;
ÿ &yuml; &#255;

数学和希腊字母标?br />symbols, mathematical symbols, and Greek letters

名称 ~号 名称 ~号 名称 ~号 名称 ~号 名称 ~号
ƒ &fnof; &#402; Α &Alpha; &#913; Β &Beta; &#914; Γ &Gamma; &#915; Δ &Delta; &#916;
Ε &Epsilon; &#917; Ζ &Zeta; &#918; Η &Eta; &#919; Θ &Theta; &#920; Ι &Iota; &#921;
Κ &Kappa; &#922; Λ &Lambda; &#923; Μ &Mu; &#924; Ν &Nu; &#925; Ξ &Xi; &#926;
Ο &Omicron; &#927; Π &Pi; &#928; Ρ &Rho; &#929; Σ &Sigma; &#931; f &Tau; &#932;
` &Upsilon; &#933; Φ &Phi; &#934; &Chi; &#935; Ψ &Psi; &#936; Ω &Omega; &#937;
&alpha; &#945; β &beta; &#946; &gamma; &#947; δ &delta; &#948; ε &epsilon; &#949;
ζ &zeta; &#950; η &eta; &#951; θ &theta; &#952; ι &iota; &#953; κ &kappa; &#954;
λ &lambda; &#955; μ &mu; &#956; ^ &nu; &#957; ξ &xi; &#958; ο &omicron; &#959;
π &pi; &#960; ρ &rho; &#961; ς &sigmaf; &#962; σ &sigma; &#963; τ &tau; &#964;
υ &upsilon; &#965; φ &phi; &#966; χ &chi; &#967; ψ &psi; &#968; ω &omega; &#969;
? &thetasym; &#977; ? &upsih; &#978; ? &piv; &#982; ?/td> &bull; &#8226; ?/td> &hellip; &#8230;
?/td> &prime; &#8242; ?/td> &Prime; &#8243; ?/td> &oline; &#8254; ?/td> &frasl; &#8260; ?/td> &weierp; &#8472;
?/td> &image; &#8465; ?/td> &real; &#8476; ?/td> &trade; &#8482; ?/td> &alefsym; &#8501; ?/td> &larr; &#8592;
?/td> &uarr; &#8593; ?/td> &rarr; &#8594; ?/td> &darr; &#8595; ?/td> &harr; &#8596; ?/td> &crarr; &#8629;
?/td> &lArr; &#8656; ?/td> &uArr; &#8657; ?/td> &rArr; &#8658; ?/td> &dArr; &#8659; ?/td> &hArr; &#8660;
&forall; &#8704; ?/td> &part; &#8706; ?/td> &exist; &#8707; ?/td> &empty; &#8709; ?/td> &nabla; &#8711;
?/td> &isin; &#8712; ?/td> &notin; &#8713; ?/td> &ni; &#8715; ?/td> &prod; &#8719; ?/td> &sum; &#8721;
?/td> &minus; &#8722; ?/td> &lowast; &#8727; ?/td> &radic; &#8730; ?/td> &prop; &#8733; ?/td> &infin; &#8734;
?/td> &ang; &#8736; ?/td> &and; &#8743; ?/td> &or; &#8744; ?/td> &cap; &#8745; ?/td> &cup; &#8746;
?/td> &int; &#8747; ?/td> &there4; &#8756; ?/td> &sim; &#8764; ?/td> &cong; &#8773; ?/td> &asymp; &#8776;
?/td> &ne; &#8800; ?/td> &equiv; &#8801; ?/td> &le; &#8804; ?/td> &ge; &#8805; ?/td> &sub; &#8834;
?/td> &sup; &#8835; ?/td> &nsub; &#8836; ?/td> &sube; &#8838; ?/td> &supe; &#8839; ?/td> &oplus; &#8853;
?/td> &otimes; &#8855; ?/td> &perp; &#8869; ?/td> &sdot; &#8901; ? &lceil; &#8968; ? &rceil; &#8969;
? &lfloor; &#8970; ? &rfloor; &#8971; ? &lang; &#9001; ? &rang; &#9002; ?/td> &loz; &#9674;
?/td> &spades; &#9824; ?/td> &clubs; &#9827; ?/td> &hearts; &#9829; ?/td> &diams; &#9830;

重要的国际标?br />markup-significant and internationalization characters

名称 ~号 名称 ~号 名称 ~号 名称 ~号 名称 ~号
" &quot; &#34; & &amp; &#38; < &lt; &#60; > &gt; &#62; Œ &OElig; &#338;
œ &oelig; &#339; Š &Scaron; &#352; Q &scaron; &#353; t &Yuml; &#376; ˆ &circ; &#710;
˜ &tilde; &#732; ?/td> &ensp; &#8194; ?/td> &emsp; &#8195; ?/td> &thinsp; &#8201; ?/td> &zwnj; &#8204;
?/td> &zwj; &#8205; ?/td> &lrm; &#8206; ?/td> &rlm; &#8207; ?/td> &ndash; &#8211; ?/td> &mdash; &#8212;
?/td> &lsquo; &#8216; ?/td> &rsquo; &#8217; ?/td> &sbquo; &#8218; ?/td> &ldquo; &#8220; ?/td> &rdquo; &#8221;
?/td> &bdquo; &#8222; ?/td> &dagger; &#8224; ?/td> &Dagger; &#8225; ?/td> &permil; &#8240; ?/td> &lsaquo; &#8249;
?/td> &rsaquo; &#8250; ?/td> &euro; &#8364;

JavaScript转义W?/h2>
转义序列 字符
\b 退?/td>
\f 走纸换页
\n 换行
\r 回R
\t 横向x(chng) (Ctrl-I)
\' 单引?/td>
\" 双引?/td>
\\ 反斜?/td>

~程的时候要注意Ҏ(gu)字符的问题,很多q行时出现的问题都是因ؓ(f)Ҏ(gu)字符的出现而引L(fng)?

注意Q由于反斜杠本n用作转义W,因此不能直接在脚本中键入一个反斜杠。如果要产生一个反斜杠Q必M起键入两个反斜杠 (\\)?


~码转换Qto UnicodeQ?/h2>

Q程序代码来源于|络Q?

Js?

<script>
 (tng) (tng) (tng) (tng) test = "你好abc"
 (tng) (tng) (tng) (tng) str = ""
 (tng) (tng) (tng) (tng) for( i=0; (tng) (tng) (tng) i<test.length; i++ )
 (tng) (tng) (tng) (tng) {
 (tng) (tng) (tng) (tng)  temp = test.charCodeAt(i).toString(16);
 (tng) (tng) (tng) (tng)  str (tng) (tng) (tng) += "\\u"+ new Array(5-String(temp).length).join("0") +temp;
 (tng) (tng) (tng) (tng) }
 (tng) (tng) (tng) (tng) document.write (str)
</script>


vbs?/strong>


Function Unicode(str1)
 (tng) (tng) (tng) (tng) Dim str,temp
 (tng) (tng) (tng) (tng) str = ""
 (tng) (tng) (tng) (tng) For i=1 (tng) (tng) (tng) to len(str1)
 (tng) (tng) (tng) (tng)  temp = Hex(AscW(Mid(str1,i,1)))
 (tng) (tng) (tng) (tng)  If len(temp) < 5 Then (tng) (tng) (tng) temp = right("0000" & temp, 4)
 (tng) (tng) (tng) (tng)  str = str & "\u" & temp
 (tng) (tng) (tng) (tng) Next
 (tng) (tng) (tng) (tng) Unicode = str
End Function


Function htmlentities(str)
 (tng) (tng) (tng) (tng) For i = 1 to Len(str)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) char = mid(str, i, 1)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) If Ascw(char) > 128 then
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) htmlentities = htmlentities & "&#" & Ascw(char) & ";"
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) Else
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) htmlentities = htmlentities & char
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) End if
 (tng) (tng) (tng) (tng) Next
End Function

coldfusion?/span>

function nochaoscode(str)
{
 (tng) (tng) (tng) (tng) var new_str = “?
 (tng) (tng) (tng) (tng) for(i=1; i lte len(str);i=i+1){
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) if(asc(mid(str,i,1)) lt 128){
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) new_str = new_str & mid(str,i,1);
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }else{
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) new_str = new_str & ?amp;##?& asc(mid(str,i,1));
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) }
 (tng) (tng) (tng) (tng) }
 (tng) (tng) (tng) (tng) return new_str;
}


附:(x)

在php中我们可以用mbstring的mb_convert_encoding函数实现q个正向?qing)反向的转化?如:(x)


mb_convert_encoding ("你好", "HTML-ENTITIES", "gb2312"); //输出Q?amp;#20320;&#22909;

mb_convert_encoding ("&#20320;&#22909;", "gb2312", "HTML-ENTITIES"); //输出Q你?

如果需要对整个面转化Q则只需要在php文g的头部加上这三行代码Q?/p>

mb_internal_encoding("gb2312"); // q里的gb2312是你|站原来的编?

mb_http_output("HTML-ENTITIES");

ob_start('mb_output_handler');



zhuyongjp 2009-08-05 15:32 发表评论
]]>
javascript 键盘?sh)g?keyCode http://m.tkk7.com/zhuyongjp/archive/2009/07/23/288069.htmlzhuyongjpzhuyongjpThu, 23 Jul 2009 09:57:00 GMThttp://m.tkk7.com/zhuyongjp/archive/2009/07/23/288069.htmlhttp://m.tkk7.com/zhuyongjp/comments/288069.htmlhttp://m.tkk7.com/zhuyongjp/archive/2009/07/23/288069.html#Feedback0http://m.tkk7.com/zhuyongjp/comments/commentRss/288069.htmlhttp://m.tkk7.com/zhuyongjp/services/trackbacks/288069.htmlkeycode (tng) (tng) (tng) 8 = BackSpace BackSpace
keycode (tng) (tng) (tng) 9 = Tab Tab
keycode (tng) (tng) 12 = Clear
keycode (tng) (tng) 13 = Enter
keycode (tng) (tng) 16 = Shift_L
keycode (tng) (tng) 17 = Control_L
keycode (tng) (tng) 18 = Alt_L
keycode (tng) (tng) 19 = Pause
keycode (tng) (tng) 20 = Caps_Lock
keycode (tng) (tng) 27 = Escape Escape
keycode (tng) (tng) 32 = space space
keycode (tng) (tng) 33 = Prior
keycode (tng) (tng) 34 = Next
keycode (tng) (tng) 35 = End
keycode (tng) (tng) 36 = Home
keycode (tng) (tng) 37 = Left
keycode (tng) (tng) 38 = Up
keycode (tng) (tng) 39 = Right
keycode (tng) (tng) 40 = Down
keycode (tng) (tng) 41 = Select
keycode (tng) (tng) 42 = Print
keycode (tng) (tng) 43 = Execute
keycode (tng) (tng) 45 = Insert
keycode (tng) (tng) 46 = Delete
keycode (tng) (tng) 47 = Help
keycode (tng) (tng) 48 = 0 equal braceright
keycode (tng) (tng) 49 = 1 exclam onesuperior
keycode (tng) (tng) 50 = 2 quotedbl twosuperior
keycode (tng) (tng) 51 = 3 section threesuperior
keycode (tng) (tng) 52 = 4 dollar
keycode (tng) (tng) 53 = 5 percent
keycode (tng) (tng) 54 = 6 ampersand
keycode (tng) (tng) 55 = 7 slash braceleft
keycode (tng) (tng) 56 = 8 parenleft bracketleft
keycode (tng) (tng) 57 = 9 parenright bracketright
keycode (tng) (tng) 65 = a A
keycode (tng) (tng) 66 = b B
keycode (tng) (tng) 67 = c C
keycode (tng) (tng) 68 = d D
keycode (tng) (tng) 69 = e E EuroSign
keycode (tng) (tng) 70 = f F
keycode (tng) (tng) 71 = g G
keycode (tng) (tng) 72 = h H
keycode (tng) (tng) 73 = i I
keycode (tng) (tng) 74 = j J
keycode (tng) (tng) 75 = k K
keycode (tng) (tng) 76 = l L
keycode (tng) (tng) 77 = m M mu
keycode (tng) (tng) 78 = n N
keycode (tng) (tng) 79 = o O
keycode (tng) (tng) 80 = p P
keycode (tng) (tng) 81 = q Q at
keycode (tng) (tng) 82 = r R
keycode (tng) (tng) 83 = s S
keycode (tng) (tng) 84 = t T
keycode (tng) (tng) 85 = u U
keycode (tng) (tng) 86 = v V
keycode (tng) (tng) 87 = w W
keycode (tng) (tng) 88 = x X
keycode (tng) (tng) 89 = y Y
keycode (tng) (tng) 90 = z Z
keycode (tng) (tng) 96 = KP_0 KP_0
keycode (tng) (tng) 97 = KP_1 KP_1
keycode (tng) (tng) 98 = KP_2 KP_2
keycode (tng) (tng) 99 = KP_3 KP_3
keycode 100 = KP_4 KP_4
keycode 101 = KP_5 KP_5
keycode 102 = KP_6 KP_6
keycode 103 = KP_7 KP_7
keycode 104 = KP_8 KP_8
keycode 105 = KP_9 KP_9
keycode 106 = KP_Multiply KP_Multiply
keycode 107 = KP_Add KP_Add
keycode 108 = KP_Separator KP_Separator
keycode 109 = KP_Subtract KP_Subtract
keycode 110 = KP_Decimal KP_Decimal
keycode 111 = KP_Divide KP_Divide
keycode 112 = F1
keycode 113 = F2
keycode 114 = F3
keycode 115 = F4
keycode 116 = F5
keycode 117 = F6
keycode 118 = F7
keycode 119 = F8
keycode 120 = F9
keycode 121 = F10
keycode 122 = F11
keycode 123 = F12
keycode 124 = F13
keycode 125 = F14
keycode 126 = F15
keycode 127 = F16
keycode 128 = F17
keycode 129 = F18
keycode 130 = F19
keycode 131 = F20
keycode 132 = F21
keycode 133 = F22
keycode 134 = F23
keycode 135 = F24
keycode 136 = Num_Lock
keycode 137 = Scroll_Lock
keycode 187 = acute grave
keycode 188 = comma semicolon
keycode 189 = minus underscore
keycode 190 = period colon
keycode 192 = numbersign apostrophe
keycode 210 = plusminus hyphen macron
keycode 211 =
keycode 212 = copyright registered
keycode 213 = guillemotleft guillemotright
keycode 214 = masculine ordfeminine
keycode 215 = ae AE
keycode 216 = cent yen
keycode 217 = questiondown exclamdown
keycode 218 = onequarter onehalf threequarters
keycode 220 = less greater bar
keycode 221 = plus asterisk asciitilde
keycode 227 = multiply division
keycode 228 = acircumflex Acircumflex
keycode 229 = ecircumflex Ecircumflex
keycode 230 = icircumflex Icircumflex
keycode 231 = ocircumflex Ocircumflex
keycode 232 = ucircumflex Ucircumflex
keycode 233 = ntilde Ntilde
keycode 234 = yacute Yacute
keycode 235 = oslash Ooblique
keycode 236 = aring Aring
keycode 237 = ccedilla Ccedilla
keycode 238 = thorn THORN
keycode 239 = eth ETH
keycode 240 = diaeresis cedilla currency
keycode 241 = agrave Agrave atilde Atilde
keycode 242 = egrave Egrave
keycode 243 = igrave Igrave
keycode 244 = ograve Ograve otilde Otilde
keycode 245 = ugrave Ugrave
keycode 246 = adiaeresis Adiaeresis
keycode 247 = ediaeresis Ediaeresis
keycode 248 = idiaeresis Idiaeresis
keycode 249 = odiaeresis Odiaeresis
keycode 250 = udiaeresis Udiaeresis
keycode 251 = ssharp question backslash
keycode 252 = asciicircum degree
keycode 253 = 3 sterling
keycode 254 = Mode_switch

字母和数字键的键码?keyCode)
按键 键码 按键 键码 按键 键码 按键 键码
  A
 (tng)65 J 74 S 83 1 49
B 66 K 75 T 84 2 50
C 67 L 76 U 85 3 51
D 68 M 77 V 86 4 52
E 69 N 78 W 87 5 53
F 70 O 79 X 88 6 54
G 71 P 80 Y 89 7 55
H 72 Q 81 Z 90 8 56
I 73 R 82 0 48 9 57
数字键盘?sh)的键的键码?keyCode) 功能键键码?keyCode)
按键 键码 按键 键码 按键 键码 按键 键码
  0
 (tng)96 8 104 F1 112 F7 118
1 97 9 105 F2 113 F8 119
2 98 * 106 F3 114 F9 120
3 99 + 107 F4 115 F10 121
4 100 Enter 108 F5 116 F11 122
5 101 - 109 F6 117 F12 123
6 102   .
 (tng)110 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)
7   103
 (tng)/ 111 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)
控制键键码?keyCode)
按键 键码 按键 键码 按键 键码 按键 键码
BackSpace 8 Esc 27 Right Arrow 39 -_ 189
Tab 9 Spacebar 32 Down Arrow 40 .> 190
Clear 12 Page Up 33 Insert 45 /? 191
Enter 13 Page Down 34 Delete 46 `~ 192
Shift 16 End 35 Num Lock 144 [{ 219
Control 17 Home 36 ;: 186 \| 220
Alt 18 Left Arrow 37 =+ 187 ]} 221
Cape Lock 20 Up Arrow 38 ,< 188 '" 222



zhuyongjp 2009-07-23 17:57 发表评论
]]>
Javal对好文Q{载的http://m.tkk7.com/zhuyongjp/archive/2009/02/27/257077.htmlzhuyongjpzhuyongjpFri, 27 Feb 2009 09:48:00 GMThttp://m.tkk7.com/zhuyongjp/archive/2009/02/27/257077.htmlhttp://m.tkk7.com/zhuyongjp/comments/257077.htmlhttp://m.tkk7.com/zhuyongjp/archive/2009/02/27/257077.html#Feedback1http://m.tkk7.com/zhuyongjp/comments/commentRss/257077.htmlhttp://m.tkk7.com/zhuyongjp/services/trackbacks/257077.html
1Q?关于动态加载机??
学习(fn)Java比C++更容易理解OOP的思想Q毕竟C++q؜合了(jin)不少面向q程的成分。很多h都能背出来Java语言的特点,所谓的动态加载机制等{。当然概念往往是先C而后消化的,可有多少人真正去体会(x)q动态加载的机制Q试囑֎Lq其中的l节? 提供大家一个方法:(x)
在命令行H口q行JavaE序的时候,加上q个很有用的参数Q?

java -verbose *.class

q样?x)清晰的打印(gu)加蝲的类文gQ大部分是jdk自nq行需要的Q最后几行会(x)明显的看到自q到的那几个类文g被加载进来的序。即使你声明?jin)一个类对象Q不实例化也不会(x)加蝲Q说明只有真正用到那个类的实例即对象的时候,才会(x)执行加蝲。这h不是大家E微能明白一点动态加载了(jin)呢?^_^

2Q?关于Lclass文g原理??
大家在入门的时候在命o(h)行窗口编译和q行Q不要借助JCreator或者Eclipse{IDEd助做那些事情。尝试自p样做Q?
javac -classpath yourpath *.java
java -classpath yourpath *.class
也许很多人都能看懂,讄classpath的目的就是告诉编译器d里寻找你的class文g. 不过臛_W者今日才弄懂JVML询类的原理,~译器加载类要依靠classloaderQ?而classloader?个别,从高C分别是BootClassLoader(名字可能不准? , ExtClassLoader, AppClassLoader.

q?个加载器分别对应着~译器去LcL件的优先U别和不同的路径QBootClassLoader对应jre/classes路径Q是~译器最优先Lclass的地?
ExtClassLoader对应jre/lib/ext路径Q是~译器次优先Lclass的地?
AppClassLoader对应当前路径Q所以也是编译器默认找class的地?

其实大家可以自己写个E序单的试Q对MclassQ例如A,
调用new A().getClass().getClassLoader().toString() 打印出来可以看刎ͼ把class文g攑֜不同的\径下再次执行Q就?x)看到区别。特别注意的是如果打印出来是nullpC到?jin)最高 BootClassLoader, 因ؓ(f)它是C++~写的,不存在Java对应的类加蝲器的名字?

L的顺序是一U向上迂回的思想Q即如果本别找不到Q就只能LU别之上的找Q不?x)向下寻找。不q似乎从Jdk1.4到Jdk1.6q一特点又有改变Q没有找到详l资料。所以就不D例子?jin)。告诉大家设计这U体pȝ是Sun公司曄的技术核?j)宫力先生,一个纯U华人哦Q^_^

q样希望大家不至于迷惑ؓ(f)什么L错找不到cLӞ不管是自己写的还是导入的W三方的jar文gQJ2ee中经帔R要导入的Q?

3Q?关于jdk和jre??
大家肯定在安装JDK的时候会(x)有选择是否安装单独的jreQ一般都?x)一起安装,我也大家q样做。因h能帮助大家弄清楚它们的区别:(x)

Jre 是java runtime environment, 是javaE序的运行环境。既然是q行Q当然要包含jvmQ也是大家熟?zhn)的虚拟机啦?q有所有javacd的class文gQ都在lib目录下打包成?jin)jar。大家可以自己验证。至于在windows上的虚拟机是哪个文g呢? 学过MFC的都知道什么是dll文g吧,那么大家看看jre/bin/client里面是不是有一个jvm.dll呢?那就是虚拟机?

Jdk 是java development kitQ是java的开发工具包Q里面包含了(jin)各种cd和工兗当然也包括?jin)另外一个Jre. 那么Z么要包括另外一个Jre呢?而且jdk/jre/bin同时有client和server两个文g夹下都包含一个jvm.dll?说明是有两个虚拟机的。这一点不知道大家是否注意C(jin)呢?

怿大家都知道jdk的bin下有各种javaE序需要用到的命o(h)Q与jre的bin目录最明显的区别就是jdk下才有javacQ这一点很好理解,因ؓ(f) jre只是一个运行环境而已。与开发无养I正因为如此,具备开发功能的jdk自己的jre下才?x)同时有client性质的jvm和server性质?jvmQ?而仅仅作行环境的jre下只需要client性质的jvm.dll够?jin)?

记得在环境变量path中设|jdk/bin路径麽?q应该是大家学习(fn)Java的第一步吧Q?老师?x)告诉大家不讄的话javac和java是用不了(jin)的。确实jdk/bin目录下包含了(jin)所有的命o(h)。可是有没有人想q我们用的java命o(h)q不?jdk/bin目录下的而是jre/bin目录下的呢?不信可以做一个实验,大家可以把jdk/bin目录下的java.exe剪切到别的地方再q行 javaE序Q发C(jin)什么?一切OKQ?

那么有h?x)问了(jin)?我明明没有设|jre/bin目录到环境变量中啊?

试想一下如果javaZ(jin)提供l大多数Z用,他们是不需要jdk做开发的Q只需要jre能让javaE序跑v来就可以?jin),那么每个客户q需要手动去讄环境变量多麻?ch)啊Q所以安装jre的时候安装程序自动帮你把jre的java.exedC(jin)pȝ变量中,验证的方法很单,大家看到?jin)系l环境变量的 path最前面有?SystemRoot%\system32;%SystemRoot%;”这L(fng)配置Q那么再去Windows/system32下面ȝ看吧Q发C(jin)什么?有一个java.exe?

如果能够把jdk/bin挪到system32变量前面Q当然也可以q使用jdk/jre里面的javaQ不q除非有必要Q我不徏议大家这么做。用单独的jre跑javaE序也算是客L(fng)境下的一U测试?

q下大家应该更清楚jdk和jre内部的一些联pd区别?jin)吧Q?

PS: 其实q有满多感想可以ȝ的,一ơ写多了(jin)怕大家扔砖头砸死我,怪我太罗唆。大家应该更加踏实更加务实的d一些研Iƈ互相分n?j)得Q大方向和太前沿的技术讨论是必要的但最好不要太多,毕竟自己基础都还没打好,什么都讲最新版本其实是q步的一大障!


Java 学习(fn)杂谈Q二Q?/strong> (tng)

鉴于上回写的一Ҏ(gu)惛_家不嫌弃Q都鼓励弟l箋(hu)写下去,好不Ҏ(gu){到国庆(jin)黄金周,实习(fn)ȝ有一个休息的阶段Q于是这开始写W二了(jin)。希望这ơ写的仍然对志同道合的朋友们有所帮助。上回讲?jin)Java动态加载机制、classLoader原理和关于jdk和jre三个问题。这ơgl着讲一些具体的cd??

1Q?关于集合框架c?
怿学过Java的各位对q个名词q不陌生Q对 java.util.*q个package肯定也不陌生。不知道大家查询API的时候怎么d视或者分析其中的一个packageQ每个包最重要的两个部分就是interfaces和classesQ接口代表了(jin)它能做什么,实现cd代表?jin)它如何d。关注实现类之前Q我们应该先理解清楚它的来源接口Q不在j2seq是j2ee中,都应该是q样。那么我们先看这三个接口QList、Set、Map?
也许有些Z太熟(zhn)这三个名字Q但怿大部分h都熟(zhn)ArrayListQLinkedListQTreeSetQHashSetQHashMapQ?Hashtable{实现类的名字。它们的区别也是满容易理解的QList攑֏以重复的对象集合QSet放不可重复的对象l合Q而Map则放 <Key,Value > q样的名值对Q?Key不可重复QValue可以。这里有几个Ҏ(gu)h的问题:(x)

到底Vector和ArrayListQHashtable和HashMap有什么区别?
很多面试官喜Ƣ问q个问题Q其实更专业一点应该这样问Q新集合框架和旧集合框架有哪些区别?新集合框架大家可以在q些包中找since jdk1.2的,之前的如vector和Hashtable都是旧的集合框架包括的类。那么区别是Q?
a. 新集合框架的命名更加U学合理。例如List下的ArrayList和LinkedList
b. 新集合框架下全部都是非线E安全的。徏议去jdk里面包含的源代码里面自己M自看看vector和ArrayList的区别吧。当然如果是jdk5.0之后的会(x)比较隄一点,因ؓ(f)又加入了(jin)泛型的语法,cMc++的template语法?

那么大家是否惌Z么要从旧集合框架默认全部加锁防止多线E访问更新到新集合框架全部取消锁Q默认方式支持多U程Q?当然需要的时候可以用collections的静(rn)态方法加锁达到线E安?
W者的观点是Q何技术的发展都未必是遵@它们的初L(fng)Q很多重大改变是受到客观环境的媄(jing)响的。大家知道Java的初hZ么而开发的麽?是ؓ(f)嵌入式程序开发的。记得上一讲到classLoader机制麽?那正是ؓ(f)?jin)节U嵌入式开发环境下内存而设计的。而走C天,Java成了(jin)Z?j)中Z联网诞生的语a。互联网意味着什么?多线E是必然的趋ѝ客观环境在变,Java技术也随着飞速发展,D来脱d的初街据说Sun公司其实L的是J2seQ结果又是由于客观环境媄(jing)响,J2se几乎遗忘Q留在大家谈论焦点的一直是j2ee?

技术的l节q里׃多说?jin),只有用?jin)才能真正理解。解释这些正是ؓ(f)?jin)帮助大家理解正在学的和要学的M技术。之后讲j2ee的时候还?sh)(x)再讨论?
多扯句题外话Q几十年前的IT巨h是IBMQMainframe?jng)场无h可比。微软如何打败IBMQ正是由于硬仉速发展,对个人PC的需求这个客观环境,让微软通过OSUCؓ(f)?jin)第二个巨h。下一个打败微软的呢?Google。如何做到的Q如果微软ƈ不和IBM争大型机QGoogle借着互联|飞速发展这个客观环境作为决定性因素,避开跟微软争OSQ而是走搜索引擎这条\Q称为第3个巨人。那么第4个巨人是谁呢Q很多专安a在亚洲或者中国出玎ͼ WhateverQ客观环境变化趋势才是决定大方向的关键。当然笔者也希望?x)出现在中国Q^_^~~

2Q?关于Java设计模式
w边的很多在看GOF?3U设计模式,g学习(fn)它无论在学校q是在职场,都成?jin)一U流行风气。我不想列D解释q?3UDesign PatternQ?我写q些的初衷一直都是谈自己的经历和看法Q希望能帮助大家理解?
首先我觉得设计模式只是对一c问题的一U通用解决办法Q只要是面向对象的编E预a都可以用得上q?3U。理解它们最好的Ҏ(gu)是亲自d每一U,哪怕是一个简单的应用p够了(jin)。如果代码实CC住的话,记忆它们对应的UML图会(x)是一个比较好的办法,当然前提是必M(jin)解UML?
同时最好能利用Java自n的类库帮助记忆,例如比较常用的观察者模式,在java.util.*有现成的Observer接口和Observableq个实现c,看看源代码相信就_理解观察者模式了(jin)。再比如装饰器模式,大家只要写几个关于java.io.*的程序就可以完全理解什么是装饰器模式了(jin)。有很多得刚入门的时候不该接触设计模式,比如囄设计丛书pd很出名的那本《Java设计模式》,作? Steven John MetskerQ大部分例子老实说o(h)现在的我也很qh。但我仍然不同意入门跟学?fn)设计模式有M冲突Q只是我们需要知道每U模式的概念的和典型的应用,q样我们在第一ơ编?FileOutputStream、BufferedReader、PrintWriter的时候就能感觉到原来设计模式L们如此之q,而且q不是多么神U的东西?

另外Q在学习(fn)某些模式的同Ӟ反而更能帮助我们理解javacd的某些特炏V例如当你编写原?Prototype)模式的时候,你必M(jin)解的?java.lang.Cloneableq个接口和所有类的基cObject的clone()q个Ҏ(gu)。即深copy和浅copy的区别:(x)
Object.clone()默认实现的是copyQ也是复制一份对象拷贝,但如果对象包含其他对象的引用Q不?x)复制引用,所以原对象和拷贝共用那个引用的对象?
深copy当然是包括对象的引用都一起复制啦。这样原对象和拷贝对象,都分别拥有一份引用对象。如果要实现深copy必首先实?java.lang.Cloneable接口Q然后重写clone()Ҏ(gu)。因为在Object中的clone()Ҏ(gu)是protected{֐的,?Cloneable接口的作用就是把protected攑֤到publicQ这样clone()才能被重写?

那么又有个问题(sh)(jin)Q如果引用的对象又引用了(jin)其他对象呢?q样一直判断ƈ复制下去Q是不是昑־很麻?ch)?曄有位前辈告诉我的?gu)是重写cloneҎ(gu)的时候直接把原对象序列化到磁盘(sh)再反序列化回来,q样不用判断可以得C个深copy的结果。如果大家不?jin)解序列化的作法看一?ObjectOutputStream和ObjectInputStream

归根l底Q模式只是思想上的东西Q把它当成前人ȝ的经验其实一炚w不ؓ(f)q。鼓励大家动手自己去写,例如代理模式Q可以简单的写一个Childc, AdultcRChild要买M东西由Adult来代理实现。简单来说就是Adult里的buy()内部实际调用的是Child的buy()Q可是暴露在main函数的却是Adult.buy()。这样一个简单的E序p够理解代理模式的基本含义?jin)?

Java 杂谈Q三Q?/strong> (tng)

q已l笔者写的第三篇Java杂记?jin),庆(jin)幸前两一直得到论坛朋友们的支持鼓励,q望大家l箋(hu)指正不之处。笔者也一直(f)望通过q样方式清醒的自审,来寻找自己技术上的不之处,希望和共同爱好Java的同仁们一h高?
前两ơ分别讲qC(jin)关于jvm、jdk、jre、collection、classLoader和一些Design Pattern的自我理解。这ơ仍然不准备开始过渡到j2ee中,因ؓ(f)觉得q有一些琐的j2se的问题没有ȝ完毕?

1Q?关于Objectcȝ?
大家都知道Object是所有Javacȝ基类Q?意味着所有的Javac都?x)承?jin)Object?1个方法。徏议大家去看看Object?11个成员函数的源代码,׃(x)知道默认的实现方式。比如equalsҎ(gu)Q默认实现就是用"=="来比较,即直接比较内存地址Q返回true 或?false。而toString()Ҏ(gu)Q返回的串组成方式是??
"getClass().getName() + "@" + Integer.toHexString(hashCode())"
其实不用我过多的解释Q大安能看懂这个串的组成。接下来再看看hashCode()Q?
public native int hashCode()Q?

׃是nativeҎ(gu)Q跟OS的处理方式相养I源代码里仅仅有一个声明Ş?jin)。我们有兴趣的话完全可以LI它的hashCode到底是由O(jin)S怎么样生的呢?但笔者徏议最重要的还是先C使用它的几条原则吧!首先如果equals()Ҏ(gu)相同的对象具有相通的hashCodeQ但equals ()对象不相通的时候ƈ不保证hashCode()Ҏ(gu)q回不同的整数。而且下一ơ运行同一个程序,同一个对象未必还是当初的那个hashCode() 哦?
其余的方法呢Qnofigy()、notifyAll()、clone()、wait()都是nativeҎ(gu)的,说明依赖于操作系l的实现。最后一个有的Ҏ(gu)是finalize()Q类似C++的析构函敎ͼ{֐是protectedQ证明只有承扩展了(jin)才能使用Q方法体是空的,默示什么也不做。它的作用据W者的?jin)解仅仅是通知JVM此对象不再用,随时可以被销毁,而实际的销毁权q是在于虚拟机手上。那么它真的什么也不做麽?未必Q实际上如果是线E对象它?x)导致在一定范围内该线E的优先U别提高Q导致更快的被销毁来节约内存提高性能。其实从常理来说Q我们也可以大概q样猜测出jvm做法的目的?

2Q?关于重蝲hashCode()与Collection框架的关p?
W者曾l听一位搞Java培训多年的前辈说在他看来hashCodeҎ(gu)没有M意义Q仅仅是Z(jin)配合证明h同样的hashCode?x)导致equals Ҏ(gu)相等而存在的。连有的前辈都犯q样的错误,其实说明它还是满Ҏ(gu)被忽略的。那么hashCode()Ҏ(gu)到底做什么用Q?

学过数据l构的课E大安?x)知道有一U结构叫hash tableQ目的是通过l每个对象分配一个唯一的烦(ch)引来提高查询的效率。那么Java也不?x)肆意扭曲改变这个概念,所以hashCode唯一的作用就是ؓ(f)支持数据l构中的哈希表结构而存在的Q换句话_(d)也就是只有用到集合框架的 Hashtable、HashMap、HashSet的时候,才需要重载hashCode()Ҏ(gu)Q?
q样才能使得我们能h为的L制在哈希l构中烦(ch)引是否相{。笔者D一个例子:(x)
曄Z(jin)写一个求解类E序Q需要随机列?,2,3,4l成的不同排列组合,所以笔者写?jin)一个数l类用int[]来存l合l果Q然后把随机产生的组合加入一个HashSet中,是惛_用HashSet不包括重复元素的特点。可是HashSet怎么判断是不是重复的元素呢?当然是通过 hashCode()q回的结果是否相{来判断啦,可做一下这个实验:(x)
int[] A = {1,2,3,4};
int[] B = {1,2,3,4};
System.out.println(A.hashCode());
System.out.println(B.hashCode());

q明明是同一U组合,却是不同的hashCodeQ加入Set的时候会(x)被当成不同的对象。这个时候我们就需要自己来重写hashCode()Ҏ(gu)?jin),如何写呢Q其实也是基于原始的hashCode()Q毕竟那是操作系l的实现Q?扑ֈ盔R对象唯一的标识,实现方式很多Q笔者的实现方式是:(x)
首先重写?jin)toString()Ҏ(gu):
return A[0]??A[1]??A[2]??A[3]; //昄上比较直?
然后利用toString()来计hashCode()Q?
return this.toString().hashCode()Q?
q样上述A和Bq回的就都是?234”,在测试toString().hashCode()Q由于String在内存(sh)的副本是一L(fng)Q?234?hashCode()q回的一定是相同的结果?

说到q,怿大家能理解得比我更好Q今后千万不要再误解hashCode()Ҏ(gu)的作用?

3Q?关于Classcȝ成员函数与Java反射机制
很早刚接触Java听很多老师说过Java的动态运行时机制、反机制等。确实它们都是Java的显著特点,q行时加载笔者在W一介l过?jin),现在惌讲反机制。在Java中,主要是通过java.lang包中的ClasscdMethodcL实现内存反射机制的?
熟?zhn)C++的h一定知道下面这样在C++中是做不到的Q?q行时以字符串参C递一个类名,可以得到这个类的所有信息,包括它所有的Ҏ(gu)Q和Ҏ(gu)的详l信息。还可以实例化一个对象,q过查到的方法名来调用该对象的Q何方法。这是因为Java的类在内存(sh)除了(jin)C++中也有的?rn)态动态数据区之外Q还包括一份对c自w的描述Q也正是通过q描qC的信息,才能帮助我们才运行时d里面的内容,得到需要加载目标类的所有信息,从而实现反机制。大家有没有惌当我们需要得C个JavaBean的实例的时候,怎么知道它有哪些属性呢Q再明显单不q的例子是自己写一个JavaBean的解析器Q?

a. 通过Class.forName(“Bean的类名?得到Class对象Q例如叫ABeanClass
b. 通过ABeanClass的getMethods()Ҏ(gu)Q得到Method[]对象
c. 按照规范所有getҎ(gu)名后的单词就代表着该Bean的一个属?
d. 当已l知道一个方法名Q可以调用newInstance()得到一个实例,然后通过invoke()Ҏ(gu)方法的名字和方法需要用的参C递进去,可以动态调用此Ҏ(gu)?

当然q有更复杂的应用Q这里就不赘qͼ大家可以参考ClasscdMethodcȝҎ(gu)?

4Q?坦言Synchronize的本?
Synchronize大家都知道是同步、加锁的意思,其实它的本质q没有大家想得那么复杂。声明Synchronize的方法被调用的时候,锁其实是加蝲对象上,当然如果是静(rn)态类则是加在cM的锁Q调用结束锁被解除。它的实现原理很单,仅仅是不让第二把锁再ơ被加在同一个对象或cMQ仅此而已。一个简单的例子以说明问题Q?
class A{
synchronized void f(){}
void g(){}
}

当A的一个对象a被第一个线E调用其f()Ҏ(gu)的时候,W二个线E不能调用a的synchronizedҎ(gu)例如f()Q因为那是在试图在对象上加第二把锁。但调用g()却是可以的,因ؓ(f)q没有在同一对象上加两把锁的行ؓ(f)产生?
q样大家能理解了(jin)麽?明白它的原理能更好的帮助大家设计同步机制Q不要滥用加锁?

PSQ下笔者计划开始对J2ee接触到的各个斚w来进行ȝQ谈谈自ql验和想法。希望大家还能一如既往的支持笔者写下去Q指正不之处?

Java杂谈Q四Q?/strong>

不知不觉已经写到W四了(jin)Q论坛里面不断的有朋友鼓励我写下厅R坚持自q作风Q把一切迷惑不Ҏ(gu)理清楚的知识讲出来,讲到大家都能听懂Q那么自己就真的懂了(jin)。最q在公司实习(fn)的时候Trainer跟我讲了(jin)很多l典事迹Q对q未毕业的我来说是笔不小的胦(ch)富,我自q信念是:(x)人在逆境中成长的速度要远q快q顺境中Q这h看一切都能欣然接受了(jin)?
好了(jin)Q闲话不说了(jin)Q第三篇讲的是反机刉合框架之cȝQ这ơ打讲讲自己对反序列化和多U程的理解。希望能对大家学?fn)Java起到帮助??

1Q关于序列化和反序列?
应该大家都大概知道Java中序列化和反序列化的意思,序列化就是把一个Java对象转换成二q制q行盘?sh)传输或者网l流的传输,反序列化的意思就是把q个接受到的二进制流重新l装成原来的对象逆过E。它们在Java中分别是通过ObjectInputStream?ObjectInputStreamq两个类来实现的Q以下分别用ois和oos来简Uͼ(j)?

oos的writeObject()Ҏ(gu)用来执行序列化的q程Qois的readObject()用来执行反序列化的过E,在传输二q制之前,需要讲q两个高层流对象q接到同一个Channel上,q个Channel可以是磁盘文Ӟ也可以是socket底层。所以无论用哪种方式Q底层流对象都是以构造函数参数的形式传递进oos和oisq两个高层流Q连接完毕了(jin)才可以进行二q制数据传输的。例子:(x)
可以是文件流通道
file = new File(“C:/data.dat?;
oos = new ObjectOutputStream(new FileOutputStream(file));
ois = new ObjectInputStream(new FileInputStream(file));

或者网l流通道
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());

不知道大家是否注意到oosL在ois之前定义Q这里不希望大家误解q个序是固定的么?回答是否定的Q那么有序要求么?回答是肯定的。原则是什么呢Q?
原则是互相对接的输入/输出之间必Loutput先初始化然后再input初始化Q否则就?x)抛异常。大家肯定会(x)问ؓ(f)什么?只要E微看一看这两个cȝ源代码文件就大概知道?jin),output的d很简单,只要把对象{换成二进制往通道中写可以了(jin)Q但input需要做很多准备工作来接受ƈ最l重l这个ObjectQ所以ObjectInputStream的构造函C需要用到output初始化发送过来的header信息Q这个方法叫?readStreamHeader()Q它?yu)?x)去读两个Short值用于决定用多大的缓存来存放通道发送过来的二进制流Q这个缓存的size因jre的版本不同是不一L(fng)。所以output如果不先初始化,input的构造函数首先就无法正确q行?

对于上面两个例子Q第一个顺序是严格的,W二个因为oos和oisq接的已l不是对方了(jin)Q而是socket另外一端的,需要严格按照另外一方对接的output先于对接的input打开才能利q行?

q个writeObject和readObject本n是U程安全的,传输q程中是不允许被q发讉K的。所以对象能一个一个接q不断的传过来,有很多h在运行的时候会(x)到EOFException, 然后百思不得其解,dU论坛问解决Ҏ(gu)。其实笔者这里想_(d)q个异常不是必须声明的,也就是说它虽然是异常Q但其实是正常运行结束的标志。EOF表示d?jin)文件尾Q发送结束自然连接也断开?jin)。如果这影响C(jin)你程序的正确性的话,请各位静(rn)下心(j)来看看自q序的业务逻辑Q而不要把注意力狭隘的聚集在发送和接受的方法上。因为笔者也被这L(fng)bug困扰?整天Q被很多论坛的帖子误解了(jin)很多ơ最后得出的教训。如果在while循环中去readObjectQ本质上是没有问题的Q有对象数据来就?x)读Q没有就自动d。那么抛出EOFException一定是因ؓ(f)q接断了(jin)q在l箋(hu)readQ什么原因导致连接断?jin)呢Q一定是业务逻辑哪里存在错误Q比如NullPoint?ClassCaseException、ArrayOutofBoundQ即使程序较大也没关p,最多只要单步调适一ơ就能很快发现bugq且解决它?

难怪一位程序大师说q:(x)解决问题90Q靠l验Q?Q靠技术,剩下5Q靠q气Q真是金玉良aQ笔者大概查阅过不下30讨论在while循环中?readObject抛出EOFExceptionde 的帖子,大家都盲目的d注解释这个名词、反序列化的行ؓ(f)或反对这样写而没有一个h认ؓ(f)EOF是正的行ؓ(f)Q它其实很老实的在做它的事情。ؓ(f)什么大安忽略?jin)真正出错误的地方呢Q两个字Q经验!

2Q关于Java的多U程~程
关于Java的线E,初学或者接触不q大概也能知道一些基本概念,同时又会(x)很迷惑线E到底是怎么回事Q如果有己已l懂?jin)不妨来回答下面的问题?x)
a. A对象实现Runnable接口QA.start()q行后所谓的U程对象是谁Q是A么?
b. U程的wait()、notify()Ҏ(gu)到底是做什么时候用的,什么时候用Q?
c. Z么线E的suspendҎ(gu)?x)被标注q时Q不推荐再用,U程q能挂v么?
d. Z(jin)同步我们?x)对U程Ҏ(gu)声明Synchronized来加锁在对象上,那么如果父类的f()Ҏ(gu)加了(jin)SynchronizedQ子c重写f()Ҏ(gu)必须也加Synchronized么?如果子类的f()Ҏ(gu)重写时声明Synchronizedq调用super.f()Q那么子cd象上到底有几把锁呢??x)因为竞争生死锁么Q?

呵呵Q各位能回答上来几道呢?如果q些都能{上来,说明对线E的概念q是满清晰的Q虽说还q远不能精通。笔者这里一一做回{,于幅的原因,W者尽量说得简介一点,如果大家有疑惑的Ƣ迎一赯论?

首先W一点,U程跟对象完全是两回事,虽然我们也常说线E对象。但当你用run()和start()来启动一个线E之后,U程其实跟这个承了(jin) Thread或实C(jin)Runnable的对象已l没有关pM(jin)Q对象只能算内存?sh)可用资源而对象的Ҏ(gu)只能内存正文区可以执行的代码段而已。既然是资源和代码段Q另外一个线E当然也可以去访问,main函数执行p会(x)启动两个U程Q一个我们称之ؓ(f)ȝE,q(sh)个是垃圾攉器的U程Q主U程l束意味着E序l束Q可垃圾攉器线E很可能正在工作?

W二点,wait()和sleep()cMQ都是让U程处于d状态暂停一D|_(d)不同之处在于wait?x)释攑ֽ前线E占有的所有的锁,?sleep不会(x)。我们知道获得锁的唯一Ҏ(gu)是进入了(jin)Synchronized保护代码D,所以大家会(x)发现只有SynchronizedҎ(gu)中才?x)出?waitQ直接写?x)给警告没有获得当前对象的锁。所以notify跟wait配合使用Qnotify?x)重新把锁还l阻塞的U程重而其l执行,当有多个对象wait?jin),notify不能定唤醒哪一个,必经锁只有一把,所以一般用notifyAll()来让它们自己Ҏ(gu)优先U等竞争那唯一的一把锁Q竞争到的线E执行,其他U程只要l箋(hu)wait?

从前Java允许在一个线E之外把U程挂vQ即调用suspendҎ(gu)Q这L(fng)操作是极不安全的。根据面向对象的思想每个对象必须对自q行ؓ(f)负责Q而对自己的权力进行封装。如果Q何外步对象都能ɾU程被挂赯(g)阻塞的话,E序往往?x)出现؜乱导致崩溃,所以这L(fng)Ҏ(gu)自然是被毙掉?jin)啦?

最后一个问题比较有意思,首先回答的是子类重写f()Ҏ(gu)可以加Synchronized也可以不加,如果加了(jin)而且q内部调用了(jin)super.f ()的话理论上是应该对同一对象加两把锁的,因ؓ(f)每次调用SynchronizedҎ(gu)都要加一把,调用子类的f首先加?jin)一把,q入Ҏ(gu)内部调用父类?f又要加一把,加两把不是互斥的么?那么调父cf加锁不就必须永远{待已经加的锁释放而造成死锁么?实际上是不会(x)的,q个机制叫重q入Q当父类的fҎ(gu)试图在本对象上再加一把锁的时候,因ؓ(f)当前U程拥有q个对象的锁Q也可以理解为开启它的钥匙,所以同一个线E在同一对象上还没释放之前加W二ơ锁是不?x)出问题的,q个锁其实根本就没有加,它有?jin)钥匙,不管加几把还是可以进入锁保护的代码段Q畅通无阻,所以叫重进入,我们可以单认为第二把锁没有加上去?

总而言之,Synchronized的本质是不让其他U程在同一对象上再加一把锁。?br />
Java杂谈Q五Q?/strong>

本来预计J2se只讲?jin)第四篇收?jin)Q可是版d爱把帖子|顶长期让大家浏览让弟倍感责Q重大Q务必追求最到更好,所以关于J2se一些没有提到的部分Q决定再写几把常用的部分经验全部写出来供大家讨论切。这一准备讲一讲Xml解析包和Java SwingQ然后下一再讲java.security包关于Java沙箱安全机制和RMI机制Q再q入J2ee的部分,暂时做q样的计划了(jin)。如果由于实?fn)繁忙更新稍微慢了(jin)一些,希望各位见谅Q?

1Q?Java关于XML的解?
怿大家对XML都不陌生Q含义是可扩展标记语a。本w它也就是一个数据的载体以树(wi)状表现Ş式出现。后来慢慢的数据变成?jin)信息,区别是信息可以包括可变的状态从而针对程序硬~码的做法变革ؓ(f)针对l一接口编码而可变状态作Z息进入了(jin)XML中存储。这h变状态实现扩展的唯一工作是在XML中添加一D|本信息就可以?jin),代码不需要改动也不需要重新编译。这个灵zL是XML诞生时候谁也没惛_的?

当然Q如果接口要能提取XML中配|的信息需要程序能解析规范的XML文gQJava中当然要提高包对q个行ؓ(f)q行有利支持。笔者打讲到的两个包是 org.w3c.dom和javax.xml.parsers和。(大家可以览一下这些包中间的接口和cd义)(j)

Javax.xml.parsers包很单,没有接口Q两个工厂配两个解析器。显然解析XML是有两种方式的:(x)DOM解析和SAX解析。本质上q没有谁好谁不好Q只是实现的思想不一L(fng)Ş?jin)。给一个XML文g的例子:(x)
<?xml version=?.0?encoding=”UTF-8?>
<root >
<child name=”Kitty?>
A Cat
</child >
</root >

所谓DOM解析的思\是把整个?wi)状囑֭入内存?sh)Q需要那个节点只需要在?wi)上搜?ch)可以读到节点的属性,内容{,q样的好处是所有节点皆在内存可以反复搜索重复用,~点是需要消耗相应的内存I间?

自然SAX解析的思\是Z(jin)克服DOM的缺点,以事件触发ؓ(f)基本思\Q顺序的搜烦(ch)下来Q碰C(jin)Element之前触发什么事Ӟ到之后做什么动作。由于需要自己来写触发事件的处理Ҏ(gu)Q所以需要借助另外一个自定义的HandlerQ处于org.xml.sax.helpers包中。它的优点当然是不用整个包都d内存Q缺点也是只能顺序搜索,走完一遍就得重来?

大家很容易就能猜刎ͼ接触到的J2ee框架用的是哪一U,昄是DOM。因为类似StrutsQHibernate框架配置文g毕竟是很的一部分配置信息Q而且需要频J搜索来dQ当然会(x)采用DOM方式Q其实SAX内部也是用DOM采用的结构来存储节点信息的)(j)。现在无论用什么框Ӟq真隑֏C?SAX来解析XML的技术了(jin)Q如果哪位仁兄知道,误W者也学习(fn)学习(fn)?

既然解析方式有了(jin)Q那么就需要有解析的存储位|。不知道大家是否发现org.w3c.domq个包是没有实现cd部都是接口的。这里笔者想说一下Java 如何对XML解析是Jdk应该考虑的事Q是它的责Q。而w3cl织是维护定义XML标准的组l,所以一个XMLl构是怎么L(fng)由w3c说了(jin),它不兛_(j) Java如何d玎ͼ于是乎规定了(jin)所有XML存储的结构应该遵循的规则Q这是org.w3c.dom里全部的接口目的所在。在W者看来,单理解接口的概念是实现者必遵守的原则?

整个XML对应的结构叫Document、子元素对应的叫做Element、还有节点相关的Node、NodeList、Text、Entity?CharacterData、CDATASection{接口,它们都可以在XML的语法中间找到相对应的含义。由于这里不是讲解XML基本语法Q就不多介绍?jin)。如果大家感兴趣Q笔者也可以专门写一关于XML的语法规则帖与大家分享一下?

2Q?Java Swing
Swing是一个让人又爱又恨的东西Q可׃处在于上手很Ҏ(gu)Q较AWT比v来Swing提供的界面功能更加强大,可恨之处在于~复杂的界面工作量实在是巨大。笔者写q超q?000行的Swing界面Q感觉用户体验还?sh)是那么优秀。最q又写过过6000行的Q由于功能模块多?jin),整体效果q只是一般般。体?x)最q׃个字Q篏! 所以大家现在都陆箋(hu)不怎么用Swing在真正开发的目上了(jin)Q太多界面技术可以取代它?jin)。笔者去写也是迫于无奈组里面大家都没写过Q我不入地域谁入Q?

管Swing慢慢的在被h忽略Q特别是随着B/S慢慢的在Ҏ(gu)C/SQ笔者倒是很愿意站出来为Swing正n。每一Ҏ(gu)术的掌握l不是ؓ(f)?jin)流行时跟风。真正喜ƢJava的朋友们q是应该好好体会(x)一下SwingQ相信在校的很多学生也很多在学习(fn)它。很可能从Jdk 1.1?.2走过来的很多大学老师可能是最不熟(zhn)它的?
Swing提供?jin)一l轻lgl称为JComponentQ它们与AWTlg的最大区别是JComponent全部都是ContainerQ?Container的特Ҏ(gu)里面可以装蝲别的lg。在Swinglg中无论是JButton、JLabel、JPanel、JList{都可以再装入Q何其他组件。好处是E序员可以对Swinglg实现“再开发”,针对特定需求构q按钮、标{、画ѝ列表之cȝ特定lg?

有轻自然有重,那么ȝ件和重组件区别是Q重lg表现出来的Ş态因操作pȝ不同而异Q轻lg是Swing自己提供GUIQ在跨^台的时候最大程度的保持一致?
那么在编E的时候要注意一些什么呢Q笔者谈谈自q几点l验Q?

a. 明确一个概念,只有Framelg才可以单独显C的Q也许有Z(x)说JOptionPane里面的静(rn)态方法就实现?jin)单独窗口出玎ͼ但追L代码?x)发现其实现实出来的Dialog也需要依托(sh)个FrameH体Q如果没有指定就?x)默认生一个然后装载这个Dialog昄出来?

b. JFrame是由q么几部分组成:(x)
最底下一层JRootPaneQ上面是glassPane (一个JPanel)和layeredPane (一个JLayeredPane)Q而layeredPane又由contentPane(一个JPanel)和menuBar构成。我们的lg都是加在 contentPane上,而背景图片只能加在layeredPane上面?至于glassPane是一个透明的覆盖了(jin)contentPane的一层,在特定效果中被利用到来记录鼠标坐标或掩饰组件?

c. Z(jin)增强用户体验Q我们会(x)在一些按钮上d快捷键,但Swing里面通常只能识别键盘的Alt键,要加入其他的快捷键,必须自己实现一个ActionListener?

d. 通过setLayout(null)可以使得所有组件以setBounds()的四个参数来_定位各自的大、位|,但不推荐使用Q因为好的编E风g应该在Swing代码中硬~码具体数字Q所有的数字应该以常数的形式l一存在一个静(rn)态无实例资源cL件中。这个静(rn)态无实例cȝ一负责Swing界面的风|包括字体和颜色都应该包括q去?

e. 好的界面设计有一条Golden Rule: 用户不用M手册通过数试p学会(x)使用软g。所以尽量把按钮以菜单的形式Q不是右键菜单q是H体自带剙菜单Q呈现给֮Q除非是频繁点击的按钮才有必要直接呈现在界面中?

其实Swing的功能是相当强大的,只是现在应用不广泛,专门ȝI大概是要花不少旉的。笔者在各网站论坛浏览关于Swing的技巧文章还是比较可信的Q自己所学非常有限,各h体会(x)对Swing各个lg的掌握就是一个实늧累的q程。笔者只用到q以上这些,所以只能谈谈部分想法,q望大家见谅Q?br />
Java杂谈Q六Q?

q篇是笔者打写的J2se部分的最后一了(jin)Q这结束之后,再写J2ee部分Q不知道是否q合适写在这个版块?大家可以l点意见Q谢谢大家对弟q么鼓励一路写完前六篇Java杂谈的J2se部分。最后这打谈一谈Java中的RMI机制和JVM沙箱安全框架?

1Q?Java中的RMI机制
RMI的全U是q程Ҏ(gu)调用Q相信不朋友都听说q,基本的思\可以用一个经典比Ҏ(gu)解释QA计算机想要计一个两个数的加法,但A自己做不?jin),于是叫另外一台计机B帮忙QB有计加法的功能QA调用它就像调用这个功能是自己的一hѝ这个就叫做q程Ҏ(gu)调用?jin)?

q程Ҏ(gu)调用是EJB实现的支柱,建立分布式应用的核心(j)思想。这个很好理解,再拿上面的计加法例子,A只知道去call计算机B的方法,自己q没有B的那些功能,所以A计算机端无法看到B执行q段功能的过E和代码Q因为看都看不到Q所以既没有Z(x)H取也没有机?x)去改动?gu)代码。EJB正式Zq样的思想来完成它的Q务的。当单的加法变成复杂的数据库操作和电(sh)子商务交易应用的时候,q样的安全性和分布式应用的便利性就表现出来优势?jin)?

好了(jin)Q回到细节上Q要如何实现q程Ҏ(gu)调用呢?我希望大家学?fn)Q何技术的时候可以试着依赖自己的下意识判断Q只要你的想法是合理健壮的,那么很可能实际上它就是这么做的,毕竟真理都蕴藏在q_的生zȝ节中。这样只要带着一些薄qJava基础来思考RMIQ其实也可以惛_个大概来?

a) 需要有一个服务器角色Q它拥有真正的功能代码方法。例如BQ它提供加法服务
b) 如果惌E用B的功能,需要知道B的IP地址
c) 如果惌E用B的功能,q需要知道B中那个特定服务的名字

我们很自然可以想到这些,虽然不完善,但已l很接近正确的做法了(jin)。实际上RMI要得以实现还得意于Java一个很重要的特性,是Java反射机制。我们需要知道服务的名字Q但又必隐藏实现的代码Q如何去做呢Q答案就是:(x)接口Q?
举个例子Q?
public interface Person(){
public void sayHello();
}

Public class PersonImplA implements Person{
public PersonImplA(){}

public void sayHello(){ System.out.println(“Hello!?;}
}

Public class PersonImplB implements Person{
public PersonImplB(){}

public void sayHello(){ System.out.println(“Nice to meet you!?;}
}

客户端:(x)Person p = Naming.lookup(“PersonService?;
p.sayHello();

p几段代码包含了(jin)几乎所有的实现技术,大家怿么?客户端请求一个say hello服务Q服务器q行时接到这个请求,利用Java反射机制的Class.newInstance()q回一个对象,但客L(fng)不知道服务器q回的是 ImplAq是ImplBQ它接受用的参数{֐是PersonQ它知道实现?jin)Person接口的对象一定有sayHello()Ҏ(gu)Q这意味着客户端ƈ不知道服务器真正如何d现的Q但它通过?jin)解Person接口明确?jin)它要用的服务方法名字叫做sayHello()?

如此cLQ服务器只需要暴露自q接口出来供客L(fng)Q所有客L(fng)可以自己选择需要的服务。这像馆只要拿出自己的菜单出来让客户选择Q就可以在后台厨房一道道的按需做出来,它怎么做的通常是不让客L(fng)道的Q(传菜谱吧,^_^Q?

最后一Ҏ(gu)我调用lookupQ查找一个叫PersonService名字的对象,服务器只要看到这个名字,在自q目录Q相当于?sh)话?j)中找到对应的对象名字提供服务可以了(jin)Q这个目录就叫做JNDI (Java命名与目录接口)(j)Q相信大家也听过的?

有兴的朋友不妨自己做个RMI的应用,很多前辈的博客中有简单的例子。提CZ下利用Jdk的bin目录中rmi.exe?rmiregistry.exe两个命o(h)可以自己徏起一个服务器Q提供远E服务。因Z子很Ҏ(gu)找,我就不自׃D例子?jin)?

2Q?JVM沙箱&框架
RMI|唆得太多了(jin)Q实在是力x(chng)它说清楚Q希望对大家有帮助。最后的最后,l大家简单讲一下JVM框架Q我们叫做Java沙箱。Java沙箱的基本组件如下:(x)
a) c装载器l构
b) class文g(g)验器
c) 内置于Java虚拟机的安全Ҏ(gu)?
d) 安全理器及(qing)Java API

其中c装载器?个方面对Java沙箱起作用:(x)
a. 它防止恶意代码去q涉善意的代?
b. 它守护了(jin)被信ȝcd边界
c. 它将代码归入保护域,定?jin)代码可以进行哪些操?

虚拟Zؓ(f)不同的类加蝲器蝲入的cL供不同的命名I间Q命名空间由一pd唯一的名U组成,每一个被装蝲的类有一个名字,q个命名I间是由Java虚拟Zؓ(f)每一个类装蝲器维护的Q它们互怹间甚至不可见?

我们常说的包QpackageQ是在Java虚拟机第2版的规范W一ơ出玎ͼ正确定义是由同一个类装蝲器装载的、属于同一个包、多个类型的集合。类装蝲器采用的机制是双亲委z模式。具体的加蝲器框架我在Java杂谈Q一Q中已经解释q了(jin)Q当时说最外层的加载器是AppClassLoaderQ其实算上网l层的话AppClassLoader也可以作为parentQ还有更外层的加载器URLClassLoader。ؓ(f)?jin)防止恶意攻ȝURL加蝲q来的类文g我们当然需要分不同的访问命名空_(d)q且制定最安全的加载次序,单来说就是两点:(x)

a. 从最内层JVM自带cd载器开始加载,外层恶意同名cd不到先加载而无法?
b. ׃严格通过包来区分?jin)访问域Q外层恶意的c通过内置代码也无法获得权限访问到内层c,破坏代码p然无法生效?

附:(x)关于Java的^台无x(chng),有一个例子可以很明显的说明这个特性:(x)
一般来_(d)C或C++中的int占位宽度是根据目标^台的字长来决定的Q这意味着针对不同的^台编译同一个C++E序在运行时?x)有不同的行为。然而对?Java中的int都是32位的二进制补码标识的有符h敎ͼ而float都是遵守IEEE 754点标准?2位QҎ(gu)?

PS: q个弟最q也没时间l研I下M(jin)Q只是想抛砖引玉的提供给大家一个初步认识JVM的印象。有Z(x)?jin)解一下JVM的内部结构对今后做Java开发是很有好处的?

Java杂谈Q七Q-Q接?amp; lg、容?

l于又静(rn)下来l箋(hu)写这个主题的l篇Q前六篇主要讲了(jin)一些J2se斚w的经验和感受Q?gJava应用范围已经被J2ee占据?jin)相当大的一块领域,有些人甚臛_UJava被J2ee所取代?jin)。不知道大家如何来理解所谓的J2ee (Java2 Enterprise Edition)Q也是Java企业U应用?

W者的观点是,技术的发展是顺应世界变化的势的,从C/Sq渡到B/S模式Q从客户端的角度考虑企业U应用或者说?sh)子商务领域不在兛_(j)客户端维护问题,q个d已经交给?jin)Q何一台PC都会(x)有的览器去l护Q从服务器端的角度考虑Q以往C/S中的TCP/IP协议实现载体ServerSocket被Web Server Container所取代Q例如大安很熟(zhn)的Tomcat、JBoss、WebLogic{等。M一切的转变都是Z(jin)使得Java技术能更好的ؓ(f)人类生生活所服务?

有h?x)问Q直接去学J2ee跌J2se行否Q笔者是肯定不赞成的Q实际上实有h走这条\Q但W者自w体?x)是正是׃J2se的基很牢固,才会(x)D在J2ee学习(fn)的道路上风水Q知识点上不?x)有什么迷惑的地方。D个简单的例子吧:(x)

W者曾l跟大学同学讨论下面q两U写法的区别Q?
ArrayList list = new ArrayList(); //W者不说反对,但至不赞成
List list = new ArrayList(); //W者支?
曄W者跟同学争论?jin)几个小Ӟ他非说第一U写法更U学Q第二种完全没有必要。我无法完全说服他,但笔者认好的?fn)惯和意识是M时候都应该针对接口~程Q以辑ֈ解耦合和可扩展性的目的。下面就以接口开始进入J2ee的世界吧Q?

1. J2ee与接?

每一个版本的J2ee都对应着一个确定版本的JDKQJ2ee1.4对应Jdk1.4Q现在比较新的是JDK5.0Q自然也?x)有J2EE 5.0。其实笔者一直在用的是J2EE1.4Q不q没什么关p,大家可以下Q何一个版本的J2ee api来稍微浏览一下。笔者想先声明一个概念,J2ee也是源自JavaQ所以底层的操作依然调用到很多J2se的库Q所以才大家先牢牢掌握J2se 的主技术?

J2ee api有一个特点,大家比较熟?zhn)的几个包java.jms、javax.servlet.http、javax.ejb{都以interface居多Q实现类较少。其实大家真正在用的时候百分之六十以上都在反复的查着javax.servlet.httpq个包下面几个实现类的api函数Q其他的包很问?hu)z。笔者徏议在学习(fn)一U技术之前,Ҏ(gu)体的框架有一个了(jin)解是很有必要的,J2ee旨在通过interface的声明来规范实现的行为,MW三方的厂商惌提供自己品牌的实现前提也是遵循这些接口定义的规则。如果在从前J2se学习(fn)的道路上Ҏ(gu)口的理解很好的话Q这里的体会(x)是非常深刻的,举个单的例子Q?

public interface Mp3{
public void play();
public void record();
public void stop();
}

如果我定义这个简单的接口Q发布出去,规定MW三方的公司x(chng)?gu)q名字为Mp3的品都必须实现q个接口Q也是臛_提供接口中方法的具体实现。这个意义已l远q不止是面向对象的多态了(jin)Q只有厂商遵循J2ee的接口定义,世界上的J2eeE序员才能针对统一的接口进行程序设计,最l不用改变(sh)码只是因Z用了(jin)不同厂商的实现类而有不同的特性Ş?jin),本质上说Q无论哪一U厂商实现都完成?jin)职责范围内的工作。这个就是笔者想一直强调的Q针Ҏ(gu)口编E的思想?

接口到底有什么好处呢Q我们这栯惻I现在有AppleMp3、SonyMp3、SamsungMp3都实C(jin)q个Mp3的接口,于是都有?jin)play?record、stopq三个功能。我们将Mp3产品座位一个组件的时候就不需要知道它的具体实玎ͼ只要看到接口定义知道q个对象?个功能就可以使用?jin)。那么类g面这L(fng)业务完全可以在M旉?个品牌扩展到L个品牌,开个玩W的_(d)目l理高高在上的写?0个接口里的方法声明,然后׃l手下的E序员去写里面的l节Q由于接口已l统一Q即每个Ҏ(gu)传入和传出的格式已经l一Q,l理只需x(chng)全局的业务就可以天天端杯咖啡走来走去?jin),^_^Q?
public Mp3 create();
public void copy(Mp3 mp3);
public Mp3 getMp3();

最后用一个简单的例子说明接口Q一?L(fng)(sh)池的手电(sh){,可以装入M牌子?L(fng)(sh)池,只要它符?L(fng)(sh)池的规范Q装入之后Q何看不到是什么牌子,只能感受到手늭在完成它的功能。那么生产手늭的厂商和生5L(fng)(sh)池的厂商可以完全解除依赖关p,可以各自自由开发自q产品Q因为它们都遵守5L(fng)(sh)池应有的形状、正负极位置{约定。这下大家能Ҏ(gu)口多一点体?x)?jin)么?

2. lg和容?
针对接口是笔者特意强调的J2ee学习(fn)之\必备的思想Q另外一个就是比较常规的lg和容器的概念?jin)。很多教材和专业|站都说J2EE的核?j)是一l规范与指南Q强调J2ee的核?j)概念就是组?容器Q这实是无可厚非的。随着来多的J2ee框架出现Q相应的每种框架都一般有与之对应的容器?

容器Q是用来理lg行ؓ(f)的一个集合工Plg的行为包括与外部环境的交互、组件的生命周期、组件之间的合作依赖关系{等。J2ee包含的容器种cdU有 Web容器、Application Client容器、EJB容器、Applet客户端容器等。但在笔者看来,现在容器的概念变得有Ҏ(gu)p了(jin)Q大家耳熟能详是那些功能强大的开源框Ӟ比如 Hibernate、Struts2、Spring、JSF{,其中Hibernate基于JDBC的基装?jin)对事务和?x)话的理Q大大方便了(jin)Ҏ(gu)据库操作的繁琐代码,从这个意义上来说它已l接q容器的概念?jin),EJB的实体Bean也逐渐被以HibernateZ表的持久化框架所取代?

lgQ本意是指可以重用的代码单元Q一般代表着一个或者一l可以独立出来的功能模块Q在J2ee中组件的U类有很多种Q比较常见的是EJBlg、DAOlg、客L(fng)lg或者应用程序组件等Q它们有个共同特Ҏ(gu)分别?x)打包?warQ?jarQ?jarQ?earQ每个组件由特定格式的xml描述W文件进行描qͼ而且服务器端的组仉需要被部v到应用服务器上面才能够被使用?

E微理解完组件和容器Q还有一个重要的概念是分层模型Q最著名的当然是MVC三层模型。在一个大的工E或目中,Z(jin)让前台和后台各个模块的编Eh员能够同时进行工作提高开发效率,最重要的就是实现层与层之间的耦合关系Q许多分层模型的宗旨和开源框架所q求的也是q样的效果。在W者看来,一个完整的 Web目大概有以下几个层ơ:(x)

a) 表示层(Jsp、Html、Javascript、Ajax、Flash{等技术对其支持)(j)
b) 控制层(Struts、JSF、WebWork{等框架在基于Servlet的基上支持,负责把具体的h数据Q有时卸载重新装载)(j)导向适合处理它的模型层对象)(j)
c) 模型层(W者认为目前最好的框架是SpringQ实质就是处理表C层l由控制层{发过来的数据Q包含着大量的业务逻辑Q?
d) 数据层(Hibernate、JDBC、EJB{,由模型层处理完了(jin)持久化到数据库中Q?

当然Q这仅仅是笔者个人的观点Q仅仅是供大家学?fn)做一个参考,如果要实现这些层之间的完全分,那么一个大的工E,可以仅仅通过增加人手来完成d。虽然《h月神话》中已经很明的阐述?jin)增加h手ƈ不能是效率增加,很大E度上是因ؓ(f)彼此做的工作有顺序上的依赖关pL者说隑ֺ和工作量上的巨大差距。当然理想状态在真实世界中是不可能达到的Q但我们永远应该朝着q个方向M断努力。最开始所提倡的针对接口来编E,哪怕是小的细节,写一条List list= = new ArrayList()语句也能体现着处处皆用接口的思想在里面。AnywayQ这只是个开,W者会(x)pqq的J2ee技术和框架再细化谈一些经?

Java杂谈Q八Q-QServlet/Jsp
l于正式q入J2ee的细节部分了(jin)Q首当其冲的当然是Servlet和Jsp?jin),上篇曄提到qJ2ee只是一个规范和指南Q定义了(jin)一l必要遵@的接口,核心(j)概念是组件和容器。曾l有的h问笔者Servlet的Class文g是哪里来的?他认为是J2ee官方提供的,我D?jin)一个简单的反例Q稍微检查了(jin)一下Tomcat5.0里面的Servlet.jar文g和JBoss里面的Servlet.jar文g大小Q很明显是不一L(fng)Q至已l说明了(jin)它们不是源自同根的吧。其实Servlet是由容器Ҏ(gu)J2ee的接口定义自己来实现的,实现的方式当然可以不同,只要都遵守J2ee规范和指南?

上述只是一个常见的误区|了(jin)Q告诉我们要~译q行ServletQ是要依赖于实现它的容器的,不然qjar文g都没有,~译都无法进行。那么Jsp呢? Java Server Page的简Uͼ是ؓ(f)?jin)开发动态网而诞生的技术,其本质也是JspQ在~写完毕之后?x)在容器启动时经q编译成对应的Servlet。只是我们利用Jsp 的很多新Ҏ(gu),可以更加专注于前后台的分,早期Jsp做前台是满流行的Q毕竟里面支持Html代码Q这让前台美工h员可以更有效率的d成自q工作。然后Jsp请求{发到后台的ServletQ由Servlet处理业务逻辑Q再转发回另外一个Jsp在前台显C出来。这g已经成ؓ(f)一U常用的模式Q最初笔者学?fn)J2ee的时候,大量旉也在~写q样的代码?

管现在做前台的技术越来越多,例如Flash、Ajax{,已经有很多h不再认ؓ(f)Jsp重要?jin)。笔者觉得Jsp带来的不仅仅是前后端分离的设计理念,它的另外一Ҏ(gu)术成׃(jin)我们今天用的很多框架Q那是Tag标签技术。所以与其说是在学习(fn)JspQ不如更清醒的告诉自己在不断的理解Tag标签的意义和本质?

1Q?Servlet以及(qing)Jsp的生命周?
Servlet是Jsp的实质,管容器对它们的处理有所区别。Servlet有init()Ҏ(gu)初始化,service()Ҏ(gu)q行W(xu)eb服务Q?destroy()Ҏ(gu)q行销毁,从生到灭都由容器来掌握,所以这些方法除非你惌己来实现ServletQ否则是很少?x)接触到的。正是由于很接触,才容易被q大初学者所忽略Q希望大家至记住Servlet生命周期Ҏ(gu)都是回调Ҏ(gu)。回调这个概늮单来说就是把自己注入另外一个类中,由它来调用你的方法,所谓的另外一个类是Web容器Q它只认识接口和接口的方法,注入q来的是怎样的对象不,它只?x)根据所需调用q个对象在接口定义存在的那些Ҏ(gu)。由容器来调用的Servlet对象的初始化、服务和销毁方法,所以叫做回调。这个概念对学习(fn)其他J2ee技术相当关键!

那么Jsp呢?本事上是ServletQ还是有些区别的Q它的生命周期是q样的:(x)
a) 一个客L(fng)的Request到达服务?->
b) 判断是否W一ơ调?-> 是的话编译Jsp成Servlet
c) 否的话再判断此Jsp是否有改?-> 是的话也重新~译Jsp成Servlet
d) 已经~译最q版本的Servlet装蝲所需的其他Class
e) 发布ServletQ即调用它的Service()Ҏ(gu)

所以JspL(fng)的是W一ơLoad~慢Q以后都?x)很快的q行。从它的生命的周期确实不隄出来q个特点Q客L(fng)的操作很会(x)改变Jsp的源码,所以它不需要编译第二次׃直可以ؓ(f)客户端提供服务。这里稍微解释一下Http的无状态性,因ؓ(f)发现很多解,Http的无状态性是指每ơ一张页面显C出来了(jin)Q与服务器的q接其实已l断开?jin),当再ơ有提交动作的时候,才会(x)再次与服务器q行q接h提供服务。当然还有现在比较流行的是Ajax与服务器异步通过 xml交互的技术,在做前台的领域潜力巨大,W者不是Ajax的高手,q里无法为大家解释?

2Q?Tag标签的本?
W者之前说?jin),Jsp本n初衷是得Web应用前后台的开发可以脱耦合分开有效的进行,可惜q个理念的A(ch)献反倒不如它带来的Tag技术对J2ee的A(ch)献要大。也许已l有很多人开始用Tag技术了(jin)却ƈ不了(jin)解它。所以才大家在学?fn)J2ee开始的时候一定要认真学习(fn)JspQ其实最重要的就是明白标{本质?

Html标签我们都很熟?zhn)了(jin),?<html> ?<head> ?<body> ?<title> QJsp带来的Tag标签遵@同样的格式,或者说更严格的Xml格式规范Q例?<jsp:include> ?<jsp:useBean> ?<c:if> ?<c:forEach> {等。它们没有什么神U的地方Q就其源头也q是Java Class而已QTag标签的实质也是一DJava代码Q或者说一个Class文g。当配置文g讄好去哪里Lq些Class的\径后Q容器负责将面中存在的标签对应到相应的Class上,执行那段特定的Java代码Q如此而已?
说得明白一点的话还是D几个单的例子说明一下吧Q?

<jsp:include> d里找执行什么class?首先q是个jspcd的标{,当然要去jspcdL相应的class?jin),同样它也是由Web容器来提供,例如 Tomcat应该去安装目录的lib文g夹下面的jsp-api.jar里面找,有兴的可以L一扑֕Q?

<c:forEach> 又去哪里扑֑Q这个是由Jsp2.0版本推荐的和核心(j)标记库的内容Q例?<c:if> 对应在面中做if判断的功能的一断Java代码。它的class文g在jstl.jarq个cd里面Q往往q需要和一个standard.jarcd一起导入,攑֜具体Web目的WEB-INF的lib目录下面可以用了(jin)?

Z|唆一句,W(xu)eb Project的目录结构是相对固定的,因ؓ(f)容器?x)按照固定的路径d扑֮需要的配置文g和资源,q个M一本J2ee入门书上都有Q这里就不介l了(jin)。了(jin)解Tag的本质还要了(jin)解它的工作原理,所以大家去J2ee的API里找到ƈ研究q个包:(x)javax.servlet.jsp.tagext。它有一些接口,和一些实现类Q专门用语开发TagQ只有自׃自写出几个不同功能的标签Q才是真正理解?jin)标{原理。别忘记?jin)自己开发的标签要自己去完成配置文gQ容器只是集成了(jin)d里寻找jsp标签对应class的\径,自己写的标签库当然要告诉容器d里找啦?

说了(jin)q么多,我们Z么要用标{֑Q完全在Jsp里面来个 <% %> 可以在里面L写Java代码?jin),但是长期实践发现面代码l一都是与html同风格的标记语言更加有助于美工h员进行开发前収ͼ它不需要懂JavaQ只要JavaE序员给个列表告诉美工什么标{֏以完成什么逻辑功能Q他可以专注于工Q也是q一步隔M(jin)前后台的工作吧!

3Q?成就Web框架
框架是什么?曄看过q样的定义:(x)与模式类|框架也是解决特定问题的可重用Ҏ(gu)Q框架是一个描q性的构徏块和服务集合Q开发h员可以用来达成某个目标。一般来_(d)框架提供?jin)解x(chng)c问题的基础设施Q是用来创徏解决Ҏ(gu)的工P而不是问题的解决Ҏ(gu)?

正是׃Tag的出玎ͼ成就?jin)以后出现的那么多Web框架Q它们都开发了(jin)自己成熟实用的一套标{,然后q定的Xml文g来配|加载信息,力图使得Web 应用的开发变得更加高效。下面这些标{应对很多人来说相当熟(zhn)了(jin)Q?
<html:password>
<logic:equal>
<bean:write>
<f:view>
<h:form>
<h:message>

它们分别来自Struts和JSF框架Q最强大的功能在于控制{发,是MVC三层模型中间完成控制器的工作。Struts-1实际上ƈ未做到真正的三层隔离Q这一点在Struts-2上得C(jin)很大的改q。而Jsf向来以比较完善合理的标签库受Ch们推崇?

今天大概讲q么多吧Q再ơ需要强调的是Servlet/Jsp是学?fn)J2ee必经之\Q也是最基础的知识,希望大家l与_的重视!
Java杂谈Q九(ji)Q-QStruts

J2ee的开源框架很多,W者只能介l自q(zhn)的几个Q其他的目前在中国IT行业应用得不是很多。希望大家对新出的框架不要盲目的推崇Q首先一定要熟?zhn)它比旧的到底好在哪里Q新的理念和Ҏ(gu)是什么?然后再决定是否要使用它?

q期的主题是StrutsQ直译过来是支架。Struts的第一个版本是?001q?月发布的Q它提供?jin)一个Web应用的解x(chng)案,如何让Jsp?servlet共存L供清晰的分离视图和业务应用逻辑的架构。在Struts之前Q通常的做法是在Jsp中加入业务逻辑Q或者在Servlet中生成视图{发到前台厅RStruts带着MVC的新理念当时退出几乎成Z界公认的Web应用标准Q于是当代IT?jng)场上也出现了(jin)众多熟?zhn)Struts的程序员。即使有新的框架再出来不用,而l用Struts的理׃加上?jin)一条低风险Q因Z途如果开发h员变动,很容易的招进新的?x)Struts的IT民工啊, ^_^!


zhuyongjp 2009-02-27 17:48 发表评论
]]>
վ֩ģ壺 ޹ƷԲĵӰ| ۺƷ˿| ޾ƷۺӰԺ| ƷؼһëƬѹۿ| ѹ99þþ㽶| ѹۿŮվ| ޺ݺۺϾþþþ| ձVAĻþõ| ӰӾ߹ۿȫ | 97ɫ׳Ƶ| 鶹Ʒ͵Բ91| ɫavɫ߹| վ߹ۿ| ÿձƬ35| ޹һƵ| պ ɫ ͼվ| Ƭ߹ۿƵ| bbbbbbƵ| ˾žŴɫ㽶վ| ҹƵ| ŷaվ| þҹɫƷAV̬ͼ| ..ŷһ| ޾ƷѹۿƵ| ɫƷ88ɫ¶| avƬvrһ| hƵ߹ۿ| ɫþþ99Ʒ91| ŷav߹ۿ| 99Ѳ| ˾޾ƷӰwww| AVպAVվ | ֻˬƵ| ˳ձ߹ۿ| þûɫվ| Ƶ˳߲| ɫɫwww| ѴƬ߹ۿyw| һҹɫ| ȫӳѹۿ߿| ֻˬƵѿ|