ï»??xml version="1.0" encoding="utf-8" standalone="yes"?>成人在线视频成人,亚洲成人精品影院,亚洲视频在线一区二区http://www.aygfsteel.com/zdf8013/zdf8013zh-cnTue, 10 Jun 2025 11:10:13 GMTTue, 10 Jun 2025 11:10:13 GMT60通过写Java代码来对MyEclipse˜q›è¡Œæ³¨å†Œ http://www.aygfsteel.com/zdf8013/archive/2009/09/01/293514.html赵国æž?/dc:creator>赵国æž?/author>Tue, 01 Sep 2009 15:42:00 GMThttp://www.aygfsteel.com/zdf8013/archive/2009/09/01/293514.htmlhttp://www.aygfsteel.com/zdf8013/comments/293514.htmlhttp://www.aygfsteel.com/zdf8013/archive/2009/09/01/293514.html#Feedback0http://www.aygfsteel.com/zdf8013/comments/commentRss/293514.htmlhttp://www.aygfsteel.com/zdf8013/services/trackbacks/293514.html

 

最˜q‘ä‹É用MyEclipse 7.5.0æ—Óž¼Œå‘现å®?0试用期快˜q‡äº†(ji¨£n)åQŒæ½Cºæˆ‘要注册ã€?/p>

其实åQŒä¸ç”¨éº»çƒ?ch¨³)从¾|‘上搜烦(ch¨³)那些存在的注册码的,˜q™æ ·æ“ä½œåQ?/p>

在MyEclipse中新å»ÞZ¸€ä¸ªå·¥½E‹ï¼Œå¯¼å…¥ä¸‹é¢çš„æ–‡ä»?

MyEclipseGen.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class MyEclipseGen {
private static final String LL = "Decompiling this copyrighted software is a violation of both your license agreement and the Digital Millenium Copyright Act of 1998 (http://www.loc.gov/copyright/legislation/dmca.pdf). Under section 1204 of the DMCA, penalties range up to a $500,000 fine or up to five years imprisonment for a first offense. Think about it; pay for a license, avoid prosecution, and feel better about yourself.";
public String getSerial(String userId, String licenseNum) {
   java.util.Calendar cal = java.util.Calendar.getInstance();
   cal.add(1, 3);
   cal.add(6, -1);
   java.text.NumberFormat nf = new java.text.DecimalFormat("000");
   licenseNum = nf.format(Integer.valueOf(licenseNum));
   String verTime = new StringBuilder("-").append(
     new java.text.SimpleDateFormat("yyMMdd").format(cal.getTime()))
     .append("0").toString();
   String type = "YE3MP-";
   String need = new StringBuilder(userId.substring(0, 1)).append(type)
     .append("300").append(licenseNum).append(verTime).toString();
   String dx = new StringBuilder(need).append(LL).append(userId)
     .toString();
   int suf = this.decode(dx);
   String code = new StringBuilder(need).append(String.valueOf(suf))
     .toString();
   return this.change(code);
}
private int decode(String s) {
   int i;
   char[] ac;
   int j;
   int k;
   i = 0;
   ac = s.toCharArray();
   j = 0;
   k = ac.length;
   while (j < k) {
    i = (31 * i) + ac[j];
    j++;
   }
   return Math.abs(i);
}
private String change(String s) {
   byte[] abyte0;
   char[] ac;
   int i;
   int k;
   int j;
   abyte0 = s.getBytes();
   ac = new char[s.length()];
   i = 0;
   k = abyte0.length;
   while (i < k) {
    j = abyte0[i];
    if ((j >= 48) && (j <= 57)) {
     j = (((j - 48) + 5) % 10) + 48;
    } else if ((j >= 65) && (j <= 90)) {
     j = (((j - 65) + 13) % 26) + 65;
    } else if ((j >= 97) && (j <= 122)) {
     j = (((j - 97) + 13) % 26) + 97;
    }
    ac[i] = (char) j;
    i++;
   }
   return String.valueOf(ac);
}
public MyEclipseGen() {
   super();
}
public static void main(String[] args) {
   try {
    System.out.println("please input register name:");
    BufferedReader reader = new BufferedReader(new InputStreamReader(
      System.in));
    String userId = null;
    userId = reader.readLine();
    MyEclipseGen myeclipsegen = new MyEclipseGen();
    String res = myeclipsegen.getSerial(userId, "5");
    System.out.println("Serial:" + res);
    reader.readLine();
   } catch (IOException ex) {
   }
}
}

˜qè¡Œè¯¥ä»£ç ï¼Œåœ¨æŽ§åˆ¶å°ä¸­ä¼š(x¨¬)出现åQ?
please input register name:
×××××åQˆä½ çš„name,随便什么)(j¨ª)
即生成序列号åQ?/strong> ××××× ××××× ×××××...

˜q›å…¥myeclipse,在菜单中选择 Myeclipse->Subscription Information 然后 输入Subscriberå’ŒSubscription code卛_¯ã€?/strong>

sub 

使用旉™—´ä¸€èˆ¬å¾ˆé•¿çš„ã€?
å“?#8230;…自己把自å·Þq ´è§£äº†(ji¨£n)åQŒçˆ½åQ?/p> 来源åQ?/a>
CξOOζLζ的专æ ?/a>



]]>
开发国际化struts应用½E‹åºä¼?x¨¬)ç”?/title><link>http://www.aygfsteel.com/zdf8013/archive/2009/05/16/270991.html</link><dc:creator>赵国æž?/dc:creator><author>赵国æž?/author><pubDate>Sat, 16 May 2009 05:08:00 GMT</pubDate><guid>http://www.aygfsteel.com/zdf8013/archive/2009/05/16/270991.html</guid><wfw:comment>http://www.aygfsteel.com/zdf8013/comments/270991.html</wfw:comment><comments>http://www.aygfsteel.com/zdf8013/archive/2009/05/16/270991.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/zdf8013/comments/commentRss/270991.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/zdf8013/services/trackbacks/270991.html</trackback:ping><description><![CDATA[<p>MyResource.properties//æ–‡äšg名和后缀</p> <p>#Simple properties file for test.</p> <p>title.login=Login Page<br /> title.welcom=Welcom,<br /> title.failure=Sorr,Login Failed!<br /> label.login=Please input username and password<br /> label.deny=Access Denied.<br /> item.submit=Submit<br /> item.reset=Reset<br /> item.user=UserName<br /> item.password=Password<br /> link.relative=FriendShip Relative<br /> link.loginAgain=Login Again</p> <p><br />  </p> <img src ="http://www.aygfsteel.com/zdf8013/aggbug/270991.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/zdf8013/" target="_blank">赵国æž?/a> 2009-05-16 13:08 <a href="http://www.aygfsteel.com/zdf8013/archive/2009/05/16/270991.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>oracle各版本下载地址 http://www.aygfsteel.com/zdf8013/archive/2009/04/10/264904.html赵国æž?/dc:creator>赵国æž?/author>Fri, 10 Apr 2009 10:58:00 GMThttp://www.aygfsteel.com/zdf8013/archive/2009/04/10/264904.htmlhttp://www.aygfsteel.com/zdf8013/comments/264904.htmlhttp://www.aygfsteel.com/zdf8013/archive/2009/04/10/264904.html#Feedback5http://www.aygfsteel.com/zdf8013/comments/commentRss/264904.htmlhttp://www.aygfsteel.com/zdf8013/services/trackbacks/264904.html 
oracleç›®å‰æœ€æ–°ç‰ˆæœ¬äØ“(f¨´)Oracle 11g下蝲åQ?br /> 分äín“Oracle 11g下蝲地址”åQˆéž11iåQ‰ã€?#8220;Oracle 10g下蝲地址”ã€?#8220;Oracle 9i下蝲地址”ã€?br /> 所有版本Oracle下蝲都是免费的,òq¶ä¸”每个软äšg都自带一个开发许可ã€?br />
Oracle 11g下蝲地址åQ?/strong>
oracle Database 11g Release 1(11.1.0.6.0) 下蝲
http://www.oracle.com/technology/software/products/database/index.html
文档åQšhttp://www.oracle.com/technology/global/cn/documentation/index.html


Oracle 10g下蝲地址
http://www.oracle.com/technology/global/cn/software/products/database/oracle10g/index.html
包括Oracle 10g 数据库企ä¸?标准版,Oracle 10g 数据åº?½W?版下载地址、Oracle 10g 数据åº?½W?版下载地址


Oracle下蝲åQOracle 9i下蝲
Oracle9i 数据库下�包括Oracle9i Release 2 (9.2.0.2)下蝲,Oracle9i Release 2 (9.2.0.1)下蝲
http://www.oracle.com/technology/global/cn/software/products/oracle9i/index.html

Oracle 9i for Windows下蝲
oracle 9i 3CD DownloadåQ?br /> http://download.oracle.com/otn/nt/oracle9i/9201/92010NT_Disk1.zip
http://download.oracle.com/otn/nt/oracle9i/9201/92010NT_Disk2.zip
http://download.oracle.com/otn/nt/oracle9i/9201/92010NT_Disk3.zip  


]]>
Ant配置http://www.aygfsteel.com/zdf8013/archive/2009/04/10/264903.html赵国�/dc:creator>赵国�/author>Fri, 10 Apr 2009 10:46:00 GMThttp://www.aygfsteel.com/zdf8013/archive/2009/04/10/264903.htmlhttp://www.aygfsteel.com/zdf8013/comments/264903.htmlhttp://www.aygfsteel.com/zdf8013/archive/2009/04/10/264903.html#Feedback0http://www.aygfsteel.com/zdf8013/comments/commentRss/264903.htmlhttp://www.aygfsteel.com/zdf8013/services/trackbacks/264903.html阅读全文

]]>
FCKeditor的应用与讄¡½®http://www.aygfsteel.com/zdf8013/archive/2009/04/09/264737.html赵国æž?/dc:creator>赵国æž?/author>Thu, 09 Apr 2009 15:08:00 GMThttp://www.aygfsteel.com/zdf8013/archive/2009/04/09/264737.htmlhttp://www.aygfsteel.com/zdf8013/comments/264737.htmlhttp://www.aygfsteel.com/zdf8013/archive/2009/04/09/264737.html#Feedback0http://www.aygfsteel.com/zdf8013/comments/commentRss/264737.htmlhttp://www.aygfsteel.com/zdf8013/services/trackbacks/264737.htmlwww.fckeditor.net官方¾|‘站上下载fckeditor压羃包ã€?br /> 2、徏立webproject应用½E‹åºã€?br /> 3、在建立的htmlæ–‡äšg中输å…?br />     <script type="text/javascript" src="/fckeditordemo/fckeditor/fckeditor.js"></script>
        <form name="form1" action="/fckeditordemo/servlet/addFckeditor" method="post">
      <input type="text" name="title" />
      <script type="text/javascript">
      var editor=new FCKeditor('editor');
      editor.BasePath="/fckeditordemo/fckeditor/";//fckeditor.js 所在的目录
      editor.Height=200;
      editor.ToolbarSet='Default'; 
      editor.Create();
      </script>
      <input type="submit" name="submit" value="提交" />
    </form>
4、徏立servlet 
    out.println("主题åQ?+"<br>");
  out.println(request.getParameter("title")+"<br>");
  out.println("内容åQ?+"<br>");
  out.println(request.getParameter("editor"));

]]>
http错误代码含义åQ?http://www.aygfsteel.com/zdf8013/archive/2009/03/21/261232.html赵国æž?/dc:creator>赵国æž?/author>Sat, 21 Mar 2009 12:01:00 GMThttp://www.aygfsteel.com/zdf8013/archive/2009/03/21/261232.htmlhttp://www.aygfsteel.com/zdf8013/comments/261232.htmlhttp://www.aygfsteel.com/zdf8013/archive/2009/03/21/261232.html#Feedback0http://www.aygfsteel.com/zdf8013/comments/commentRss/261232.htmlhttp://www.aygfsteel.com/zdf8013/services/trackbacks/261232.html

]]>
Java¾lå¯¹å¥½æ–‡åQŒè{载的åQï¼ˆè½¬è²åQ?/title><link>http://www.aygfsteel.com/zdf8013/archive/2008/12/12/246057.html</link><dc:creator>赵国æž?/dc:creator><author>赵国æž?/author><pubDate>Fri, 12 Dec 2008 15:37:00 GMT</pubDate><guid>http://www.aygfsteel.com/zdf8013/archive/2008/12/12/246057.html</guid><wfw:comment>http://www.aygfsteel.com/zdf8013/comments/246057.html</wfw:comment><comments>http://www.aygfsteel.com/zdf8013/archive/2008/12/12/246057.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/zdf8013/comments/commentRss/246057.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/zdf8013/services/trackbacks/246057.html</trackback:ping><description><![CDATA[<div id="wmqeeuq" class="postTitle"><br /> æƒÏx¥å­¦ä¹ (f¨¤n)Java也有两个òq´å¤´äº?ji¨£n),永远不敢说多么精通,但也惌™°ˆè°ˆè‡ªå·Þqš„æ„Ÿå—åQŒå†™¾l™èÊY件学院的同仁们,帮助大家在技术的道èµ\上少一点弯路。说得伟大一ç‚ÒŽ(gu¨©)˜¯å¸Œæœ›å¤§å®¶ä¸ø™ÊY件学院争气,其实最主要的还是大家自íw«çš„˜q›æ­¥æå‡?? <br /> <br /> 1åQ?关于动态加载机åˆ?? <br /> 学习(f¨¤n)Java比C++更容易理解OOP的思想åQŒæ¯•竟C++˜q˜æØœåˆäº†(ji¨£n)不少面向˜q‡ç¨‹çš„æˆåˆ†ã€‚很多äh都能背出来Java语言的特点,所谓的动态加载机制等½{‰ã€‚当然概念往往是先è®îC½è€ŒåŽæ¶ˆåŒ–的,可有多少人真正去体会(x¨¬)˜q‡åŠ¨æ€åŠ è½½çš„æœºåˆ¶åQŒè¯•囑֎»å¯ÀL‰¾˜q‡å…¶ä¸­çš„¾l†èŠ‚å‘? 提供大家一个方法:(x¨¬) <br /> 在命令行½H—口˜qè¡ŒJava½E‹åºçš„æ—¶å€™ï¼ŒåŠ ä¸Š˜q™ä¸ªå¾ˆæœ‰ç”¨çš„参数åQ?<br /> <br /> java -verbose *.class <br /> <br /> ˜q™æ ·ä¼?x¨¬)æ¸…æ™°çš„æ‰“å°å‡ø(gu¨®)™¢«åŠ è²çš„ç±»æ–‡äšgåQŒå¤§éƒ¨åˆ†æ˜¯jdk自èín˜qè¡Œéœ€è¦çš„åQŒæœ€åŽå‡ è¡Œä¼š(x¨¬)明显的看到自å·Þq”¨åˆ°çš„那几个类文äšg被加载进来的™åºåºã€‚即使你声明äº?ji¨£n)一个类对象åQŒä¸å®žä¾‹åŒ–也不会(x¨¬)加蝲åQŒè¯´æ˜Žåªæœ‰çœŸæ­£ç”¨åˆ°é‚£ä¸ªç±»çš„实例即对象的时候,才会(x¨¬)执行加蝲。这æ äh˜¯ä¸æ˜¯å¤§å®¶½Eå¾®èƒ½æ˜Žç™½ä¸€ç‚¹åŠ¨æ€åŠ è½½äº†(ji¨£n)呢?^_^ <br /> <br /> 2åQ?关于å¯ÀL‰¾classæ–‡äšg原理?? <br /> 廸™®®å¤§å®¶åœ¨å…¥é—¨çš„æ—¶å€™åœ¨å‘½ä×o(h¨´)行窗口编译和˜qè¡ŒåQŒä¸è¦å€ŸåŠ©JCreator或者Eclipse½{‰IDEåŽÕd¸®åŠ©åšé‚£äº›äº‹æƒ…ã€‚å°è¯•è‡ªå·Þp¿™æ ·åšåQ?<br /> javac -classpath yourpath *.java <br /> java -classpath yourpath *.class <br /> 也许很多人都能看懂,讄¡½®classpath的目的就是告诉编译器åŽÕd“ªé‡Œå¯»æ‰¾ä½ çš„classæ–‡äšg. 不过臛_°‘½W”者今日才弄懂JVMåŽÀLŸ¥è¯¢ç±»çš„原理,¾~–译器加载类要依靠classloaderåQ?而classloaderæœ?个çñ”别,从高åˆîC½Žåˆ†åˆ«æ˜¯BootClassLoader(名字可能不准¼‹? , ExtClassLoader, AppClassLoader. <br /> <br /> ˜q?个加载器分别对应着¾~–译器去å¯ÀL‰¾¾cÀL–‡ä»¶çš„优先¾U§åˆ«å’Œä¸åŒçš„路径åQšBootClassLoader对应jre/classes路径åQŒæ˜¯¾~–译器最优先å¯ÀL‰¾class的地æ–?<br /> ExtClassLoader对应jre/lib/ext路径åQŒæ˜¯¾~–译器次优先å¯ÀL‰¾class的地æ–?<br /> AppClassLoader对应当前路径åQŒæ‰€ä»¥ä¹Ÿæ˜¯ç¼–译器默认找class的地æ–?<br /> <br /> 其实大家可以自己写个½E‹åº½Ž€å•çš„‹¹‹è¯•åQŒå¯¹ä»ÖM½•classåQŒä¾‹å¦‚A, <br /> 调用new A().getClass().getClassLoader().toString() 打印出来ž®±å¯ä»¥çœ‹åˆŽÍ¼ŒæŠŠclassæ–‡äšg攑֜¨ä¸åŒçš„èµ\径下再次执行åQŒå°±ä¼?x¨¬)看到区别。特别注意的是如果打印出来是nullž®Þp¡¨½Cºåˆ°äº?ji¨£n)最高çñ” BootClassLoader, 因䨓(f¨´)它是C++¾~–写的,不存在Java对应的类加蝲器的名字ã€?<br /> <br /> å¯ÀL‰¾çš„顺序是一¿Uå‘上迂回的思想åQŒå³å¦‚果本çñ”别找不到åQŒå°±åªèƒ½åŽÀLœ¬¾U§åˆ«ä¹‹ä¸Šçš„æ‰¾åQŒä¸ä¼?x¨¬)向下寻找。不˜q‡ä¼¼ä¹Žä»ŽJdk1.4到Jdk1.6˜q™ä¸€ç‰¹ç‚¹åˆæœ‰æ”¹å˜åQŒæ²¡æœ‰æ‰¾åˆ°è¯¦¾l†èµ„料。所以就不ä‹D例子äº?ji¨£n)。告诉大家设计这¿Uä½“¾pÈš„æ˜¯Sun公司曄¡»çš„æŠ€æœ¯æ ¸å¿?j¨©)宫力先生,一个纯¿UåŽäººå“¦åQ^_^ <br /> <br /> ˜q™æ ·å¸Œæœ›å¤§å®¶ä¸è‡³äºŽè¿·æƒ‘䨓(f¨´)什么æ€ÀLŠ¥é”™æ‰¾ä¸åˆ°¾cÀL–‡ä»Óž¼Œä¸ç®¡æ˜¯è‡ªå·±å†™çš„还是导入的½W¬ä¸‰æ–¹çš„jaræ–‡äšgåQˆJ2ee中经帔Rœ€è¦å¯¼å…¥çš„åQ‰ã€?<br /> <br /> 3åQ?关于jdkå’Œjre?? <br /> 大家肯定在安装JDK的时候会(x¨¬)有选择是否安装单独的jreåQŒä¸€èˆ¬éƒ½ä¼?x¨¬)ä¸€èµ·å®‰è£…ï¼Œæˆ‘ä¹Ÿå»ø™®®å¤§å®¶˜q™æ ·åšã€‚因䏸™¿™æ äh›´èƒ½å¸®åŠ©å¤§å®¶å¼„æ¸…æ¥šå®ƒä»¬çš„åŒºåˆ«ï¼š(x¨¬) <br /> <br /> Jre 是java runtime environment, 是java½E‹åºçš„运行环境。既然是˜qè¡ŒåQŒå½“然要包含jvmåQŒä¹Ÿž®±æ˜¯å¤§å®¶ç†Ÿæ?zh¨¨n)‰çš„虚拟机啦ï¼?˜q˜æœ‰æ‰€æœ‰java¾cÕdº“çš„classæ–‡äšgåQŒéƒ½åœ¨lib目录下打包成äº?ji¨£n)jar。大家可以自己验证。至于在windows上的虚拟机是哪个文äšg呢? 学过MFC的都知道什么是dllæ–‡äšg吧,那么大家看看jre/bin/client里面是不是有一个jvm.dll呢?那就是虚拟机ã€?<br /> <br /> Jdk 是java development kitåQŒæ˜¯java的开发工具包åQŒé‡Œé¢åŒ…含了(ji¨£n)各种¾cÕdº“和工兗÷€‚当然也包括äº?ji¨£n)另外一个Jre. 那么ä¸ÞZ»€ä¹ˆè¦åŒ…括另外一个Jre呢?而且jdk/jre/bin同时有clientå’Œserver两个文äšg夹下都包含一个jvm.dllã€?说明是有两个虚拟机的。这一点不知道大家是否注意åˆîCº†(ji¨£n)呢? <br /> <br /> ç›æ€¿¡å¤§å®¶éƒ½çŸ¥é“jdkçš„bin下有各种java½E‹åºéœ€è¦ç”¨åˆ°çš„命ä×o(h¨´)åQŒä¸Žjreçš„bin目录最明显的区别就是jdk下才有javacåQŒè¿™ä¸€ç‚¹å¾ˆå¥½ç†è§£ï¼Œå› äØ“(f¨´) jre只是一个运行环境而已。与开发无养I¼Œæ­£å› ä¸ºå¦‚此,具备开发功能的jdk自己的jre下才ä¼?x¨¬)同时有client性质的jvmå’Œserver性质çš?jvmåQ?è€Œä»…ä»…ä½œä¸ø™¿è¡ŒçŽ¯å¢ƒçš„jre下只需要client性质的jvm.dllž®±å¤Ÿäº?ji¨£n)ã€?<br /> <br /> 记得在环境变量path中设¾|®jdk/bin路径麽?˜q™åº”该是大家学习(f¨¤n)Java的第一步吧åQ?老师ä¼?x¨¬)告诉大家不讄¡½®çš„话javacå’Œjava是用不了(ji¨£n)的。确实jdk/bin目录下包含了(ji¨£n)所有的命ä×o(h¨´)。可是有没有人想˜q‡æˆ‘们用的java命ä×o(h¨´)òq¶ä¸æ˜?jdk/bin目录下的而是jre/bin目录下的呢?不信可以做一个实验,大家可以把jdk/bin目录下的java.exe剪切到别的地方再˜qè¡Œ java½E‹åºåQŒå‘çŽîCº†(ji¨£n)什么?一切OKåQ?<br /> <br /> 那么有ähä¼?x¨¬)问了(ji¨£n)?我明明没有设¾|®jre/bin目录到环境变量中啊? <br /> <br /> 试想一下如果javaä¸ÞZº†(ji¨£n)提供¾l™å¤§å¤šæ•°äºÞZ‹É用,他们是不需要jdk做开发的åQŒåªéœ€è¦jre能让java½E‹åºè·‘è“v来就可以äº?ji¨£n),那么每个客户˜q˜éœ€è¦æ‰‹åŠ¨åŽ»è®„¡½®çŽ¯å¢ƒå˜é‡å¤šéº»çƒ?ch¨³)啊åQŸæ‰€ä»¥å®‰è£…jre的时候安装程序自动帮你把jreçš„java.exeæ·ÕdŠ åˆîCº†(ji¨£n)¾pȝ»Ÿå˜é‡ä¸­ï¼ŒéªŒè¯çš„æ–¹æ³•很½Ž€å•,大家看到äº?ji¨£n)ç³»¾lŸçŽ¯å¢ƒå˜é‡çš„ path最前面æœ?#8220;%SystemRoot%\system32;%SystemRoot%;”˜q™æ ·çš„配¾|®ï¼Œé‚£ä¹ˆå†åŽ»Windows/system32下面åŽÈœ‹çœ‹å§åQŒå‘çŽîCº†(ji¨£n)什么?有一个java.exeã€?<br /> <br /> å¦‚æžœå¼ø™¡Œèƒ½å¤ŸæŠŠjdk/bin挪到system32变量前面åQŒå½“然也可以˜q«ä‹É使用jdk/jre里面的javaåQŒä¸˜q‡é™¤éžæœ‰å¿…要åQŒæˆ‘不徏议大家这么做。ä‹É用单独的jreè·‘java½E‹åºä¹Ÿç®—是客æˆïL(f¨¥ng)Ž¯å¢ƒä¸‹çš„ä¸€¿Uæµ‹è¯•ã€?<br /> <br /> ˜q™ä¸‹å¤§å®¶åº”该更清楚jdkå’Œjre内部的一些联¾pÕd’ŒåŒºåˆ«äº?ji¨£n)吧åQ?<br /> <br /> PS: 其实˜q˜æœ‰æ»¡å¤šæ„Ÿæƒ³å¯ä»¥æ€È»“的,一‹Æ¡å†™å¤šäº†(ji¨£n)怕大家扔砖头砸死我,怪我太罗唆。大家应该更加踏实更加务实的åŽÕdšä¸€äº›ç ”½I¶åƈ互相分äínå¿?j¨©)å¾—åQŒå¤§æ–¹å‘和太前沿的技术讨论是必要的但最好不要太多,毕竟自己基础都还没打好,什么都讲最新版本其实是˜q›æ­¥çš„一大障¼„ï¼ <br /> <br /> <br /> Java 学习(f¨¤n)杂谈åQˆäºŒåQ?<br /> Java 学习(f¨¤n)杂谈åQˆäºŒåQ?<br /> 鉴于上回写的一ç‚ÒŽ(gu¨©)„Ÿæƒ›_¤§å®¶ä¸å«Œå¼ƒåQŒéƒ½é¼“励ž®å¼Ÿ¾l§ç®‹å†™ä¸‹åŽ»ï¼Œå¥½ä¸å®ÒŽ(gu¨©)˜“½{‰åˆ°å›½åº†(ji¨£n)黄金周,实习(f¨¤n)æ€È®—有一个休息的阶段åQŒäºŽæ˜¯è¿™ž®±å¼€å§‹å†™½W¬äºŒ½‹‡äº†(ji¨£n)。希望这‹Æ¡å†™çš„仍然对志同道合的朋友们有所帮助。上回讲äº?ji¨£n)Java动态加载机制、classLoader原理和关于jdkå’Œjre三个问题。这‹Æ¡åšg¾l­ç€è®²ä¸€äº›å…·ä½“çš„¾cÕdº“?? <br /> <br /> 1åQ?关于集合框架¾c?<br /> ç›æ€¿¡å­¦è¿‡Java的各位对˜q™ä¸ªåè¯òq¶ä¸é™Œç”ŸåQŒå¯¹ java.util.*˜q™ä¸ªpackage肯定也不陌生。不知道大家查询API的时候怎么åŽÕd®¡è§†æˆ–者分析其中的一个packageåQŒæ¯ä¸ªåŒ…最重要的两个部分就是interfaceså’ŒclassesåQŒæŽ¥å£ä»£è¡¨äº†(ji¨£n)它能做什么,实现¾cÕdˆ™ä»£è¡¨äº?ji¨£n)它如何åŽÕdšã€‚关注实现类之前åQŒæˆ‘们应该先理解清楚它的来源接口åQŒä¸½Ž¡åœ¨j2se˜q˜æ˜¯j2ee中,都应该是˜q™æ ·ã€‚那么我们先看这三个接口åQšList、Set、Mapã€?<br /> 也许有些äºÞZ¸å¤ªç†Ÿæ‚(zh¨¨n)‰è¿™ä¸‰ä¸ªåå­—åQŒä½†ç›æ€¿¡å¤§éƒ¨åˆ†äh都熟æ‚(zh¨¨n)‰ArrayListåQŒLinkedListåQŒTreeSetåQŒHashSetåQŒHashMapåQ?Hashtable½{‰å®žçŽ°ç±»çš„åå­—ã€‚å®ƒä»¬çš„åŒºåˆ«ä¹Ÿæ˜¯æ»¡å®¹æ˜“ç†è§£çš„åQŒList攑֏¯ä»¥é‡å¤çš„对象集合åQŒSet放不可重复的对象¾l„合åQŒè€ŒMap则放 <Key,Value > ˜q™æ ·çš„名值对åQ?Key不可重复åQŒValue可以。这里有几个å®ÒŽ(gu¨©)˜“æ·äh·†çš„问题:(x¨¬) <br /> <br /> 到底Vectorå’ŒArrayListåQŒHashtableå’ŒHashMap有什么区别? <br /> 很多面试官喜‹Æ¢é—®˜q™ä¸ªé—®é¢˜åQŒå…¶å®žæ›´ä¸“业一点应该这样问åQšæ–°é›†åˆæ¡†æž¶å’Œæ—§é›†åˆæ¡†æž¶æœ‰å“ªäº›åŒºåˆ«ï¼Ÿæ–°é›†åˆæ¡†æž¶å¤§å®¶å¯ä»¥åœ¨˜q™äº›åŒ…中找since jdk1.2的,之前的如vectorå’ŒHashtable都是旧的集合框架包括的类。那么区别是åQ?<br /> a. 新集合框架的命名更加¿U‘学合理。例如List下的ArrayListå’ŒLinkedList <br /> b. 新集合框架下全部都是非线½E‹å®‰å…¨çš„。徏议去jdk里面包含的源代码里面自己åŽÖMº²è‡ªçœ‹çœ‹vectorå’ŒArrayList的区别吧。当然如果是jdk5.0之后的会(x¨¬)比较隄¡œ‹ä¸€ç‚¹ï¼Œå› äØ“(f¨´)又加入了(ji¨£n)泛型的语法,¾cÖM¼¼c++çš„template语法ã€?<br /> <br /> 那么大家是否惌™¿‡ä¸ÞZ»€ä¹ˆè¦ä»Žæ—§é›†åˆæ¡†æž¶é»˜è®¤å…¨éƒ¨åŠ é”é˜²æ­¢å¤šçº¿½E‹è®¿é—®æ›´æ–°åˆ°æ–°é›†åˆæ¡†æž¶å…¨éƒ¨å–消锁åQŒé»˜è®¤æ–¹å¼æ”¯æŒå¤š¾U¿ç¨‹åQ?当然需要的时候可以ä‹É用collections的静(r¨´n)态方法加锁达到线½E‹å®‰å…? <br /> ½W”者的观点是ä“Q何技术的发展都未必是遵åó@它们的初è¡ïL(f¨¥ng)š„åQŒå¾ˆå¤šé‡å¤§æ”¹å˜æ˜¯å—到客观环境的媄(ji¨£ng)响的。大家知道Java的初è¡äh˜¯ä¸ÞZ»€ä¹ˆè€Œå¼€å‘çš„éº½ï¼Ÿæ˜¯äØ“(f¨´)嵌入式程序开发的。记得上一½‹‡è®²åˆ°classLoaderæœºåˆ¶éº½ï¼Ÿé‚£æ­£æ˜¯äØ“(f¨´)äº?ji¨£n)节¾U¦åµŒå…¥å¼å¼€å‘环境下内存而设计的。而走åˆîC»Šå¤©ï¼ŒJava成了(ji¨£n)äºÞZ»¬å¿?j¨©)中ä¸ÞZº’联网诞生的语­a€ã€‚互联网意味着什么?多线½E‹æ˜¯å¿…然的趋åŠÑ€‚客观环境在变,JavaæŠ€æœ¯ä¹Ÿéšç€é£žé€Ÿå‘å±•ï¼Œå¯ÆD‡´­‘Šæ¥­‘Šè„±¼›Õd®ƒçš„初街÷€‚据说Sun公司其实ä¸ÀL‰“的是J2seåQŒç»“果又是由于客观环境媄(ji¨£ng)响,J2se几乎遗忘åQŒç•™åœ¨å¤§å®¶è°ˆè®ºç„¦ç‚¹çš„一直是j2eeã€?<br /> <br /> 技术的¾l†èŠ‚˜q™é‡Œž®×ƒ¸å¤šè¯´äº?ji¨£n),只有用äº?ji¨£n)æ‰èƒ½çœŸæ­£ç†è§£ã€‚è§£é‡Šè¿™äº›æ­£æ˜¯äØ“(f¨´)äº?ji¨£n)帮助大家理解正在学的和ž®†è¦å­¦çš„ä»ÖM½•技术。之后讲j2ee的时候还ä¼?x¨¬)再讨论ã€?<br /> 多扯句题外话åQšå‡ åå¹´å‰çš„ITå·¨äh是IBMåQŒMainframeå¸?j¨¬ng)场无äh可比。微软如何打败IBMåQŸæ­£æ˜¯ç”±äºŽç¡¬ä»‰™£žé€Ÿå‘展,对个人PC的需求这个客观环境,让微软通过OS¿UîCØ“(f¨´)äº?ji¨£n)第二个巨äh。下一个打败微软的呢?Google。如何做到的åQŸå¦‚æžœå¾®è½¯åÆˆä¸å’ŒIBM争大型机åQŒGoogle借着互联¾|‘飞速发展这个客观环境作为决定性因素,避开跟微软争OSåQŒè€Œæ˜¯èµ°æœç´¢å¼•擎这条èµ\åQŒç§°ä¸ºç¬¬3个巨人。那么第4个巨人是谁呢åQŸå¾ˆå¤šä¸“安™¢„­a€ž®†åœ¨äºšæ´²æˆ–者中国出玎ͼŒ WhateveråQŒå®¢è§‚环境变化趋势才是决定大方向的关键。当然笔者也希望ä¼?x¨¬)出现在中国åQŒ^_^~~ <br /> <br /> 2åQ?关于Java设计模式 <br /> íw«è¾¹çš„很多在看GOFçš?3¿Uè®¾è®¡æ¨¡å¼ï¼Œä¼ég¹Žå­¦ä¹ (f¨¤n)它无论在学校˜q˜æ˜¯åœ¨èŒåœºï¼Œéƒ½æˆäº?ji¨£n)一¿Uæµè¡Œé£Žæ°”。我不想列ä‹D解释˜q?3¿UDesign PatternåQ?我写˜q™äº›çš„初衷一直都是谈自己的经历和看法åQŒå¸Œæœ›èƒ½å¸®åŠ©å¤§å®¶ç†è§£ã€?<br /> 首先我觉得设计模式只是对一¾c»é—®é¢˜çš„一¿Ué€šç”¨è§£å†³åŠžæ³•åQŒåªè¦æ˜¯é¢å‘对象的编½E‹é¢„­a€éƒ½å¯ä»¥ç”¨å¾—上˜q?3¿Uã€‚理解它们最好的æ–ÒŽ(gu¨©)³•ž®±æ˜¯äº²è‡ªåŽÕd†™æ¯ä¸€¿Uï¼Œå“ªæ€•是一个简单的应用ž®Þpƒö够了(ji¨£n)。如果代码实çŽîC¹Ÿè®îC¸ä½çš„话,记忆它们对应的UML图会(x¨¬)是一个比较好的办法,当然前提是必™åÖMº†(ji¨£n)è§£UMLã€?<br /> 同时最好能利用Java自èín的类库帮助记忆,例如比较常用的观察者模式,在java.util.*有现成的Observer接口和Observable˜q™ä¸ªå®žçް¾c»ï¼Œçœ‹çœ‹æºä»£ç ç›¸ä¿¡å°±­‘›_¤Ÿç†è§£è§‚察者模式了(ji¨£n)。再比如装饰器模式,大家只要写几个关于java.io.*的程序就可以完全理解什么是装饰器模式了(ji¨£n)ã€‚æœ‰å¾ˆå¤šäºø™§‰å¾—刚入门的时候不该接触设计模式,比如囄¡µè®¾è®¡ä¸›ä¹¦¾pÕdˆ—很出名的那本《Java设计模式》,作è€? Steven John MetskeråQŒå¤§éƒ¨åˆ†ä¾‹å­è€å®žè¯´ä×o(h¨´)现在的我也很˜qähƒ‘。但我仍然不同意入门跟学ä¹?f¨¤n)设计模式有ä»ÖM½•冲突åQŒåªæ˜¯æˆ‘们需要知道每¿Uæ¨¡å¼çš„æ¦‚念的和典型的应用,˜q™æ ·æˆ‘们在第一‹Æ¡ç¼–å†?FileOutputStream、BufferedReader、PrintWriter的时候就能感觉到原来设计模式¼›ÀLˆ‘们如此之˜q‘,而且òq¶ä¸æ˜¯å¤šä¹ˆç¥ž¿U˜çš„东西ã€?<br /> <br /> 另外åQŒåœ¨å­¦ä¹ (f¨¤n)某些模式的同æ—Óž¼Œåè€Œæ›´èƒ½å¸®åŠ©æˆ‘ä»¬ç†è§£java¾cÕdº“的某些特炏V€‚例如当你编写原åž?Prototype)模式的时候,你必™åÖMº†(ji¨£n)解的æ˜?java.lang.Cloneable˜q™ä¸ªæŽ¥å£å’Œæ‰€æœ‰ç±»çš„基¾c»Objectçš„clone()˜q™ä¸ªæ–ÒŽ(gu¨©)³•。即深copy和浅copy的区别:(x¨¬) <br /> Object.clone()默认实现的是‹¹…copyåQŒä¹Ÿž®±æ˜¯å¤åˆ¶ä¸€ä»½å¯¹è±¡æ‹·è´ï¼Œä½†å¦‚果对象包含其他对象的引用åQŒä¸ä¼?x¨¬)复制引用,所以原对象和拷贝共用那个引用的对象ã€?<br /> æ·±copy当然ž®±æ˜¯åŒ…括对象的引用都一起复制啦。这样原对象和拷贝对象,都分别拥有一份引用对象。如果要实现深copyž®±å¿…™å»é¦–先实çŽ?java.lang.Cloneable接口åQŒç„¶åŽé‡å†™clone()æ–ÒŽ(gu¨©)³•。因为在Object中的clone()æ–ÒŽ(gu¨©)³•是protected½{‘֐çš„,è€?Cloneable接口的作用就是把protected攑֤§åˆ°publicåQŒè¿™æ ·clone()才能被重写ã€?<br /> <br /> 那么又有个问题了(ji¨£n)åQŸå¦‚果引用的对象又引用了(ji¨£n)其他对象呢?˜q™æ ·ä¸€ç›´åˆ¤æ–­åƈ复制下去åQŒæ˜¯ä¸æ˜¯æ˜‘Ö¾—很麻çƒ?ch¨³)?曄¡»æœ‰ä½å‰è¾ˆå‘Šè¯‰æˆ‘çš„æ–Ò?gu¨©)³•是重写cloneæ–ÒŽ(gu¨©)³•的时候直接把原对象序列化到磁盘上再反序列化回来,˜q™æ ·ä¸ç”¨åˆ¤æ–­ž®±å¯ä»¥å¾—åˆîC¸€ä¸ªæ·±copy的结果。如果大家不äº?ji¨£n)è§£åºåˆ—åŒ–çš„ä½œæ³•å»ø™®®çœ‹ä¸€çœ?ObjectOutputStreamå’ŒObjectInputStream <br /> <br /> å½’æ ¹¾l“底åQŒæ¨¡å¼åªæ˜¯æ€æƒ³ä¸Šçš„东西åQŒæŠŠå®ƒå½“成前人æ€È»“的经验其实一炚wƒ½ä¸äØ“(f¨´)˜q‡ã€‚鼓励大家动手自己去写,例如代理模式åQŒå¯ä»¥ç®€å•的写一个Child¾c»ï¼Œ Adult¾c…R€‚Child要买ä»ÖM½•东西由Adult来代理实现。简单来说就是Adult里的buy()内部实际调用的是Childçš„buy()åQŒå¯æ˜¯æš´éœ²åœ¨main函数的却是Adult.buy()。这样一个简单的½E‹åºž®Þpƒö够理解代理模式的基本含义äº?ji¨£n)ã€?<br /> <br /> Java 杂谈åQˆä¸‰åQ?<br /> Java 杂谈åQˆä¸‰åQ?<br /> ˜q™å·²¾lç¬”者写的第三篇Java杂记äº?ji¨£n),庆(ji¨£n)幸前两½‹‡ä¸€ç›´å¾—到论坛朋友们的支持鼓励,˜q˜æœ›å¤§å®¶¾l§ç®‹æŒ‡æ­£ä¸èƒö之处。笔者也一直æÍ(f¨´)望通过˜q™æ ·æ–¹å¼æ¸…醒的自审,来寻找自己技术上的不­‘³ä¹‹å¤„,希望和共同爱好Java的同仁们一èµähé«˜ã€?<br /> 前两‹Æ¡åˆ†åˆ«è®²˜qîCº†(ji¨£n)关于jvm、jdk、jre、collection、classLoader和一些Design Pattern的自我理解。这‹Æ¡ä»ç„¶ä¸å‡†å¤‡å¼€å§‹è¿‡æ¸¡åˆ°j2eeä¸­ï¼Œå› äØ“(f¨´)觉得˜q˜æœ‰ä¸€äº›ç¼„Žçš„j2se的问题没有æ€È»“完毕ã€?<br /> <br /> 1åQ?关于Object¾cȝ†è§?<br /> 大家都知道Object是所有Java¾cȝš„基类åQ?意味着所有的Java¾c»éƒ½ä¼?x¨¬)ç‘ô承äº?ji¨£n)Objectçš?1个方法。徏议大家去看看Objectçš?11个成员函数的源代码,ž®×ƒ¼š(x¨¬)知道默认的实现方式。比如equalsæ–ÒŽ(gu¨©)³•åQŒé»˜è®¤å®žçŽ°å°±æ˜¯ç”¨"=="来比较,即直接比较内存地址åQŒè¿”回true 或è€?false。而toString()æ–ÒŽ(gu¨©)³•åQŒè¿”回的串组成方式是?? <br /> "getClass().getName() + "@" + Integer.toHexString(hashCode())" <br /> 其实不用我过多的解释åQŒå¤§å®‰™ƒ½èƒ½çœ‹æ‡‚这个串的组成。接下来再看看hashCode()åQ?<br /> public native int hashCode()åQ?<br /> <br /> ç”׃ºŽæ˜¯nativeæ–ÒŽ(gu¨©)³•åQŒè·ŸOS的处理方式相养I¼Œæºä»£ç é‡Œä»…仅有一个声明çÅžäº?ji¨£n)。我们有兴趣的话完全可以åŽÀL·±½I¶å®ƒçš„hashCode到底是由O(ji¨¡n)S怎么样äñ”生的呢?但笔者徏议最重要的还是先è®îC½ä½¿ç”¨å®ƒçš„几条原则吧!首先如果equals()æ–ÒŽ(gu¨©)³•相同的对象具有相通的hashCodeåQŒä½†equals ()å¯¹è±¡ä¸ç›¸é€šçš„æ—¶å€™åÆˆä¸ä¿è¯hashCode()æ–ÒŽ(gu¨©)³•˜q”回不同的整数。而且下一‹Æ¡è¿è¡ŒåŒä¸€ä¸ªç¨‹åºï¼ŒåŒä¸€ä¸ªå¯¹è±¡æœªå¿…还是当初的那个hashCode() 哦ã€?<br /> 其余的方法呢åQŸnofigy()、notifyAll()、clone()、wait()都是nativeæ–ÒŽ(gu¨©)³•的,说明依赖于操作系¾lŸçš„实现。最后一个有­‘£çš„æ–ÒŽ(gu¨©)³•是finalize()åQŒç±»ä¼¼C++的析构函敎ͼŒ½{‘֐æ˜¯protectedåQŒè¯æ˜Žåªæœ‰ç‘ô承扩展了(ji¨£n)才能使用åQŒæ–¹æ³•体是空的,默示什么也不做。它的作用据½W”者的äº?ji¨£n)解仅仅是通知JVM此对象不再ä‹É用,随时可以被销毁,而实际的销毁权˜q˜æ˜¯åœ¨äºŽè™šæ‹Ÿæœºæ‰‹ä¸Šã€‚那么它真的什么也不做麽?未必åQŒå®žé™…上如果是线½E‹å¯¹è±¡å®ƒä¼?x¨¬)导致在一定范围内该线½E‹çš„优先¾U§åˆ«æé«˜åQŒå¯¼è‡´æ›´å¿«çš„被销毁来节约内存提高性能。其实从常理来说åQŒæˆ‘们也可以大概˜q™æ ·çŒœæµ‹å‡ºjvm做法的目的ã€?<br /> <br /> 2åQ?关于重蝲hashCode()与Collection框架的关¾p?<br /> ½W”者曾¾lå¬ä¸€ä½æžJava培训多年的前辈说在他看来hashCodeæ–ÒŽ(gu¨©)³•没有ä»ÖM½•意义åQŒä»…仅是ä¸ÞZº†(ji¨£n)配合证明å…ähœ‰åŒæ ·çš„hashCodeä¼?x¨¬)导致equals æ–ÒŽ(gu¨©)³•相等而存在的。连有的前辈都犯˜q™æ ·çš„错误,其实说明它还是满å®ÒŽ(gu¨©)˜“被忽略的。那么hashCode()æ–ÒŽ(gu¨©)³•到底做什么用åQ?<br /> <br /> 学过数据¾l“构的课½E‹å¤§å®‰™ƒ½ä¼?x¨¬)知道有一¿Uç»“构叫hash tableåQŒç›®çš„æ˜¯é€šè¿‡¾l™æ¯ä¸ªå¯¹è±¡åˆ†é…ä¸€ä¸ªå”¯ä¸€çš„烦(ch¨³)引来提高查询的效率。那么Java也不ä¼?x¨¬)肆意扭曲改变这个概念,所以hashCodeå”¯ä¸€çš„ä½œç”¨å°±æ˜¯äØ“(f¨´)支持数据¾l“构中的哈希表结构而存在的åQŒæ¢å¥è¯è¯ß_(d¨¢)¼Œä¹Ÿå°±æ˜¯åªæœ‰ç”¨åˆ°é›†åˆæ¡†æž¶çš„ Hashtable、HashMap、HashSet的时候,才需要重载hashCode()æ–ÒŽ(gu¨©)³•åQ?<br /> ˜q™æ ·æ‰èƒ½ä½¿å¾—我们能äh为的åŽÀLŽ§åˆ¶åœ¨å“ˆå¸Œ¾l“构中烦(ch¨³)引是否相½{‰ã€‚笔者ä‹D一个例子:(x¨¬) <br /> 曄¡»ä¸ÞZº†(ji¨£n)写一个求解类½E‹åºåQŒéœ€è¦éšæœºåˆ—å‡?,2,3,4¾l„成的不同排列组合,所以笔者写äº?ji¨£n)一个数¾l„类用int[]来存¾l„合¾l“æžœåQŒç„¶åŽæŠŠéšæœºäº§ç”Ÿçš„组合加入一个HashSet中,ž®±æ˜¯æƒ›_ˆ©ç”¨HashSet不包括重复元素的特点。可是HashSet怎么判断是不是重复的元素呢?当然是通过 hashCode()˜q”回的结果是否相½{‰æ¥åˆ¤æ–­å•¦ï¼Œå¯åšä¸€ä¸‹è¿™ä¸ªå®žéªŒï¼š(x¨¬) <br /> int[] A = {1,2,3,4}; <br /> int[] B = {1,2,3,4}; <br /> System.out.println(A.hashCode()); <br /> System.out.println(B.hashCode()); <br /> <br /> ˜q™æ˜Žæ˜Žæ˜¯åŒä¸€¿Uç»„合,却是不同的hashCodeåQŒåŠ å…¥Set的时候会(x¨¬)被当成不同的对象。这个时候我们就需要自己来重写hashCode()æ–ÒŽ(gu¨©)³•äº?ji¨£n),如何写呢åQŸå…¶å®žä¹Ÿæ˜¯åŸºäºŽåŽŸå§‹çš„hashCode()åQŒæ¯•竟那是操作系¾lŸçš„实现åQ?扑ֈ°ç›”R€šå¯¹è±¡å”¯ä¸€çš„æ ‡è¯†ï¼Œå®žçŽ°æ–¹å¼å¾ˆå¤šåQŒç¬”者的实现方式是:(x¨¬) <br /> 首先重写äº?ji¨£n)toString()æ–ÒŽ(gu¨©)³•: <br /> return A[0]“+” A[1]“+” A[2]“+” A[3]; //昄¡¤ºä¸Šæ¯”较直è§?<br /> 然后利用toString()来计½Ž—hashCode()åQ?<br /> return this.toString().hashCode()åQ?<br /> ˜q™æ ·ä¸Šè¿°Aå’ŒB˜q”回的就都是”1234”åQŒåœ¨‹¹‹è¯•toString().hashCode()åQŒç”±äºŽString在内存中的副本是一æ ïL(f¨¥ng)š„åQ?#8221;1234”.hashCode()˜q”回的一定是相同的结果ã€?<br /> <br /> 说到˜q™ï¼Œç›æ€¿¡å¤§å®¶èƒ½ç†è§£å¾—比我更好åQŒä»ŠåŽåƒä¸‡ä¸è¦å†è¯¯è§£hashCode()æ–ÒŽ(gu¨©)³•的作用ã€?<br /> <br /> 3åQ?关于Class¾cÈš„æˆå‘˜å‡½æ•°ä¸ŽJava反射机制 <br /> 很早刚接触Javaž®±å¬å¾ˆå¤šè€å¸ˆè¯´è¿‡Java的动态运行时机制、反ž®„机制等。确实它们都是Java的显著特点,˜qè¡Œæ—¶åŠ è½½ç¬”è€…åœ¨½W¬ä¸€½‹‡ä»‹¾lè¿‡äº?ji¨£n),现在惌™®²è®²åž®„机制。在Java中,主要是通过java.lang包中的Class¾cÕd’ŒMethod¾cÀL¥å®žçŽ°å†…å­˜åå°„æœºåˆ¶çš„ã€?<br /> 熟æ?zh¨¨n)‰C++çš„äh一定知道下面这样在C++中是做不到的åQ?˜qè¡Œæ—¶ä»¥å­—符串参æ•îC¼ é€’一个类名,ž®±å¯ä»¥å¾—到这个类的所有信息,包括它所有的æ–ÒŽ(gu¨©)³•åQŒå’Œæ–ÒŽ(gu¨©)³•的详¾l†ä¿¡æ¯ã€‚还可以实例化一个对象,òq‰™€šè¿‡æŸ¥åˆ°çš„æ–¹æ³•名来调用该对象的ä“Q何方法。这是因为Java的类在内存中除了(ji¨£n)C++中也有的é?r¨´n)态动态数据区之外åQŒè¿˜åŒ…括一份对¾c»è‡ªíw«çš„æè¿°åQŒä¹Ÿæ­£æ˜¯é€šè¿‡˜q™æ˜qîC¸­çš„信息,才能帮助我们才运行时è¯Õd–里面的内容,得到需要加载目标类的所有信息,从而实现反ž®„机制。大家有没有惌™¿‡å½“我们需要得åˆîC¸€ä¸ªJavaBean的实例的时候,怎么知道它有哪些属性呢åQŸå†æ˜Žæ˜¾½Ž€å•不˜q‡çš„例子ž®±æ˜¯è‡ªå·±å†™ä¸€ä¸ªJavaBean的解析器åQ?<br /> <br /> a. 通过Class.forName(“Bean的类å?#8221;)得到Class对象åQŒä¾‹å¦‚叫ABeanClass <br /> b. 通过ABeanClassçš„getMethods()æ–ÒŽ(gu¨©)³•åQŒå¾—到Method[]对象 <br /> c. 按照规范所有getæ–ÒŽ(gu¨©)³•名后的单词就代表着该Bean的一个属æ€?<br /> d. 当已¾lçŸ¥é“一个方法名åQŒå¯ä»¥è°ƒç”¨newInstance()得到一个实例,然后通过invoke()æ–ÒŽ(gu¨©)³•ž®†æ–¹æ³•的名字和方法需要用的参æ•îC¼ é€’进去,ž®±å¯ä»¥åŠ¨æ€è°ƒç”¨æ­¤æ–ÒŽ(gu¨©)³•ã€?<br /> <br /> 当然˜q˜æœ‰æ›´å¤æ‚的应用åQŒè¿™é‡Œå°±ä¸èµ˜˜qŽÍ¼Œå¤§å®¶å¯ä»¥å‚考Class¾cÕd’ŒMethod¾cÈš„æ–ÒŽ(gu¨©)³•ã€?<br /> <br /> 4åQ?坦言Synchronize的本è´?<br /> Synchronize大家都知道是同步、加锁的意思,其实它的本质˜qœæ²¡æœ‰å¤§å®¶æƒ³å¾—那么复杂。声明Synchronize的方法被调用的时候,锁其实是加蝲对象上,当然如果是静(r¨´n)态类则是加在¾cÖM¸Šçš„锁åQŒè°ƒç”¨ç»“束锁被解除。它的实现原理很½Ž€å•,仅仅是不让第二把锁再‹Æ¡è¢«åŠ åœ¨åŒä¸€ä¸ªå¯¹è±¡æˆ–¾cÖM¸ŠåQŒä»…此而已。一个简单的例子­‘³ä»¥è¯´æ˜Žé—®é¢˜åQ?<br /> class A{ <br /> synchronized void f(){} <br /> void g(){} <br /> } <br /> <br /> 当A的一个对象a被第一个线½E‹è°ƒç”¨å…¶f()æ–ÒŽ(gu¨©)³•的时候,½W¬äºŒä¸ªçº¿½E‹ä¸èƒ½è°ƒç”¨açš„synchronizedæ–ÒŽ(gu¨©)³•例如f()åQŒå› ä¸ºé‚£æ˜¯åœ¨è¯•图在对象上加第二把锁。但调用g()å´æ˜¯å¯ä»¥çš„ï¼Œå› äØ“(f¨´)òq¶æ²¡æœ‰åœ¨åŒä¸€å¯¹è±¡ä¸ŠåŠ ä¸¤æŠŠé”çš„è¡ŒäØ“(f¨´)产生ã€?<br /> ˜q™æ ·å¤§å®¶èƒ½ç†è§£äº†(ji¨£n)麽?明白它的原理能更好的帮助大家设计同步机制åQŒä¸è¦æ»¥ç”¨åР锁ã€?<br /> <br /> PSåQšä¸‹½‹‡ç¬”者计划开始对J2ee接触到的各个斚w¢æ¥è¿›è¡Œæ€È»“åQŒè°ˆè°ˆè‡ªå·Þqš„¾léªŒå’Œæƒ³æ³•。希望大家还能一如既往的支持笔者写下去åQŒæŒ‡æ­£ä¸­‘³ä¹‹å¤„ã€?<br /> <br /> Java杂谈åQˆå››åQ?<br /> <br /> 不知不觉已经写到½W¬å››½‹‡äº†(ji¨£n)åQŒè®ºå›é‡Œé¢ä¸æ–­çš„æœ‰æœ‹å‹é¼“励我写下厅R€‚坚持自å·Þqš„作风åQŒæŠŠä¸€åˆ‡è¿·æƒ‘不å®ÒŽ(gu¨©)˜“理清楚的知识讲出来,讲到大家都能听懂åQŒé‚£ä¹ˆè‡ªå·±å°±çœŸçš„æ‡‚了(ji¨£n)。最˜q‘在公司实习(f¨¤n)的时候Trainer跟我讲了(ji¨£n)很多¾lå…¸äº‹è¿¹åQŒå¯¹˜q˜æœªæ¯•业的我来说是笔不小的胦(ch¨³)富,我自å·Þqš„信念是:(x¨¬)人在逆境中成长的速度要远˜qœå¿«˜q‡é¡ºå¢ƒä¸­åQŒè¿™æ äh¥çœ‹ä¸€åˆ‡éƒ½èƒ½æ¬£ç„¶æŽ¥å—了(ji¨£n)ã€?<br /> 好了(ji¨£n)åQŒé—²è¯ä¸è¯´äº†(ji¨£n)åQŒç¬¬ä¸‰ç¯‡è®²çš„æ˜¯åž®„机刉™›†åˆæ¡†æž¶ä¹‹¾cȝš„åQŒè¿™‹Æ¡æ‰“½Ž—讲讲自己对反序列化和多¾U¿ç¨‹çš„理解。希望能对大家学ä¹?f¨¤n)Java起到帮助?? <br /> <br /> 1åQŽå…³äºŽåºåˆ—化和反序列åŒ?<br /> 应该大家都大概知道Java中序列化和反序列化的意思,序列化就是把一个Java对象转换成二˜q›åˆ¶˜q›è¡Œ¼‚ç›˜ä¸Šä¼ è¾“或者网¾lœæµçš„传输,反序列化的意思就是把˜q™ä¸ªæŽ¥å—到的二进制流重新¾l„装成原来的对象逆过½E‹ã€‚它们在Java中分别是通过ObjectInputStreamå’?ObjectInputStream˜q™ä¸¤ä¸ªç±»æ¥å®žçŽ°çš„åQˆä»¥ä¸‹åˆ†åˆ«ç”¨oiså’Œoos来简¿UŽÍ¼‰(j¨ª)ã€?<br /> <br /> oosçš„writeObject()æ–ÒŽ(gu¨©)³•用来执行序列化的˜q‡ç¨‹åQŒoisçš„readObject()用来执行反序列化的过½E‹ï¼Œåœ¨ä¼ è¾“二˜q›åˆ¶‹¹ä¹‹å‰ï¼Œéœ€è¦è®²˜q™ä¸¤ä¸ªé«˜å±‚流对象˜qžæŽ¥åˆ°åŒä¸€ä¸ªChannel上,˜q™ä¸ªChannel可以是磁盘文ä»Óž¼Œä¹Ÿå¯ä»¥æ˜¯socket底层‹¹ã€‚所以无论用哪种方式åQŒåº•层流对象都是以构造函数参数的形式传递进ooså’Œois˜q™ä¸¤ä¸ªé«˜å±‚流åQŒè¿žæŽ¥å®Œæ¯•了(ji¨£n)才可以进行二˜q›åˆ¶æ•°æ®ä¼ è¾“的。例子:(x¨¬) <br /> 可以是文件流通道 <br /> file = new File(“C:/data.dat”); <br /> oos = new ObjectOutputStream(new FileOutputStream(file)); <br /> ois = new ObjectInputStream(new FileInputStream(file)); <br /> <br /> 或者网¾lœæµé€šé“ <br /> oos = new ObjectOutputStream(socket.getOutputStream()); <br /> ois = new ObjectInputStream(socket.getInputStream()); <br /> <br /> 不知道大家是否注意到oosæ€ÀL˜¯åœ¨ois之前定义åQŒè¿™é‡Œä¸å¸Œæœ›å¤§å®¶è¯¯è§£˜q™ä¸ª™åºåºæ˜¯å›ºå®šçš„么?回答是否定的åQŒé‚£ä¹ˆæœ‰™åºåºè¦æ±‚么?回答是肯定的。原则是什么呢åQ?<br /> 原则是互相对接的输入/输出‹¹ä¹‹é—´å¿…™åÀL˜¯output‹¹å…ˆåˆå§‹åŒ–然后再input‹¹åˆå§‹åŒ–åQŒå¦åˆ™å°±ä¼?x¨¬)抛异常。大家肯定会(x¨¬)问䨓(f¨´)什么?只要½Eå¾®çœ‹ä¸€çœ‹è¿™ä¸¤ä¸ª¾cÈš„æºä»£ç æ–‡ä»¶å°±å¤§æ¦‚知道äº?ji¨£n),output‹¹çš„ä»ÕdŠ¡å¾ˆç®€å•ï¼Œåªè¦æŠŠå¯¹è±¡è{换成二进制往通道中写ž®±å¯ä»¥äº†(ji¨£n)åQŒä½†input‹¹éœ€è¦åšå¾ˆå¤šå‡†å¤‡å·¥ä½œæ¥æŽ¥å—åÆˆæœ€¾lˆé‡¾l„这个ObjectåQŒæ‰€ä»¥ObjectInputStream的构造函æ•îC¸­ž®±éœ€è¦ç”¨åˆ°output初始化发送过来的header信息åQŒè¿™ä¸ªæ–¹æ³•叫å?readStreamHeader()åQŒå®ƒ?y¨­u)®†ä¼?x¨¬)去读两个Short值用于决定用多大的缓存来存放通道发送过来的二进制流åQŒè¿™ä¸ªç¼“存的sizeå› jre的版本不同是不一æ ïL(f¨¥ng)š„。所以output如果不先初始化,input的构造函数首先就无法正确˜qè¡Œã€?<br /> <br /> 对于上面两个例子åQŒç¬¬ä¸€ä¸ªé¡ºåºæ˜¯ä¸¥æ ¼çš„,½W¬äºŒä¸ªå› ä¸ºooså’Œois˜qžæŽ¥çš„å·²¾lä¸æ˜¯å¯¹æ–¹äº†(ji¨£n)åQŒè€Œæ˜¯socket另外一端的‹¹ï¼Œéœ€è¦ä¸¥æ ¼æŒ‰ç…§å¦å¤–一方对接的output‹¹å…ˆäºŽå¯¹æŽ¥çš„input‹¹æ‰“开才能™åºåˆ©˜qè¡Œã€?<br /> <br /> ˜q™ä¸ªwriteObjectå’ŒreadObject本èínž®±æ˜¯¾U¿ç¨‹å®‰å…¨çš„,传输˜q‡ç¨‹ä¸­æ˜¯ä¸å…è®¸è¢«òq¶å‘讉K—®çš„。所以对象能一个一个接˜qžä¸æ–­çš„传过来,有很多äh在运行的时候会(x¨¬)¼„°åˆ°EOFException, 然后百思不得其解,åŽÕd„¿Uè®ºå›é—®è§£å†³æ–ÒŽ(gu¨©)¡ˆã€‚其实笔者这里想è¯ß_(d¨¢)¼Œ˜q™ä¸ªå¼‚常不是必须声明的,也就是说它虽然是异常åQŒä½†å…¶å®žæ˜¯æ­£å¸¸è¿è¡Œç»“束的标志。EOF表示è¯Õdˆ°äº?ji¨£n)文件尾åQŒå‘送结束自然连接也ž®±æ–­å¼€äº?ji¨£n)。如果这影响åˆîCº†(ji¨£n)你程序的正确性的话,请各位静(r¨´n)下心(j¨©)来看看自å·Þq¨‹åºçš„业务逻辑åQŒè€Œä¸è¦æŠŠæ³¨æ„åŠ›ç‹­éš˜çš„èšé›†åœ¨å‘é€å’ŒæŽ¥å—çš„æ–¹æ³•ä¸Šã€‚å› ä¸ºç¬”è€…ä¹Ÿè¢«è¿™æ ïL(f¨¥ng)š„bug困扰äº?整天åQŒè¢«å¾ˆå¤šè®ºå›çš„帖子误解了(ji¨£n)很多‹Æ¡æœ€åŽå¾—出的教训。如果在while循环中去readObjectåQŒæœ¬è´¨ä¸Šæ˜¯æ²¡æœ‰é—®é¢˜çš„åQŒæœ‰å¯¹è±¡æ•°æ®æ¥å°±ä¼?x¨¬)读åQŒæ²¡æœ‰å°±è‡ªåЍé˜Õd¡žã€‚那么抛出EOFExceptionä¸€å®šæ˜¯å› äØ“(f¨´)˜qžæŽ¥æ–­äº†(ji¨£n)˜q˜åœ¨¾l§ç®‹readåQŒä»€ä¹ˆåŽŸå› å¯¼è‡´è¿žæŽ¥æ–­äº?ji¨£n)å‘¢åQŸä¸€å®šæ˜¯ä¸šåŠ¡é€»è¾‘å“ªé‡Œå­˜åœ¨é”™è¯¯åQŒæ¯”如NullPointã€?ClassCaseException、ArrayOutofBoundåQŒå³ä½¿ç¨‹åºè¾ƒå¤§ä¹Ÿæ²¡å…³¾p»ï¼Œæœ€å¤šåªè¦å•步调适一‹Æ¡å°±èƒ½å¾ˆå¿«å‘现bugòq¶ä¸”解决它ã€?<br /> <br /> 难怪一位程序大师说˜q‡ï¼š(x¨¬)解决问题90åQ…靠¾léªŒåQ?åQ…靠技术,剩下5åQ…靠˜qæ°”åQçœŸæ˜¯é‡‘玉良­a€åQŒç¬”者大概查阅过不下30½‹‡è®¨è®ºåœ¨while循环中ä‹Éç”?readObject抛出EOFExceptionde 的帖子,大家都盲目的åŽÕd…³æ³¨è§£é‡Šè¿™ä¸ªåè¯ã€ååºåˆ—åŒ–çš„è¡ŒäØ“(f¨´)或反对这样写而没有一个ähè®¤äØ“(f¨´)EOF是正¼‹®çš„è¡ŒäØ“(f¨´)åQŒå®ƒå…¶å®žå¾ˆè€å®žçš„åœ¨åšå®ƒçš„äº‹æƒ…ã€‚äØ“(f¨´)什么大安™ƒ½å¿½ç•¥äº?ji¨£n)真正出错误的地方呢åQŸä¸¤ä¸ªå­—åQŒç»éªŒï¼ <br /> <br /> 2åQŽå…³äºŽJava的多¾U¿ç¨‹¾~–程 <br /> 关于Java的线½E‹ï¼Œåˆå­¦æˆ–者接触不æ·Þqš„大概也能知道一些基本概念,同时又会(x¨¬)很迷惑线½E‹åˆ°åº•是怎么回事åQŸå¦‚æžœæœ‰äºø™®¤ä¸ø™‡ªå·±å·²¾læ‡‚äº?ji¨£n)不妨来回答下面的问题ï¼?x¨¬) <br /> a. A对象实现Runnable接口åQŒA.start()˜qè¡ŒåŽæ‰€è°“çš„¾U¿ç¨‹å¯¹è±¡æ˜¯è°åQŸæ˜¯A么? <br /> b. ¾U¿ç¨‹çš„wait()、notify()æ–ÒŽ(gu¨©)³•到底是做什么时候用的,什么时候用åQ?<br /> c. ä¸ÞZ»€ä¹ˆçº¿½E‹çš„suspendæ–ÒŽ(gu¨©)³•ä¼?x¨¬)被标注˜q‡æ—¶åQŒä¸æŽ¨èå†ä‹É用,¾U¿ç¨‹˜q˜èƒ½æŒ‚è“v么? <br /> d. ä¸ÞZº†(ji¨£n)同步我们ä¼?x¨¬)对¾U¿ç¨‹æ–ÒŽ(gu¨©)³•声明Synchronized来加锁在对象上,那么如果父类的f()æ–ÒŽ(gu¨©)³•加了(ji¨£n)SynchronizedåQŒå­¾c»é‡å†™f()æ–ÒŽ(gu¨©)³•必须也加Synchronized么?如果子类的f()æ–ÒŽ(gu¨©)³•重写时声明Synchronizedòq¶è°ƒç”¨super.f()åQŒé‚£ä¹ˆå­¾cÕd¯¹è±¡ä¸Šåˆ°åº•有几把锁呢?ä¼?x¨¬)因为竞争äñ”生死锁么åQ?<br /> <br /> 呵呵åQŒå„位能回答上来几道呢?如果˜q™äº›éƒ½èƒ½½{”上来,说明对线½E‹çš„æ¦‚念˜q˜æ˜¯æ»¡æ¸…æ™°çš„åQŒè™½è¯´è¿˜˜qœè¿œä¸èƒ½½Ž—精通。笔者这里一一做回½{”,¼„äºŽ½‹‡å¹…的原因,½W”者尽量说得简介一点,如果大家有疑惑的‹Æ¢è¿Žä¸€èµ¯‚®¨è®ºã€?<br /> <br /> 首先½W¬ä¸€ç‚¹ï¼Œ¾U¿ç¨‹è·Ÿå¯¹è±¡å®Œå…¨æ˜¯ä¸¤å›žäº‹ï¼Œè™½ç„¶æˆ‘们也常说线½E‹å¯¹è±¡ã€‚但当你用run()å’Œstart()来启动一个线½E‹ä¹‹åŽï¼Œ¾U¿ç¨‹å…¶å®žè·Ÿè¿™ä¸ªç‘ô承了(ji¨£n) Thread或实çŽîCº†(ji¨£n)Runnable的对象已¾læ²¡æœ‰å…³¾pÖMº†(ji¨£n)åQŒå¯¹è±¡åªèƒ½ç®—内存中可用资源而对象的æ–ÒŽ(gu¨©)³•只能½Ž—内存正文区可以执行的代码段而已。既然是资源和代码段åQŒå¦å¤–一个线½E‹å½“然也可以去访问,main函数执行ž®Þp‡³ž®‘会(x¨¬)启动两个¾U¿ç¨‹åQŒä¸€ä¸ªæˆ‘ä»¬ç§°ä¹‹äØ“(f¨´)ä¸Èº¿½E‹ï¼Œ˜q˜ä¸€ä¸ªæ˜¯åžƒåœ¾æ”‰™›†å™¨çš„¾U¿ç¨‹åQŒä¸»¾U¿ç¨‹¾l“束ž®±æ„å‘³ç€½E‹åº¾l“束åQŒå¯åžƒåœ¾æ”‰™›†å™¨çº¿½E‹å¾ˆå¯èƒ½æ­£åœ¨å·¥ä½œã€?<br /> <br /> ½W¬äºŒç‚¹ï¼Œwait()å’Œsleep()¾cÖM¼¼åQŒéƒ½æ˜¯è®©¾U¿ç¨‹å¤„于é˜Õd¡žçŠ¶æ€æš‚åœä¸€ŒD‰|—¶é—ß_(d¨¢)¼Œä¸åŒä¹‹å¤„在于waitä¼?x¨¬)释攑ֽ“前线½E‹å æœ‰çš„æ‰€æœ‰çš„锁,è€?sleep不会(x¨¬)。我们知道获得锁的唯一æ–ÒŽ(gu¨©)³•是进入了(ji¨£n)Synchronized保护代码ŒDµï¼Œæ‰€ä»¥å¤§å®¶ä¼š(x¨¬)发现只有Synchronizedæ–ÒŽ(gu¨©)³•中才ä¼?x¨¬)出ç?waitåQŒç›´æŽ¥å†™ä¼?x¨¬)给警告没有获得当前对象的锁。所以notifyè·Ÿwait配合使用åQŒnotifyä¼?x¨¬)重新把锁还¾l™é˜»å¡žçš„¾U¿ç¨‹é‡è€Œä‹Éå…¶ç‘ô¾l­æ‰§è¡Œï¼Œå½“有多个对象waitäº?ji¨£n),notify不能¼‹®å®šå”¤é†’哪一个,必经锁只有一把,所以一般用notifyAll()来让它们自己æ ÒŽ(gu¨©)®ä¼˜å…ˆ¾U§ç­‰ç«žäº‰é‚£å”¯ä¸€çš„一把锁åQŒç«žäº‰åˆ°çš„线½E‹æ‰§è¡Œï¼Œå…¶ä»–¾U¿ç¨‹åªè¦¾l§ç®‹waitã€?<br /> <br /> 从前Java允许在一个线½E‹ä¹‹å¤–把¾U¿ç¨‹æŒ‚è“våQŒå³è°ƒç”¨suspendæ–ÒŽ(gu¨©)³•åQŒè¿™æ ïL(f¨¥ng)š„æ“ä½œæ˜¯æžä¸å®‰å…¨çš„。根据面向对象的思想每个对象必须对自å·Þqš„è¡ŒäØ“(f¨´)è´Ÿè´£åQŒè€Œå¯¹è‡ªå·±çš„æƒåŠ›è¿›è¡Œå°è£…ã€‚å¦‚æžœä“Q何外步对象都能ä‹É¾U¿ç¨‹è¢«æŒ‚赯‚€(g¨¨)Œé˜»å¡žçš„话,½E‹åºå¾€å¾€ä¼?x¨¬)å‡ºçŽ°æØœä¹±å¯¼è‡´å´©æºƒï¼Œæ‰€ä»¥è¿™æ ïL(f¨¥ng)š„æ–ÒŽ(gu¨©)³•自然是被毙掉äº?ji¨£n)啦ã€?<br /> <br /> 最后一个问题比较有意思,首先回答的是子类重写f()æ–ÒŽ(gu¨©)³•可以加Synchronized也可以不加,如果加了(ji¨£n)而且˜q˜å†…部调用了(ji¨£n)super.f ()çš„è¯ç†è®ºä¸Šæ˜¯åº”è¯¥å¯¹åŒä¸€å¯¹è±¡åŠ ä¸¤æŠŠé”çš„ï¼Œå› äØ“(f¨´)每次调用Synchronizedæ–ÒŽ(gu¨©)³•都要加一把,调用子类的f首先ž®±åŠ äº?ji¨£n)一把,˜q›å…¥æ–ÒŽ(gu¨©)³•内部调用父类çš?f又要加一把,加两把不是互斥的么?那么调父¾c»f加锁不就必须永远½{‰å¾…已经加的锁释放而造成死锁么?实际上是不会(x¨¬)的,˜q™ä¸ªæœºåˆ¶å«é‡˜q›å…¥åQŒå½“父类的fæ–ÒŽ(gu¨©)³•è¯•å›¾åœ¨æœ¬å¯¹è±¡ä¸Šå†åŠ ä¸€æŠŠé”çš„æ—¶å€™ï¼Œå› äØ“(f¨´)当前¾U¿ç¨‹æ‹¥æœ‰˜q™ä¸ªå¯¹è±¡çš„锁åQŒä¹Ÿå¯ä»¥ç†è§£ä¸ºå¼€å¯å®ƒçš„钥匙,所以同一个线½E‹åœ¨åŒä¸€å¯¹è±¡ä¸Šè¿˜æ²¡é‡Šæ”¾ä¹‹å‰åŠ ½W¬äºŒ‹Æ¡é”æ˜¯ä¸ä¼?x¨¬)出问题的,˜q™ä¸ªé”å…¶å®žæ ¹æœ¬å°±æ²¡æœ‰åŠ ï¼Œå®ƒæœ‰äº?ji¨£n)钥匙,不管加几把还是可以进入锁保护的代码段åQŒç•…通无阻,所以叫重进入,我们可以½Ž€å•认为第二把锁没有加上去ã€?<br /> <br /> 总而言之,Synchronized的本质是不让其他¾U¿ç¨‹åœ¨åŒä¸€å¯¹è±¡ä¸Šå†åŠ ä¸€æŠŠé”ã€?<br /> Java杂谈åQˆäº”åQ?<br /> Java杂谈åQˆäº”åQ?<br /> <br /> <br /> 本来预计J2se只讲äº?ji¨£n)第四篇ž®±æ”¶ž®¾äº?ji¨£n)åQŒå¯æ˜¯ç‰ˆä¸ÕdŽšçˆ±æŠŠå¸–å­¾|®é¡¶é•¿æœŸè®©å¤§å®¶æµè§ˆè®©ž®å¼Ÿå€æ„Ÿè´£ä“Q重大åQŒåŠ¡å¿…è¿½æ±‚æœ€åˆ°æ›´å¥½ï¼Œæ‰€ä»¥å…³äºŽJ2se一些没有提到的部分åQŒå†³å®šå†å†™å‡ ½‹‡æŠŠå¸¸ç”¨çš„部分经验全部写出来供大家讨论切¼‚‹ã€‚这一½‹‡å‡†å¤‡è®²ä¸€è®²Xml解析包和Java SwingåQŒç„¶åŽä¸‹ä¸€½‹‡å†è®²java.security包关于Java沙箱安全机制和RMI机制åQŒå†˜q›å…¥J2ee的部分,暂时ž®±åš˜q™æ ·çš„计划了(ji¨£n)。如果由于实ä¹?f¨¤n)繁忙更新稍微慢了(ji¨£n)一些,希望各位见谅åQ?<br /> <br /> 1åQ?Java关于XML的解æž?<br /> ç›æ€¿¡å¤§å®¶å¯¹XML都不陌生åQŒå«ä¹‰æ˜¯å¯æ‰©å±•标记语­a€ã€‚本íw«å®ƒä¹Ÿå°±æ˜¯ä¸€ä¸ªæ•°æ®çš„载体以树(w¨¨i)状表现åŞ式出现。后来慢慢的数据变成äº?ji¨£n)信息,区别是信息可以包括可变的状态从而针对程序硬¾~–ç çš„åšæ³•å˜é©äØ“(f¨´)针对¾lŸä¸€æŽ¥å£¼‹¬ç¼–码而可变状态作ä¸ÞZ¿¡æ¯è¿›å…¥äº†(ji¨£n)XML中存储。这æ äh”¹å˜çŠ¶æ€å®žçŽ°æ‰©å±•çš„å”¯ä¸€å·¥ä½œæ˜¯åœ¨XML中添加一ŒD‰|–‡æœ¬ä¿¡æ¯å°±å¯ä»¥äº?ji¨£n),代码不需要改动也不需要重新编译。这个灵‹zÀL€§æ˜¯XML诞生时候谁也没惛_ˆ°çš„ã€?<br /> <br /> 当然åQŒå¦‚果接口要能提取XML中配¾|®çš„信息ž®±éœ€è¦ç¨‹åºèƒ½è§£æžè§„范的XMLæ–‡äšgåQŒJava中当然要提高包对˜q™ä¸ªè¡ŒäØ“(f¨´)˜q›è¡Œæœ‰åˆ©æ”¯æŒã€‚笔者打½Ž—讲到的两个包是 org.w3c.domå’Œjavax.xml.parsers和。(大家可以‹¹è§ˆä¸€ä¸‹è¿™äº›åŒ…中间的接口和¾cÕd®šä¹‰ï¼‰(j¨ª) <br /> <br /> Javax.xml.parsers包很½Ž€å•,没有接口åQŒä¸¤ä¸ªå·¥åŽ‚é…ä¸¤ä¸ªè§£æžå™¨ã€‚æ˜¾ç„¶è§£æžXML是有两种方式的:(x¨¬)DOM解析和SAX解析。本质上òq¶æ²¡æœ‰è°å¥½è°ä¸å¥½åQŒåªæ˜¯å®žçŽ°çš„æ€æƒ³ä¸ä¸€æ ïL(f¨¥ng)Åžäº?ji¨£n)。给一个XMLæ–‡äšg的例子:(x¨¬) <br /> <?xml version=”1.0” encoding=”UTF-8” > <br /> <root > <br /> <child name=”Kitty” > <br /> A Cat <br /> </child > <br /> </root > <br /> <br /> 所谓DOM解析的思èµ\是把整个æ ?w¨¨i)状囑֭˜å…¥å†…存中åQŒéœ€è¦é‚£ä¸ªèŠ‚ç‚¹åªéœ€è¦åœ¨æ ?w¨¨i)上搜çƒ?ch¨³)ž®±å¯ä»¥è¯»åˆ°èŠ‚ç‚¹çš„å±žæ€§ï¼Œå†…å®¹½{‰ï¼Œ˜q™æ ·çš„好处是所有节点皆在内存可以反复搜索重复ä‹É用,¾~ºç‚¹æ˜¯éœ€è¦æ¶ˆè€—相应的内存½Iºé—´ã€?<br /> <br /> 自然SAX解析的思èµ\ž®±æ˜¯ä¸ÞZº†(ji¨£n)克服DOMçš„ç¼ºç‚¹ï¼Œä»¥äº‹ä»¶è§¦å‘äØ“(f¨´)基本思èµ\åQŒé¡ºåºçš„æœçƒ¦(ch¨³)下来åQŒç¢°åˆîCº†(ji¨£n)Element之前触发什么事ä»Óž¼Œ¼„°åˆ°ä¹‹åŽåšä»€ä¹ˆåŠ¨ä½œã€‚ç”±äºŽéœ€è¦è‡ªå·±æ¥å†™è§¦å‘äº‹ä»¶çš„å¤„ç†æ–ÒŽ(gu¨©)¡ˆåQŒæ‰€ä»¥éœ€è¦å€ŸåŠ©å¦å¤–ä¸€ä¸ªè‡ªå®šä¹‰çš„HandleråQŒå¤„于org.xml.sax.helpers包中。它的优点当然是不用整个包都è¯Õd…¥å†…å­˜åQŒç¼ºç‚¹ä¹Ÿæ˜¯åªèƒ½é¡ºåºæœç´¢ï¼Œèµ°å®Œä¸€éå°±å¾—重来ã€?<br /> <br /> 大家很容易就能猜刎ͼŒæŽ¥è§¦åˆ°çš„J2ee框架用的是哪一¿Uï¼Œæ˜„¡„¶æ˜¯DOM。因为类似StrutsåQŒHibernate框架配置文äšg毕竟是很ž®çš„一部分配置信息åQŒè€Œä¸”需要频¾Jæœç´¢æ¥è¯Õd–åQŒå½“然会(x¨¬)采用DOM方式åQˆå…¶å®žSAX内部也是用DOM采用的结构来存储节点信息的)(j¨ª)。现在无论用什么框æžÓž¼Œ˜q˜çœŸéš‘֏‘çŽîC‹Éç”?SAX来解析XML的技术了(ji¨£n)åQŒå¦‚果哪位仁兄知道,误‚®©½W”者也学习(f¨¤n)学习(f¨¤n)ã€?<br /> <br /> 既然解析方式有了(ji¨£n)åQŒé‚£ä¹ˆå°±éœ€è¦æœ‰è§£æžçš„存储位¾|®ã€‚不知道大家是否发现org.w3c.dom˜q™ä¸ªåŒ…是没有实现¾cÕd…¨éƒ¨éƒ½æ˜¯æŽ¥å£çš„。这里笔者想说一下Java 如何对XML解析是Jdk应该考虑的事åQŒæ˜¯å®ƒçš„è´£ä“Q。而w3c¾l„织是维护定义XML标准的组¾l‡ï¼Œæ‰€ä»¥ä¸€ä¸ªXML¾l“构是怎么æ ïL(f¨¥ng)š„ç”±w3c说了(ji¨£n)½Ž—,它不兛_¿ƒ(j¨©) Java如何åŽÕd®žçŽŽÍ¼ŒäºŽæ˜¯ä¹Žè§„定了(ji¨£n)所有XML存储的结构应该遵循的规则åQŒè¿™ž®±æ˜¯org.w3c.dom里全部的接口目的所在。在½W”者看来,½Ž€å•理解接口的概念ž®±æ˜¯å®žçŽ°è€…å¿…™å»éµå®ˆçš„原则ã€?<br /> <br /> 整个XML对应的结构叫Document、子元素对应的叫做Element、还有节点相关的Node、NodeList、Text、Entityã€?CharacterData、CDATASection½{‰æŽ¥å£ï¼Œå®ƒä»¬éƒ½å¯ä»¥åœ¨XML的语法中间找到相对应的含义。由于这里不是讲解XML基本语法åQŒå°±ä¸å¤šä»‹ç»äº?ji¨£n)。如果大家感兴趣åQŒç¬”者也可以专门写一½‹‡å…³äºŽXML的语法规则帖与大家分享一下ã€?<br /> <br /> 2åQ?Java Swing <br /> Swing是一个让人又爱又恨的东西åQŒå¯çˆ×ƒ¹‹å¤„在于上手很å®ÒŽ(gu¨©)˜“åQŒè¾ƒAWT比è“v来Swing提供的界面功能更加强大,可恨之处在于¾~–复杂的界面工作量实在是巨大。笔者写˜q‡è¶…˜q?000行的Swing界面åQŒæ„Ÿè§‰ç”¨æˆ·ä½“验还不是那么优秀。最˜q‘又写过­‘…过6000行的åQŒç”±äºŽåŠŸèƒ½æ¨¡å—å¤šäº?ji¨£n),整体效果˜q˜åªæ˜¯ä¸€èˆ¬èˆ¬ã€‚体ä¼?x¨¬)最æ·Þqš„ž®×ƒ¸€ä¸ªå­—åQšç¯! 所以大家现在都陆箋不怎么用Swing在真正开发的™å¹ç›®ä¸Šäº†(ji¨£n)åQŒå¤ªå¤šç•Œé¢æŠ€æœ¯å¯ä»¥å–代它äº?ji¨£n)。笔者去写也是迫于无奈组里面大家都没写过åQŒæˆ‘不入地域谁入åQ?<br /> <br /> ž®½ç®¡Swing慢慢的在被äh忽略åQŒç‰¹åˆ«æ˜¯éšç€B/S慢慢的在æ·ÒŽ(gu¨©)²¡C/SåQŒç¬”者倒是很愿意站出来为Swingæ­£èín。每一™åÒŽ(gu¨©)Š€æœ¯çš„æŽŒæ¡¾lä¸æ˜¯äØ“(f¨´)äº?ji¨£n)流行时ž®šè·Ÿé£Žã€‚真正喜‹Æ¢Java的朋友们˜q˜æ˜¯åº”该好好体会(x¨¬)一下SwingåQŒç›¸ä¿¡åœ¨æ ¡çš„很多学生也很多在学习(f¨¤n)它。很可能从Jdk 1.1ã€?.2走过来的很多大学老师可能是最不熟æ‚(zh¨¨n)‰å®ƒçš„ã€?<br /> Swing提供äº?ji¨£n)一¾l„è½»¾l„äšg¾lŸç§°ä¸ºJComponentåQŒå®ƒä»¬ä¸ŽAWT¾l„äšg的最大区别是JComponent全部都是ContaineråQŒè€?Container的特ç‚ÒŽ(gu¨©)˜¯é‡Œé¢å¯ä»¥è£…蝲别的¾l„äšg。在Swing¾l„äšg中无论是JButton、JLabel、JPanel、JList½{‰éƒ½å¯ä»¥å†è£…å…¥ä“Q何其他组件。好处是½E‹åºå‘˜å¯ä»¥å¯¹Swing¾l„äšg实现“再开å?#8221;åQŒé’ˆå¯¹ç‰¹å®šéœ€æ±‚æž„å»ø™‡ªå·Þqš„æŒ‰é’®ã€æ ‡½{¾ã€ç”»æÑ€åˆ—表之¾cȝš„特定¾l„äšgã€?<br /> <br /> 有轻自然ž®±æœ‰é‡ï¼Œé‚£ä¹ˆè½È»„件和重组件区别是åQŸé‡¾l„äšg表现出来的åŞ态因操作¾pȝ»Ÿä¸åŒè€Œå¼‚åQŒè½»¾l„äšg是Swing自己提供GUIåQŒåœ¨è·¨åã^台的时候最大程度的保持一致ã€?<br /> 那么在编½E‹çš„æ—¶å€™è¦æ³¨æ„ä¸€äº›ä»€ä¹ˆå‘¢åQŸç¬”者谈谈自å·Þqš„几点¾léªŒåQ?<br /> <br /> a. 明确一个概念,只有Frame¾l„äšg才可以单独显½Cºçš„åQŒä¹Ÿè®¸æœ‰äºÞZ¼š(x¨¬)说JOptionPane里面的静(r¨´n)态方法就实现äº?ji¨£n)单独窗口出玎ͼŒä½†è¿½å¯ÀLºä»£ç ä¼?x¨¬)发现其实现实出来的Dialog也需要依托一个Frame½H—体åQŒå¦‚果没有指定就ä¼?x¨¬)默认äñ”生一个然后装载这个Dialog昄¡¤ºå‡ºæ¥ã€?<br /> <br /> b. JFrame是由˜q™ä¹ˆå‡ éƒ¨åˆ†ç»„成:(x¨¬) <br /> 最底下一层JRootPaneåQŒä¸Šé¢æ˜¯glassPane (一个JPanel)å’ŒlayeredPane (一个JLayeredPane)åQŒè€ŒlayeredPane又由contentPane(一个JPanel)å’ŒmenuBar构成。我们的¾l„äšg都是加在 contentPane上,而背景图片只能加在layeredPane上面ã€?至于glassPane是一个透明的覆盖了(ji¨£n)contentPane的一层,在特定效果中ž®†è¢«åˆ©ç”¨åˆ°æ¥è®°å½•鼠标坐标或掩饰组件ã€?<br /> <br /> c. ä¸ÞZº†(ji¨£n)增强用户体验åQŒæˆ‘们会(x¨¬)在一些按钮上æ·ÕdŠ å¿«æ·é”®ï¼Œä½†Swing里面通常只能识别键盘的Alt键,要加入其他的快捷键,必须自己实现一个ActionListenerã€?<br /> <br /> d. 通过setLayout(null)可以使得所有组件以setBounds()的四个参数来¾_„¡¡®å®šä½å„自的大ž®ã€ä½¾|®ï¼Œä½†ä¸æŽ¨èä½¿ç”¨åQŒå› ä¸ºå¥½çš„ç¼–½E‹é£Žæ ég¸åº”该在Swing代码中硬¾~–码具体数字åQŒæ‰€æœ‰çš„æ•°å­—应该以常数的形式¾lŸä¸€å­˜åœ¨ä¸€ä¸ªé™(r¨´n)态无实例资源¾cÀL–‡ä»¶ä¸­ã€‚这个静(r¨´n)态无实例¾cȝ»Ÿä¸€è´Ÿè´£Swing界面的风æ û|¼ŒåŒ…括字体和颜色都应该包括˜q›åŽ»ã€?<br /> <br /> e. 好的界面设计有一条Golden Rule: 用户不用ä»ÖM½•手册通过ž®‘æ•°ž®è¯•ž®Þpƒ½å­¦ä¼š(x¨¬)使用软äšg。所以尽量把按钮以菜单的形式åQˆä¸½Ž¡æ˜¯å³é”®èœå•˜q˜æ˜¯½H—体自带™å‰™ƒ¨èœå•åQ‰å‘ˆçŽ°ç»™™å‘Ö®¢åQŒé™¤éžæ˜¯é¢‘繁点击的按钮才有必要直接呈现在界面中ã€?<br /> <br /> 其实Swing的功能是相当强大的,只是现在应用不广泛,专门åŽÈ ”½I¶å¤§æ¦‚是要花不少旉™—´çš„。笔者在各网站论坛浏览关于Swing的技巧文章还是比较可信的åQŒè‡ªå·±æ‰€å­¦éžå¸¸æœ‰é™ï¼Œå„äh体会(x¨¬)对Swing各个¾l„äšg的掌握就是一个实è·ëЧ¯ç´¯çš„˜q‡ç¨‹ã€‚笔者只用到˜q‡ä»¥ä¸Šè¿™äº›ï¼Œæ‰€ä»¥åªèƒ½è°ˆè°ˆéƒ¨åˆ†æƒ³æ³•,˜q˜æœ›å¤§å®¶è§è°…åQ?<br /> Java杂谈åQˆå…­åQ?<br /> Java杂谈åQˆå…­åQ?<br /> <br /> <br /> ˜q™ç¯‡æ˜¯ç¬”者打½Ž—写的J2se部分的最后一½‹‡äº†(ji¨£n)åQŒè¿™½‹‡ç»“束之后,再写J2ee部分åQŒä¸çŸ¥é“是否˜q˜åˆé€‚写在这个版块?大家可以¾l™ç‚¹æ„è§åQŒè°¢è°¢å¤§å®¶å¯¹ž®å¼Ÿ˜q™ä¹ˆé¼“励一路写完前六篇Java杂谈的J2se部分。最后这½‹‡æ‰“½Ž—谈一谈Java中的RMI机制和JVM沙箱安全框架ã€?<br /> <br /> 1åQ?Java中的RMI机制 <br /> RMI的全¿U°æ˜¯˜qœç¨‹æ–ÒŽ(gu¨©)³•调用åQŒç›¸ä¿¡ä¸ž®‘朋友都听说˜q‡ï¼ŒåŸºæœ¬çš„æ€èµ\可以用一个经典比æ–ÒŽ(gu¨©)¥è§£é‡ŠåQšA计算机想要计½Ž—一个两个数的加法,但A自己做不äº?ji¨£n),于是叫另外一台计½Ž—机B帮忙åQŒB有计½Ž—加法的功能åQŒA调用它就像调用这个功能是自己的一æ äh–¹ä¾Ñ€‚这个就叫做˜qœç¨‹æ–ÒŽ(gu¨©)³•调用äº?ji¨£n)ã€?<br /> <br /> ˜qœç¨‹æ–ÒŽ(gu¨©)³•调用是EJB实现的支柱,建立分布式应用的核心(j¨©)思想。这个很好理解,再拿上面的计½Ž—加法例子,A只知道去call计算机B的方法,自己òq¶æ²¡æœ‰B的那些功能,所以A计算机端ž®±æ— æ³•看到B执行˜q™æ®µåŠŸèƒ½çš„è¿‡½E‹å’Œä»£ç åQŒå› ä¸ºçœ‹éƒ½çœ‹ä¸åˆ°åQŒæ‰€ä»¥æ—¢æ²¡æœ‰æœÞZ¼š(x¨¬)½Hƒå–也没有机ä¼?x¨¬)去改动æ–Ò?gu¨©)³•代码。EJB正式åŸÞZºŽ˜q™æ ·çš„æ€æƒ³æ¥å®Œæˆå®ƒçš„ä“Q务的。当½Ž€å•的加法变成复杂的数据库操作和电(sh¨´)子商务交易应用的时候,˜q™æ ·çš„安全性和分布式应用的便利性就表现出来优势äº?ji¨£n)ã€?<br /> <br /> 好了(ji¨£n)åQŒå›žåˆ°ç»†èŠ‚ä¸ŠåQŒè¦å¦‚何实现˜qœç¨‹æ–ÒŽ(gu¨©)³•调用呢?我希望大家学ä¹?f¨¤n)ä“Q何技术的时候可以试着依赖自己的下意识判断åQŒåªè¦ä½ çš„æƒ³æ³•是合理健壮的,那么很可能实际上它就是这么做的,毕竟真理都蕴藏在òq›_‡¡çš„生‹zȝ»†èŠ‚ä¸­ã€‚è¿™æ ·åªè¦å¸¦ç€ä¸€äº›è–„å¼Þqš„Java基础来思考RMIåQŒå…¶å®žä¹Ÿå¯ä»¥æƒ›_‡ºä¸ªå¤§æ¦‚来ã€?<br /> <br /> a) 需要有一个服务器角色åQŒå®ƒæ‹¥æœ‰çœŸæ­£çš„功能代码方法。例如BåQŒå®ƒæä¾›åŠ æ³•æœåŠ¡ <br /> b) 如果惌™¿œ½E‹ä‹É用B的功能,需要知道Bçš„IP地址 <br /> c) 如果惌™¿œ½E‹ä‹É用B的功能,˜q˜éœ€è¦çŸ¥é“B中那个特定服务的名字 <br /> <br /> 我们很自然可以想到这些,虽然不完善,但已¾lå¾ˆæŽ¥è¿‘正确的做法了(ji¨£n)。实际上RMI要得以实现还得意于Java一个很重要的特性,ž®±æ˜¯Java反射机制。我们需要知道服务的名字åQŒä½†åˆå¿…™å»éšè—å®žçŽ°çš„ä»£ç åQŒå¦‚何去做呢åQŸç­”案就是:(x¨¬)接口åQ?<br /> 举个例子åQ?<br /> public interface Person(){ <br /> public void sayHello(); <br /> } <br /> <br /> Public class PersonImplA implements Person{ <br /> public PersonImplA(){} <br /> <br /> public void sayHello(){ System.out.println(“Hello!”);} <br /> } <br /> <br /> Public class PersonImplB implements Person{ <br /> public PersonImplB(){} <br /> <br /> public void sayHello(){ System.out.println(“Nice to meet you!”);} <br /> } <br /> <br /> 客户端:(x¨¬)Person p = Naming.lookup(“PersonService”); <br /> p.sayHello(); <br /> <br /> ž®Þp¿™å‡ æ®µä»£ç ž®±åŒ…含了(ji¨£n)å‡ ä¹Žæ‰€æœ‰çš„å®žçŽ°æŠ€æœ¯ï¼Œå¤§å®¶ç›æ€¿¡ä¹ˆï¼Ÿå®¢æˆ·ç«¯è¯·æ±‚一个say hello服务åQŒæœåС噍˜qè¡Œæ—¶æŽ¥åˆ°è¿™ä¸ªè¯·æ±‚,利用Java反射机制的Class.newInstance()˜q”回一个对象,但客æˆïL(f¨¥ng)«¯ä¸çŸ¥é“服务器˜q”回的是 ImplA˜q˜æ˜¯ImplBåQŒå®ƒæŽ¥å—用的参数½{‘֐æ˜¯PersonåQŒå®ƒçŸ¥é“实现äº?ji¨£n)Person接口的对象一定有sayHello()æ–ÒŽ(gu¨©)³•åQŒè¿™ž®±æ„å‘³ç€å®¢æˆ·ç«¯åƈ不知道服务器真正如何åŽÕd®žçŽ°çš„åQŒä½†å®ƒé€šè¿‡äº?ji¨£n)è§£Person接口明确äº?ji¨£n)它要用的服务方法名字叫做sayHello()ã€?<br /> <br /> 如此¾cÀLލåQŒæœåŠ¡å™¨åªéœ€è¦æš´éœ²è‡ªå·Þqš„æŽ¥å£å‡ºæ¥ä¾›å®¢æˆïL(f¨¥ng)«¯åQŒæ‰€æœ‰å®¢æˆïL(f¨¥ng)«¯ž®±å¯ä»¥è‡ªå·±é€‰æ‹©éœ€è¦çš„æœåŠ¡ã€‚è¿™ž®±åƒ˜¡é¦†åªè¦æ‹¿å‡ºè‡ªå·±çš„菜单出来让客户选择åQŒå°±å¯ä»¥åœ¨åŽå°åŽ¨æˆ¿ä¸€é“é“çš„æŒ‰éœ€åšå‡ºæ¥ï¼Œå®ƒæ€Žä¹ˆåšçš„é€šå¸¸æ˜¯ä¸è®©å®¢æˆïL(f¨¥ng)Ÿ¥é“çš„åQï¼ˆ¼œ–传菜谱吧,^_^åQ?<br /> <br /> 最后一ç‚ÒŽ(gu¨©)˜¯æˆ‘调用lookupåQŒæŸ¥æ‰¾ä¸€ä¸ªå«PersonService名字的对象,服务器只要看到这个名字,在自å·Þqš„目录åQˆç›¸å½“于ç”?sh¨´)话½¿ï¼?j¨ª)中找到对应的对象名字提供服务ž®±å¯ä»¥äº†(ji¨£n)åQŒè¿™ä¸ªç›®å½•就叫做JNDI (Java命名与目录接口)(j¨ª)åQŒç›¸ä¿¡å¤§å®¶ä¹Ÿå¬è¿‡çš„ã€?<br /> <br /> 有兴­‘£çš„æœ‹å‹ä¸å¦¨è‡ªå·±åšä¸ªRMI的应用,很多前辈的博客中有简单的例子。提½CÞZ¸€ä¸‹åˆ©ç”¨Jdkçš„bin目录中rmi.exeå’?rmiregistry.exe两个命ä×o(h¨´)ž®±å¯ä»¥è‡ªå·±å¾èµ·ä¸€ä¸ªæœåС噍åQŒæä¾›è¿œ½E‹æœåŠ¡ã€‚å› ä¸ÞZ¾‹å­å¾ˆå®ÒŽ(gu¨©)˜“找,我就不自å·×ƒ‹D例子äº?ji¨£n)ï¼?<br /> <br /> 2åQ?JVM沙箱&框架 <br /> RMI¾|—唆得太多了(ji¨£n)åQŒå®žåœ¨æ˜¯ž®½åŠ›æƒÏxŠŠå®ƒè¯´æ¸…æ¥šåQŒå¸Œæœ›å¯¹å¤§å®¶æœ‰å¸®åŠ©ã€‚æœ€åŽçš„æœ€åŽï¼Œ¾l™å¤§å®¶ç®€å•讲一下JVM框架åQŒæˆ‘们叫做Java沙箱。Java沙箱的基本组件如下:(x¨¬) <br /> a) ¾c»è£…载器¾l“æž„ <br /> b) classæ–‡äšg‹‚€(g¨¨)验器 <br /> c) 内置于Java虚拟机的安全ç‰ÒŽ(gu¨©)€?<br /> d) 安全½Ž¡ç†å™¨åŠ(qi¨¢ng)Java API <br /> <br /> 其中¾c»è£…载器åœ?个方面对Java沙箱起作用:(x¨¬) <br /> a. 它防止恶意代码去òq²æ¶‰å–„意的代ç ?<br /> b. 它守护了(ji¨£n)被信ä»Èš„¾cÕdº“边界 <br /> c. 它将代码归入保护域,¼‹®å®šäº?ji¨£n)代码可以进行哪些操ä?<br /> <br /> 虚拟æœÞZØ“(f¨´)不同的类加蝲器蝲入的¾cÀLä¾›ä¸åŒçš„命名½Iºé—´åQŒå‘½åç©ºé—´ç”±ä¸€¾pÕdˆ—唯一的名¿U°ç»„成,每一个被装蝲的类ž®†æœ‰ä¸€ä¸ªåå­—,˜q™ä¸ªå‘½å½Iºé—´æ˜¯ç”±Java虚拟æœÞZØ“(f¨´)每一个类装蝲器维护的åQŒå®ƒä»¬äº’ç›æ€¹‹é—´ç”šè‡³ä¸å¯è§ã€?<br /> <br /> 我们常说的包åQˆpackageåQ‰æ˜¯åœ¨Java虚拟机第2版的规范½W¬ä¸€‹Æ¡å‡ºçŽŽÍ¼Œæ­£ç¡®å®šä¹‰æ˜¯ç”±åŒä¸€ä¸ªç±»è£…蝲器装载的、属于同一个包、多个类型的集合。类装蝲器采用的机制是双亲委‹z¾æ¨¡å¼ã€‚具体的加蝲器框架我在Java杂谈åQˆä¸€åQ‰ä¸­å·²ç»è§£é‡Š˜q‡äº†(ji¨£n)åQŒå½“时说最外层的加载器是AppClassLoaderåQŒå…¶å®žç®—上网¾lœå±‚的话AppClassLoader也可以作为parentåQŒè¿˜æœ‰æ›´å¤–层的加载器URLClassLoaderã€‚äØ“(f¨´)äº?ji¨£n)防止恶意攻å‡È”±URL加蝲˜q›æ¥çš„类文äšg我们当然需要分不同的访问命名空é—ß_(d¨¢)¼Œòq¶ä¸”制定最安全的加载次序,½Ž€å•来说就是两点:(x¨¬) <br /> <br /> a. 从最内层JVM自带¾cÕdŠ è½½å™¨å¼€å§‹åŠ è½½ï¼Œå¤–å±‚æ¶æ„åŒå¾cÕd¾—不到先加载而无法ä‹Éç”?<br /> b. ç”׃ºŽä¸¥æ ¼é€šè¿‡åŒ…来区分äº?ji¨£n)访问域åQŒå¤–层恶意的¾c»é€šè¿‡å†…置代码也无法获得权限访问到内层¾c»ï¼Œç ´åä»£ç ž®Þp‡ªç„¶æ— æ³•生效ã€?<br /> <br /> 附:(x¨¬)关于Javaçš„åã^台无å…Ïx€§ï¼Œæœ‰ä¸€ä¸ªä¾‹å­å¯ä»¥å¾ˆæ˜Žæ˜¾çš„说明这个特性:(x¨¬) <br /> 一般来è¯ß_(d¨¢)¼ŒC或C++中的int占位宽度是根据目标åã^台的字长来决定的åQŒè¿™ž®±æ„å‘³ç€é’ˆå¯¹ä¸åŒçš„åã^台编译同一个C++½E‹åºåœ¨è¿è¡Œæ—¶ä¼?x¨¬)有不同的行为。然而对äº?Java中的int都是32位的二进制补码标识的有符åäh•´æ•ŽÍ¼Œè€Œfloat都是遵守IEEE 754‹¹®ç‚¹æ ‡å‡†çš?2位æÕQç‚ÒŽ(gu¨©)•°ã€?<br /> <br /> PS: ˜q™ä¸ªž®å¼Ÿæœ€˜q‘也没时间ç‘ô¾l­ç ”½I¶ä¸‹åŽÖMº†(ji¨£n)åQŒåªæ˜¯æƒ³æŠ›ç –引玉的提供给大家一个初步认识JVM的印象。有æœÞZ¼š(x¨¬)äº?ji¨£n)解一下JVM的内部结构对今后做Java开发是很有好处的ã€?<br /> Java杂谈åQˆä¸ƒåQ‰ï¼åQæŽ¥å?amp; ¾l„äšg、容å™?<br /> Java杂谈åQˆä¸ƒåQ‰ï¼åQæŽ¥å?amp; ¾l„äšg、容å™?<br /> <br /> ¾lˆäºŽåˆé™(r¨´n)下来¾l§ç®‹å†™è¿™ä¸ªä¸»é¢˜çš„¾l­ç¯‡åQŒå‰å…­ç¯‡ä¸»è¦è®²äº†(ji¨£n)一些J2seæ–šw¢çš„经验和感受åQ?çœég¸‹Java应用范围已经被J2ee占据äº?ji¨£n)相当大的一块领域,有些人甚臛_£°¿U°Java被J2ee所取代äº?ji¨£n)。不知道大家如何来理解所谓的J2ee (Java2 Enterprise Edition)åQŒä¹Ÿž®±æ˜¯Java企业¾U§åº”用? <br /> <br /> ½W”者的观点是,技术的发展是顺应世界变化的­‘‹åŠ¿çš„ï¼Œä»ŽC/S˜q‡æ¸¡åˆ°B/S模式åQŒä»Žå®¢æˆ·ç«¯çš„角度考虑企业¾U§åº”用或者说ç”?sh¨´)子商务领域不在兛_¿ƒ(j¨©)客户端维护问题,˜q™ä¸ªä»ÕdŠ¡å·²ç»äº¤ç»™äº?ji¨£n)ä“Q何一台PC都会(x¨¬)有的‹¹è§ˆå™¨åŽ»¾l´æŠ¤åQ›ä»ŽæœåŠ¡å™¨ç«¯çš„è§’åº¦è€ƒè™‘åQŒä»¥å¾€C/S中的TCP/IP协议实现载体ServerSocket被Web Server Container所取代åQŒä¾‹å¦‚大安™ƒ½å¾ˆç†Ÿæ‚(zh¨¨n)‰çš„Tomcat、JBoss、WebLogic½{‰ç­‰ã€‚æ€ÖM¹‹ä¸€åˆ‡çš„转变都是ä¸ÞZº†(ji¨£n)使得JavaæŠ€æœ¯èƒ½æ›´å¥½çš„äØ“(f¨´)人类生äñ”生活所服务ã€?<br /> <br /> 有ähä¼?x¨¬)é—®åQŒç›´æŽ¥å޻学J2eeè·Œ™¿‡J2se行否åQŸç¬”者是肯定不赞成的åQŒå®žé™…上¼‹®å®žæœ‰äh走这条èµ\åQŒä½†½W”者自íw«ä½“ä¼?x¨¬)是正是ç”׃ºŽJ2se的基¼‹€å¾ˆç‰¢å›ºï¼Œæ‰ä¼š(x¨¬)坯D‡´åœ¨J2ee学习(f¨¤n)的道路上™åºé£Ž™åºæ°´åQŒçŸ¥è¯†ç‚¹ä¸Šä¸ä¼?x¨¬)有什么迷惑的地方。ä‹D个简单的例子吧:(x¨¬) <br /> <br /> ½W”者曾¾lè·Ÿå¤§å­¦åŒå­¦è®¨è®ºä¸‹é¢˜q™ä¸¤¿Uå†™æ³•的区别åQ?<br /> ArrayList list = new ArrayList(); //½W”者不说反对,但至ž®‘不赞成 <br /> List list = new ArrayList(); //½W”者支æŒ?<br /> 曄¡»½W”者跟同学争论äº?ji¨£n)几个小æ—Óž¼Œä»–非说第一¿Uå†™æ³•æ›´¿U‘å­¦åQŒç¬¬äºŒç§å®Œå…¨æ²¡æœ‰å¿…è¦ã€‚æˆ‘æ— æ³•å®Œå…¨è¯´æœä»–ï¼Œä½†ç¬”è€…è®¤ä¸ø™‰¯å¥½çš„ä¹?f¨¤n)惯和意识是ä»ÖM½•时候都应该针对接口¾~–程åQŒä»¥è¾‘Öˆ°è§£è€¦åˆå’Œå¯æ‰©å±•性的目的。下面就以接口开始进入J2ee的世界吧åQ?<br /> <br /> 1. J2ee与接å?<br /> <br /> 每一个版本的J2ee都对应着一个确定版本的JDKåQŒJ2ee1.4对应Jdk1.4åQŒçŽ°åœ¨æ¯”è¾ƒæ–°çš„æ˜¯JDK5.0åQŒè‡ªç„¶ä¹Ÿä¼?x¨¬)有J2EE 5.0。其实笔者一直在用的是J2EE1.4åQŒä¸˜q‡æ²¡ä»€ä¹ˆå…³¾p»ï¼Œå¤§å®¶å¯ä»¥ä¸‹ä“Q何一个版本的J2ee api来稍微浏览一下。笔者想先声明一个概念,J2ee也是源自JavaåQŒæ‰€ä»¥åº•层的操作依然调用到很多J2se的库åQŒæ‰€ä»¥æ‰å»ø™®®å¤§å®¶å…ˆç‰¢ç‰¢æŽŒæ¡J2se 的主‹¹æŠ€æœ¯ã€?<br /> <br /> J2ee api有一个特点,大家比较熟æ?zh¨¨n)‰çš„几个包java.jms、javax.servlet.http、javax.ejb½{‰éƒ½ä»¥interface居多åQŒå®žçŽ°ç±»è¾ƒå°‘ã€‚å…¶å®žå¤§å®¶çœŸæ­£åœ¨ç”¨çš„æ—¶å€™ç™¾åˆ†ä¹‹å…­åä»¥ä¸Šéƒ½åœ¨åå¤çš„æŸ¥ç€javax.servlet.http˜q™ä¸ªåŒ…下面几个实现类的api函数åQŒå…¶ä»–的包很ž®‘é—®‹z¥ã€‚笔者徏议在学习(f¨¤n)一¿UæŠ€æœ¯ä¹‹å‰ï¼Œå¯ÒŽ(gu¨©)•´ä½“的框架有一个了(ji¨£n)解是很有必要的,J2ee旨在通过interface的声明来规范实现的行为,ä»ÖM½•½W¬ä¸‰æ–¹çš„厂商惌™¦æä¾›è‡ªå·±å“ç‰Œçš„实现前提也是遵循这些接口定义的规则。如果在从前J2se学习(f¨¤n)的道路上å¯ÒŽ(gu¨©)Ž¥å£çš„ç†è§£å¾ˆå¥½çš„è¯åQŒè¿™é‡Œçš„体会(x¨¬)ž®†æ˜¯éžå¸¸æ·±åˆ»çš„,举个½Ž€å•的例子åQ?<br /> <br /> public interface Mp3{ <br /> public void play(); <br /> public void record(); <br /> public void stop(); <br /> } <br /> <br /> 如果我定义这个简单的接口åQŒå‘布出去,规定ä»ÖM½•½W¬ä¸‰æ–¹çš„公司æƒÏxލå‡?gu¨®)™‡ªå·Þqš„名字为Mp3çš„äñ”品都必须实现˜q™ä¸ªæŽ¥å£åQŒä¹Ÿž®±æ˜¯è‡›_°‘提供接口中方法的具体实现。这个意义已¾lè¿œ˜qœä¸æ­¢æ˜¯é¢å‘对象的多态了(ji¨£n)åQŒåªæœ‰åŽ‚å•†éµå¾ªJ2ee的接口定义,世界上的J2ee½E‹åºå‘˜æ‰èƒ½é’ˆå¯¹ç»Ÿä¸€çš„æŽ¥å£è¿›è¡Œç¨‹åºè®¾è®¡ï¼Œæœ€¾lˆä¸ç”¨æ”¹å˜ä»£ç åªæ˜¯å› ä¸ÞZ‹É用了(ji¨£n)不同厂商的实现类而有不同的特性çÅžäº?ji¨£n),本质上说åQŒæ— è®ºå“ªä¸€¿UåŽ‚å•†å®žçŽ°éƒ½å®Œæˆäº?ji¨£n)职责范围内的工作。这个就是笔者想一直强调的åQŒé’ˆå¯ÒŽ(gu¨©)Ž¥å£ç¼–½E‹çš„æ€æƒ³ã€?<br /> <br /> 接口到底有什么好处呢åQŸæˆ‘们这栯‚®¾æƒ»I¼ŒçŽ°åœ¨æœ‰AppleMp3、SonyMp3、SamsungMp3都实çŽîCº†(ji¨£n)˜q™ä¸ªMp3的接口,于是都有äº?ji¨£n)playã€?record、stop˜q™ä¸‰ä¸ªåŠŸèƒ½ã€‚æˆ‘ä»¬å°†Mp3产品座位一个组件的时候就不需要知道它的具体实玎ͼŒåªè¦çœ‹åˆ°æŽ¥å£å®šä¹‰çŸ¥é“˜q™ä¸ªå¯¹è±¡æœ?个功能就可以使用äº?ji¨£n)。那么类ä¼ég¸‹é¢è¿™æ ïL(f¨¥ng)š„业务ž®±å®Œå…¨å¯ä»¥åœ¨ä»ÖM½•æ—‰™—´ä»?个品牌扩展到ä»ÀL„ä¸ªå“ç‰Œï¼Œå¼€ä¸ªçŽ©½W‘çš„è¯ß_(d¨¢)¼Œ™å¹ç›®¾lç†é«˜é«˜åœ¨ä¸Šçš„写å®?0个接口里的方法声明,然后ž®×ƒ¸¢¾l™æ‰‹ä¸‹çš„½E‹åºå‘˜åŽ»å†™é‡Œé¢çš„¾l†èŠ‚åQŒç”±äºŽæŽ¥å£å·²¾lç»Ÿä¸€åQˆå³æ¯ä¸ªæ–ÒŽ(gu¨©)³•传入和传出的格式已经¾lŸä¸€åQ‰ï¼Œ¾lç†åªéœ€å…Ïx³¨å…¨å±€çš„业务就可以天天端杯咖啡走来走去äº?ji¨£n),^_^åQ?<br /> public Mp3 create(); <br /> public void copy(Mp3 mp3); <br /> public Mp3 getMp3(); <br /> <br /> 最后用一个简单的例子说明接口åQšä¸€ä¸?åïL(f¨¥ng)”µ(sh¨´)池的手电(sh¨´)½{’,可以装入ä»ÖM½•牌子çš?åïL(f¨¥ng)”µ(sh¨´)池,只要它符å?åïL(f¨¥ng)”µ(sh¨´)池的规范åQŒè£…入之后ä“Q何看不到是什么牌子,只能感受到手ç”늭’在完成它的功能。那么生产手ç”늭’的厂商和生äñ”5åïL(f¨¥ng)”µ(sh¨´)池的厂商ž®±å¯ä»¥å®Œå…¨è§£é™¤ä¾èµ–å…³¾p»ï¼Œå¯ä»¥å„自自由开发自å·Þqš„产品åQŒå› ä¸ºå®ƒä»¬éƒ½éµå®ˆ5åïL(f¨¥ng)”µ(sh¨´)池应有的形状、正负极位置½{‰çº¦å®šã€‚这下大家能å¯ÒŽ(gu¨©)Ž¥å£å¤šä¸€ç‚¹ä½“ä¼?x¨¬)äº?ji¨£n)么? <br /> <br /> 2. ¾l„äšg和容å™?<br /> 针对接口是笔者特意强调的J2ee学习(f¨¤n)之èµ\必备的思想åQŒå¦å¤–一个就是比较常规的¾l„äšg和容器的概念äº?ji¨£n)。很多教材和专业¾|‘站都说J2EE的核å¿?j¨©)是一¾l„规范与指南åQŒå¼ºè°ƒJ2ee的核å¿?j¨©)概念就是组ä?容器åQŒè¿™¼‹®å®žæ˜¯æ— å¯åŽšéžçš„ã€‚éšç€­‘Šæ¥­‘Šå¤šçš„J2ee框架出现åQŒç›¸åº”的每种框架都一般有与之对应的容器ã€?<br /> <br /> 容器åQŒæ˜¯ç”¨æ¥½Ž¡ç†¾l„äšgè¡ŒäØ“(f¨´)çš„ä¸€ä¸ªé›†åˆå·¥å…øP¼Œ¾l„äšg的行为包括与外部环境的交互、组件的生命周期、组件之间的合作依赖关系½{‰ç­‰ã€‚J2ee包含的容器种¾cÕd¤§¾U¦æœ‰ Web容器、Application Client容器、EJB容器、Applet客户端容器等。但在笔者看来,现在容器的概念变得有ç‚ÒŽ(gu¨©)¨¡¾pŠäº†(ji¨£n)åQŒå¤§å®¶è€³ç†Ÿèƒ½è¯¦æ˜¯é‚£äº›åŠŸèƒ½å¼ºå¤§çš„å¼€æºæ¡†æžÓž¼Œæ¯”如 Hibernate、Struts2、Spring、JSF½{‰ï¼Œå…¶ä¸­Hibernatež®±åŸºäºŽJDBC的基¼‹€ž®è£…äº?ji¨£n)对事务和ä¼?x¨¬)话的½Ž¡ç†åQŒå¤§å¤§æ–¹ä¾¿äº†(ji¨£n)å¯ÒŽ(gu¨©)•°æ®åº“操作的繁琐代码,从这个意义上来说它已¾læŽ¥˜q‘容器的概念äº?ji¨£n),EJB的实体Bean也逐渐被以Hibernateä¸ÞZ»£è¡¨çš„æŒä¹…化框架所取代ã€?<br /> <br /> ¾l„äšgåQŒæœ¬æ„æ˜¯æŒ‡å¯ä»¥é‡ç”¨çš„代码单元åQŒä¸€èˆ¬ä»£è¡¨ç€ä¸€ä¸ªæˆ–者一¾l„可以独立出来的功能模块åQŒåœ¨J2ee中组件的¿Uç±»æœ‰å¾ˆå¤šç§åQŒæ¯”较常见的是EJB¾l„äšg、DAO¾l„äšg、客æˆïL(f¨¥ng)«¯¾l„äšg或者应用程序组件等åQŒå®ƒä»¬æœ‰ä¸ªå…±åŒç‰¹ç‚ÒŽ(gu¨©)˜¯åˆ†åˆ«ä¼?x¨¬)打包æˆ?waråQ?jaråQ?jaråQ?earåQŒæ¯ä¸ªç»„件由特定格式的xml描述½W¦æ–‡ä»¶è¿›è¡Œæ˜qŽÍ¼Œè€Œä¸”服务器端的组仉™ƒ½éœ€è¦è¢«éƒ¨çÖv到应用服务器上面才能够被使用ã€?<br /> <br /> ½Eå¾®ç†è§£å®Œç»„件和容器åQŒè¿˜æœ‰ä¸€ä¸ªé‡è¦çš„æ¦‚念ž®±æ˜¯åˆ†å±‚模型åQŒæœ€è‘—名的当然是MVC三层模型。在一个大的工½E‹æˆ–™å¹ç›®ä¸­ï¼Œä¸ÞZº†(ji¨£n)让前台和后台各个模块的编½E‹äh员能够同时进行工作提高开发效率,最重要的就是实现层与层之间的耦合关系åQŒè®¸å¤šåˆ†å±‚模型的宗旨和开源框架所˜q½æ±‚的也ž®±æ˜¯˜q™æ ·çš„æ•ˆæžœã€‚在½W”者看来,一个完整的 Web™å¹ç›®å¤§æ¦‚有以下几个层‹Æ¡ï¼š(x¨¬) <br /> <br /> a) 表示层(Jsp、Html、Javascript、Ajax、Flash½{‰ç­‰æŠ€æœ¯å¯¹å…¶æ”¯æŒï¼‰(j¨ª) <br /> b) 控制层(Struts、JSF、WebWork½{‰ç­‰æ¡†æž¶åœ¨åŸºäºŽServlet的基¼‹€ä¸Šæ”¯æŒï¼Œè´Ÿè´£æŠŠå…·ä½“çš„è¯äh±‚数据åQˆæœ‰æ—¶å¸è½½é‡æ–°è£…载)(j¨ª)导向适合处理它的模型层对象)(j¨ª) <br /> c) 模型层(½W”者认为目前最好的框架是SpringåQŒå®žè´¨å°±æ˜¯å¤„理表½Cºå±‚¾lç”±æŽ§åˆ¶å±‚è{发过来的数据åQŒåŒ…含着大量的业务逻辑åQ?<br /> d) 数据层(Hibernate、JDBC、EJB½{‰ï¼Œç”±æ¨¡åž‹å±‚处理完了(ji¨£n)持久化到数据库中åQ?<br /> <br /> 当然åQŒè¿™ä»…仅是笔者个人的观点åQŒä»…仅是供大家学ä¹?f¨¤n)做一个参考,如果要实现这些层之间的完全分¼›»ï¼Œé‚£ä¹ˆä¸€ä¸ªå¤§çš„å·¥½E‹ï¼Œå¯ä»¥ä»…仅通过增加人手ž®±æ¥å®Œæˆä»ÕdŠ¡ã€‚è™½ç„¶ã€Šäh月神话》中已经很明¼‹®çš„阐述äº?ji¨£n)增加ähæ‰‹åÆˆä¸èƒ½æ˜¯æ•ˆçŽ‡å¢žåŠ ï¼Œå¾ˆå¤§½E‹åº¦ä¸Šæ˜¯å› äØ“(f¨´)彼此做的工作有顺序上的依赖关¾pÀLˆ–者说隑ֺ¦å’Œå·¥ä½œé‡ä¸Šçš„巨大差距。当然理想状态在真实世界中是不可能达到的åQŒä½†æˆ‘们永远应该朝着˜q™ä¸ªæ–¹å‘åŽÖM¸æ–­åŠªåŠ›ã€‚æœ€å¼€å§‹æ‰€æå€¡çš„é’ˆå¯¹æŽ¥å£æ¥ç¼–½E‹ï¼Œå“ªæ€•是ž®å°çš„细节,写一条List list= = new ArrayList()语句也能体现着处处皆ä‹É用接口的思想在里面。AnywayåQŒè¿™åªæ˜¯ä¸ªå¼€½‹‡ï¼Œ½W”者会(x¨¬)ž®Þp‡ªå·Þq”¨˜q‡çš„J2ee技术和框架再细化谈一些经éª?<br /> Java杂谈åQˆå…«åQ‰ï¼åQServlet/Jsp <br /> ¾lˆäºŽæ­£å¼˜q›å…¥J2ee的细节部分了(ji¨£n)åQŒé¦–当其冲的当然是Servletå’ŒJspäº?ji¨£n),上篇曄¡»æåˆ°˜q‡J2ee只是一个规范和指南åQŒå®šä¹‰äº†(ji¨£n)一¾l„å¿…™å»è¦éµåó@的接口,核心(j¨©)概念是组件和容器。曾¾læœ‰çš„äh问笔者Servletçš„Classæ–‡äšg是哪里来的?他认为是J2ee官方提供的,我ä‹Däº?ji¨£n)一个简单的反例åQšç¨å¾®æ£€æŸ¥äº†(ji¨£n)一下Tomcat5.0里面的Servlet.jaræ–‡äšgå’ŒJBoss里面的Servlet.jaræ–‡äšg大小åQŒå¾ˆæ˜Žæ˜¾æ˜¯ä¸ä¸€æ ïL(f¨¥ng)š„åQŒè‡³ž®‘å·²¾lè¯´æ˜Žäº†(ji¨£n)它们不是源自同根的吧。其实Servlet是由容器æ ÒŽ(gu¨©)®J2ee的接口定义自己来实现的,实现的方式当然可以不同,只要都遵守J2ee规范和指南ã€?<br /> <br /> 上述只是一个常见的误区¾|¢äº†(ji¨£n)åQŒå‘Šè¯‰æˆ‘们要¾~–译˜qè¡ŒServletåQŒæ˜¯è¦ä¾èµ–于实现它的容器的,不然˜qžjaræ–‡äšg都没有,¾~–译都无法进行。那么Jsp呢? Java Server Page的简¿UŽÍ¼Œæ˜¯äØ“(f¨´)äº?ji¨£n)开发动态网™åµè€Œè¯žç”Ÿçš„æŠ€æœ¯ï¼Œå…¶æœ¬è´¨ä¹Ÿæ˜¯JspåQŒåœ¨¾~–写完毕之后ä¼?x¨¬)在容器启动时经˜q‡ç¼–译成对应的Servlet。只是我们利用Jsp 的很多新ç‰ÒŽ(gu¨©)€§ï¼Œå¯ä»¥æ›´åŠ ä¸“æ³¨äºŽå‰åŽå°çš„åˆ†¼›»ï¼Œæ—©æœŸJsp做前台是满流行的åQŒæ¯•竟里面支持Html代码åQŒè¿™è®©å‰å°ç¾Žå·¥äh员可以更有效率的åŽÕd®Œæˆè‡ªå·Þqš„工作。然后Jspž®†è¯·æ±‚è{发到后台的ServletåQŒç”±Servlet处理业务逻辑åQŒå†è½¬å‘回另外一个Jsp在前台显½Cºå‡ºæ¥ã€‚è¿™ä¼ég¹Žå·²ç»æˆäØ“(f¨´)一¿Uå¸¸ç”¨çš„æ¨¡å¼åQŒæœ€åˆç¬”者学ä¹?f¨¤n)J2ee的时候,大量旉™—´ä¹Ÿåœ¨¾~–写˜q™æ ·çš„代码ã€?<br /> <br /> ž®½ç®¡çŽ°åœ¨åšå‰å°çš„æŠ€æœ¯è¶Šæ¥è¶Šå¤šï¼Œä¾‹å¦‚Flash、Ajax½{‰ï¼Œå·²ç»æœ‰å¾ˆå¤šähä¸å†è®¤äØ“(f¨´)Jsp重要äº?ji¨£n)。笔者觉得Jsp带来的不仅仅是前后端分离的设计理念,它的另外一™åÒŽ(gu¨©)Š€æœ¯æˆž®×ƒº†(ji¨£n)我们今天用的很多框架åQŒé‚£ž®±æ˜¯Tag标签技术。所以与其说是在学习(f¨¤n)JspåQŒä¸å¦‚更清醒的告诉自己在不断的理解Tag标签的意义和本质ã€?<br /> <br /> 1åQ?Servlet以及(qi¨¢ng)Jsp的生命周æœ?<br /> Servlet是Jsp的实质,ž®½ç®¡å®¹å™¨å¯¹å®ƒä»¬çš„处理有所区别。Servlet有init()æ–ÒŽ(gu¨©)³•初始化,service()æ–ÒŽ(gu¨©)³•˜q›è¡ŒW(xu¨¦)eb服务åQ?destroy()æ–ÒŽ(gu¨©)³•˜q›è¡Œé”€æ¯ï¼Œä»Žç”Ÿåˆ°ç­éƒ½ç”±å®¹å™¨æ¥æŽŒæ¡ï¼Œæ‰€ä»¥è¿™äº›æ–¹æ³•除非你惌™‡ªå·±æ¥å®žçްServletåQŒå¦åˆ™æ˜¯å¾ˆå°‘ä¼?x¨¬)接触到的。正是由于很ž®‘接触,才容易被òq¿å¤§åˆå­¦è€…所忽略åQŒå¸Œæœ›å¤§å®¶è‡³ž®‘记住Servlet生命周期æ–ÒŽ(gu¨©)³•都是回调æ–ÒŽ(gu¨©)³•。回调这个概å¿ëŠ®€å•来说就是把自己注入另外一个类中,由它来调用你的方法,所谓的另外一个类ž®±æ˜¯Web容器åQŒå®ƒåªè®¤è¯†æŽ¥å£å’ŒæŽ¥å£çš„æ–¹æ³•,注入˜q›æ¥çš„æ˜¯æ€Žæ ·çš„对象不½Ž¡ï¼Œå®ƒåªä¼?x¨¬)根据所需调用˜q™ä¸ªå¯¹è±¡åœ¨æŽ¥å£å®šä¹‰å­˜åœ¨çš„那些æ–ÒŽ(gu¨©)³•。由容器来调用的Servlet对象的初始化、服务和销毁方法,所以叫做回调。这个概念对学习(f¨¤n)å…¶ä»–J2ee技术相当关键! <br /> <br /> 那么Jsp呢?本事上是ServletåQŒè¿˜æ˜¯æœ‰äº›åŒºåˆ«çš„åQŒå®ƒçš„生命周期是˜q™æ ·çš„:(x¨¬) <br /> a) 一个客æˆïL(f¨¥ng)«¯çš„Request到达服务å™?-> <br /> b) 判断是否½W¬ä¸€‹Æ¡è°ƒç”?-> 是的话编译Jsp成Servlet <br /> c) 否的话再判断此Jsp是否有改å?-> 是的话也重新¾~–译Jsp成Servlet <br /> d) 已经¾~–译最˜q‘版本的Servlet装蝲所需的其他Class <br /> e) 发布ServletåQŒå³è°ƒç”¨å®ƒçš„Service()æ–ÒŽ(gu¨©)³• <br /> <br /> 所以JspåïL(f¨¥ng)§°çš„æ˜¯½W¬ä¸€‹Æ¡Load¾~“æ…¢åQŒä»¥åŽéƒ½ä¼?x¨¬)很快的˜qè¡Œã€‚从它的生命的周期确实不隄¡œ‹å‡ºæ¥˜q™ä¸ªç‰¹ç‚¹åQŒå®¢æˆïL(f¨¥ng)«¯çš„æ“ä½œå¾ˆž®‘会(x¨¬)改变Jsp的源码,所以它不需要编译第二次ž®×ƒ¸€ç›´å¯ä»¥äØ“(f¨´)客户端提供服务。这里稍微解释一下Httpçš„æ— çŠ¶æ€æ€§ï¼Œå› äØ“(f¨´)å‘çŽ°å¾ˆå¤šäºø™¯¯è§£ï¼ŒHttp的无状态性是指每‹Æ¡ä¸€å¼ é¡µé¢æ˜¾½Cºå‡ºæ¥äº†(ji¨£n)åQŒä¸ŽæœåŠ¡å™¨çš„˜qžæŽ¥å…¶å®žž®±å·²¾læ–­å¼€äº?ji¨£n),当再‹Æ¡æœ‰æäº¤åŠ¨ä½œçš„æ—¶å€™ï¼Œæ‰ä¼š(x¨¬)再次与服务器˜q›è¡Œ˜qžæŽ¥è¯äh±‚提供服务。当然还有现在比较流行的是Ajax与服务器异步通过 xml交互的技术,在做前台的领域潜力巨大,½W”者不是Ajax的高手,˜q™é‡Œæ— æ³•为大家解释ã€?<br /> <br /> 2åQ?Tag标签的本è´?<br /> ½W”者之前说äº?ji¨£n),Jsp本èín初衷是ä‹Éå¾—Web应用前后台的开发可以脱¼›»è€¦åˆåˆ†å¼€æœ‰æ•ˆçš„进行,可惜˜q™ä¸ªç†å¿µçš„èµA(ch¨³)献反倒不如它带来的Tag技术对J2eeçš„èµA(ch¨³)献要大。也许已¾læœ‰å¾ˆå¤šäººå¼€å§‹ä‹É用Tag技术了(ji¨£n)å´åÆˆä¸äº†(ji¨£n)è§£å®ƒã€‚æ‰€ä»¥æ‰å»ø™®®å¤§å®¶åœ¨å­¦ä¹?f¨¤n)J2ee开始的时候一定要认真学习(f¨¤n)JspåQŒå…¶å®žæœ€é‡è¦çš„就是明白标½{„¡š„本质ã€?<br /> <br /> Html标签我们都很熟æ?zh¨¨n)‰äº†(ji¨£n),æ?<html> ã€?<head> ã€?<body> ã€?<title> åQŒJsp带来的Tag标签遵åó@同样的格式,或者说更严格的Xml格式规范åQŒä¾‹å¦?<jsp:include> ã€?<jsp:useBean> ã€?<c:if> ã€?<c:forEach> ½{‰ç­‰ã€‚它们没有什么神¿U˜çš„地方åQŒå°±å…¶æºå¤´ä¹Ÿ˜q˜æ˜¯Java Class而已åQŒTag标签的实质也ž®±æ˜¯ä¸€ŒDµJava代码åQŒæˆ–者说一个Classæ–‡äšg。当配置文äšg讄¡½®å¥½åŽ»å“ªé‡Œå¯ÀL‰¾˜q™äº›Classçš„èµ\径后åQŒå®¹å™¨è´Ÿè´£å°†™åµé¢ä¸­å­˜åœ¨çš„æ ‡ç­¾å¯¹åº”到相应的Class上,执行那段特定的Java代码åQŒå¦‚此而已ã€?<br /> 说得明白一点的话还是ä‹D几个½Ž€å•的例子说明一下吧åQ?<br /> <br /> <jsp:include> åŽÕd“ªé‡Œæ‰¾æ‰§è¡Œä»€ä¹ˆclasså‘?首先˜q™æ˜¯ä¸ªjsp¾cÕdº“的标½{¾ï¼Œå½“然要去jsp¾cÕdº“å¯ÀL‰¾ç›¸åº”çš„classäº?ji¨£n),同样它也是由Web容器来提供,例如 Tomcatž®±åº”该去安装目录的libæ–‡äšg夹下面的jsp-api.jar里面找,有兴­‘£çš„可以åŽÀL‰¾ä¸€æ‰‘Ö•ŠåQ?<br /> <br /> <c:forEach> 又去哪里扑֑¢åQŸè¿™ä¸ªæ˜¯ç”±Jsp2.0版本推荐的和核心(j¨©)标记库的内容åQŒä¾‹å¦?<c:if> ž®±å¯¹åº”在™åµé¢ä¸­åšif判断的功能的一断Java代码。它的classæ–‡äšg在jstl.jar˜q™ä¸ª¾cÕdº“里面åQŒå¾€å¾€˜q˜éœ€è¦å’Œä¸€ä¸ªstandard.jar¾cÕdº“一起导入,攑֜¨å…·ä½“Web™å¹ç›®çš„WEB-INFçš„lib目录下面ž®±å¯ä»¥ä‹É用了(ji¨£n)ã€?<br /> <br /> ™åÞZ¾¿¾|—唆一句,W(xu¨¦)eb Projectçš„ç›®å½•ç»“æž„æ˜¯ç›¸å¯¹å›ºå®šçš„ï¼Œå› äØ“(f¨´)容器ä¼?x¨¬)按照固定的路径åŽÕd¯»æ‰‘Ö®ƒéœ€è¦çš„配置文äšg和资源,˜q™ä¸ªä»ÖM½•一本J2ee入门书上都有åQŒè¿™é‡Œå°±ä¸ä»‹¾läº†(ji¨£n)。了(ji¨£n)è§£Tag的本质还要了(ji¨£n)解它的工作原理,所以大家去J2eeçš„APIé‡Œæ‰¾åˆ°åÆˆç ”ç©¶˜q™ä¸ªåŒ…:(x¨¬)javax.servlet.jsp.tagext。它有一些接口,和一些实现类åQŒä¸“门用语开发TagåQŒåªæœ‰è‡ªå·×ƒº²è‡ªå†™å‡ºå‡ ä¸ªä¸åŒåŠŸèƒ½çš„æ ‡ç­¾åQŒæ‰½Ž—是真正理解äº?ji¨£n)æ ‡½{„¡š„原理。别忘记äº?ji¨£n)自己开发的标签要自己去完成配置文äšgåQŒå®¹å™¨åªæ˜¯é›†æˆäº†(ji¨£n)åŽÕd“ªé‡Œå¯»æ‰¾jsp标签对应classçš„èµ\径,自己写的标签库当然要告诉容器åŽÕd“ªé‡Œæ‰¾å•¦ã€?<br /> <br /> 说了(ji¨£n)˜q™ä¹ˆå¤šï¼Œæˆ‘们ä¸ÞZ»€ä¹ˆè¦ç”¨æ ‡½{‘Ö‘¢åQŸå®Œå…¨åœ¨Jsp里面来个 <% %> ž®±å¯ä»¥åœ¨é‡Œé¢ä»ÀL„å†™Java代码äº?ji¨£n),但是长期实践发现™åµé¢ä»£ç ¾lŸä¸€éƒ½æ˜¯ä¸Žhtml同风格的标记语言更加有助于美工äh员进行开发前収ͼŒå®ƒä¸éœ€è¦æ‡‚JavaåQŒåªè¦Java½E‹åºå‘˜ç»™ä¸ªåˆ—表告诉美工什么标½{‘֏¯ä»¥å®Œæˆä»€ä¹ˆé€»è¾‘功能åQŒä»–ž®±å¯ä»¥ä¸“注于¾ŸŽå·¥åQŒä¹Ÿ½Ž—是˜q›ä¸€æ­¥é𔼛ÖMº†(ji¨£n)前后台的工作吧! <br /> <br /> 3åQ?成就Web框架 <br /> 框架是什么?曄¡»çœ‹è¿‡˜q™æ ·çš„定义:(x¨¬)与模式类ä¼û|¼Œæ¡†æž¶ä¹Ÿæ˜¯è§£å†³ç‰¹å®šé—®é¢˜çš„可重用æ–ÒŽ(gu¨©)³•åQŒæ¡†æž¶æ˜¯ä¸€ä¸ªæ˜q°æ€§çš„æž„徏块和服务集合åQŒå¼€å‘äh员可以用来达成某个目标。一般来è¯ß_(d¨¢)¼Œæ¡†æž¶æä¾›äº?ji¨£n)è§£å†ÏxŸ¾c»é—®é¢˜çš„基础设施åQŒæ˜¯ç”¨æ¥åˆ›å¾è§£å†³æ–ÒŽ(gu¨©)¡ˆçš„工典P¼Œè€Œä¸æ˜¯é—®é¢˜çš„解决æ–ÒŽ(gu¨©)¡ˆã€?<br /> <br /> 正是ç”׃ºŽTag的出玎ͼŒæˆå°±äº?ji¨£n)以后出现的那么多Web框架åQŒå®ƒä»¬éƒ½å¼€å‘了(ji¨£n)自己成熟实用的一套标½{¾ï¼Œç„¶åŽç”Þq‰¹å®šçš„Xmlæ–‡äšg来配¾|®åŠ è½½ä¿¡æ¯ï¼ŒåŠ›å›¾ä½¿å¾—Web 应用的开发变得更加高效。下面这些标½{„¡›¸åº”对很多人来说相当熟æ‚(zh¨¨n)‰äº†(ji¨£n)åQ?<br /> <html:password> <br /> <logic:equal> <br /> <bean:write> <br /> <f:view> <br /> <h:form> <br /> <h:message> <br /> <br /> 它们分别来自Strutså’ŒJSF框架åQŒæœ€å¼ºå¤§çš„功能在于控制è{发,ž®±æ˜¯MVC三层模型中间完成控制器的工作。Struts-1å®žé™…ä¸ŠåÆˆæœªåšåˆ°çœŸæ­£çš„ä¸‰å±‚éš”ç¦»åQŒè¿™ä¸€ç‚¹åœ¨Struts-2上得åˆîCº†(ji¨£n)很大的改˜q›ã€‚而Jsf向来以比较完善合理的标签库受åˆîCh们推崇ã€?<br /> <br /> 今天ž®±å¤§æ¦‚讲˜q™ä¹ˆå¤šå§åQŒå†‹Æ¡éœ€è¦å¼ºè°ƒçš„æ˜¯Servlet/Jsp是学ä¹?f¨¤n)J2ee必经之èµ\åQŒä¹Ÿæ˜¯æœ€åŸºç¡€çš„知识,希望大家¾l™ä¸Ž­‘›_¤Ÿçš„重视! <br /> Java杂谈åQˆä¹(ji¨¦)åQ‰ï¼åQStruts <br /> Java杂谈åQˆä¹(ji¨¦)åQ‰ï¼åQStruts <br /> <br /> J2ee的开源框架很多,½W”者只能介¾lè‡ªå·Þq†Ÿæ‚(zh¨¨n)‰çš„几个åQŒå…¶ä»–的目前在中国IT行业应用得不是很多。希望大家对新出的框架不要盲目的推崇åQŒé¦–先一定要熟æ?zh¨¨n)‰å®ƒæ¯”旧的到底好在哪里åQŒæ–°çš„理念和ç‰ÒŽ(gu¨©)€§æ˜¯ä»€ä¹ˆï¼Ÿç„¶åŽå†å†³å®šæ˜¯å¦è¦ä½¿ç”¨å®ƒã€?<br /> <br /> ˜q™æœŸçš„主题是StrutsåQŒç›´è¯‘过来是支架。Struts的第一个版本是åœ?001òq?月发布的åQŒå®ƒæä¾›äº?ji¨£n)一个Web应用的解å†Ïx–¹æ¡ˆï¼Œå¦‚何让Jspå’?servlet共存åŽÀLä¾›æ¸…晰的分离视图和业务应用逻辑的架构。在Struts之前åQŒé€šå¸¸çš„做法是在Jsp中加入业务逻辑åQŒæˆ–者在Servlet中生成视图è{发到前台厅R€‚Struts带着MVC的新理念当时退出几乎成ä¸ÞZ¸šç•Œå…¬è®¤çš„Web应用标准åQŒäºŽæ˜¯å½“代ITå¸?j¨¬ng)场上也出现了(ji¨£n)众多熟æ?zh¨¨n)‰Struts的程序员。即使有新的框架再出来不用,而ç‘ô¾l­ç”¨Struts的理ç”׃¹ŸåŠ ä¸Šäº?ji¨£n)一条低风险åQŒå› ä¸ÞZ¸­é€”如果开发äh员变动,很容易的招进新的ä¼?x¨¬)Strutsçš„IT民工啊, ^_^! <br /> </div> <img src ="http://www.aygfsteel.com/zdf8013/aggbug/246057.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/zdf8013/" target="_blank">赵国æž?/a> 2008-12-12 23:37 <a href="http://www.aygfsteel.com/zdf8013/archive/2008/12/12/246057.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> Ö÷Õ¾Ö©Öë³ØÄ£°å£º <a href="http://" target="_blank">ͳ·¬ÊÐ</a>| <a href="http://" target="_blank">³¤ÁëÏØ</a>| <a href="http://" target="_blank">ƽÓßÏØ</a>| <a href="http://" target="_blank">ÔæÑôÊÐ</a>| <a href="http://" target="_blank">̨ɽÊÐ</a>| <a href="http://" target="_blank">ÍÁÄ¬ÌØÓÒÆì</a>| <a href="http://" target="_blank">ÖÎÏØ¡£</a>| <a href="http://" target="_blank">ÍþÐÅÏØ</a>| <a href="http://" target="_blank">ËàÄÏ</a>| <a href="http://" target="_blank">ÁøÁÖÏØ</a>| <a href="http://" target="_blank">³çÈÊÏØ</a>| <a href="http://" target="_blank">³¤Ë³ÏØ</a>| <a href="http://" target="_blank">¾¸½­ÊÐ</a>| <a href="http://" target="_blank">ÎIJýÊÐ</a>| <a href="http://" target="_blank">ÇɼÒÏØ</a>| <a href="http://" target="_blank">¸ö¾ÉÊÐ</a>| <a href="http://" target="_blank">ϲµÂÏØ</a>| <a href="http://" target="_blank">ÁúÉ½ÏØ</a>| <a href="http://" target="_blank">ÂåÄþÏØ</a>| <a href="http://" target="_blank">ÁÙÏæÊÐ</a>| <a href="http://" target="_blank">´óÒ±ÊÐ</a>| <a href="http://" target="_blank">ÄÏ¿ªÇø</a>| <a href="http://" target="_blank">Ç­ÄÏ</a>| <a href="http://" target="_blank">Û·ÉÆÏØ</a>| <a href="http://" target="_blank">¹ãÖÝÊÐ</a>| <a href="http://" target="_blank">³çÀñÏØ</a>| <a href="http://" target="_blank">°×ÓñÏØ</a>| <a href="http://" target="_blank">ͨÓÜÏØ</a>| <a href="http://" target="_blank">¾®ÚêÏØ</a>| <a href="http://" target="_blank">ÐÂÏçÊÐ</a>| <a href="http://" target="_blank">Ê©±üÏØ</a>| <a href="http://" target="_blank">ÑïÖÝÊÐ</a>| <a href="http://" target="_blank">±ß°ÓÏØ</a>| <a href="http://" target="_blank">Æ½Ò£ÏØ</a>| <a href="http://" target="_blank">Ïî³ÇÊÐ</a>| <a href="http://" target="_blank">¶¼½­ÑßÊÐ</a>| <a href="http://" target="_blank">Ìì½òÊÐ</a>| <a href="http://" target="_blank">ÜÆ½­</a>| <a href="http://" target="_blank">ºÍÁÖ¸ñ¶ûÏØ</a>| <a href="http://" target="_blank">ÓÀµÂÏØ</a>| <a href="http://" target="_blank">̨ÍåÊ¡</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>