﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>语源科技BlogJava-caid</title><link>http://www.blogjava.net/caid/</link><description>JAVA CPP</description><language>zh-cn</language><lastBuildDate>Mon, 13 Apr 2026 10:45:29 GMT</lastBuildDate><pubDate>Mon, 13 Apr 2026 10:45:29 GMT</pubDate><ttl>60</ttl><item><title>JAVA面试题（ZT）</title><link>http://www.blogjava.net/caid/archive/2006/02/17/31217.html</link><dc:creator>caid'weblog</dc:creator><author>caid'weblog</author><pubDate>Fri, 17 Feb 2006 08:17:00 GMT</pubDate><guid>http://www.blogjava.net/caid/archive/2006/02/17/31217.html</guid><wfw:comment>http://www.blogjava.net/caid/comments/31217.html</wfw:comment><comments>http://www.blogjava.net/caid/archive/2006/02/17/31217.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/caid/comments/commentRss/31217.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caid/services/trackbacks/31217.html</trackback:ping><description><![CDATA[前段时间因为要参加一个笔试，在准备期间在网上找到了两条关于笔试题目的文章，其中一篇为&lt;&lt;有感:应聘Java笔试时可能出现问题&gt;&gt;，还有一篇忘了名字，读后深受启发。 <BR>在寻找这些答案的过程中，我将相关答案记录下来，就形成了以下这些东西。需要说明的是以下答案肯定有很多不完整甚至错误的地方，需要各位来更正与完善它，千万不要扔我的鸡蛋啊。 <BR>希望本文能够给即将奔赴笔试考场的同仁些许帮助，更希望更多的人加入到收集整理笔试题与完善答案的这些工作中来，为大家更好的获得工作机会做一点贡献。 <BR>在此感谢前面两文的作者的对笔试题目的收集与整理。 <BR>如有任何意见与建议请通过QQ:6045306,Mail:huijunzi@21cn.com与我联系。 <BR>Java基础方面: <BR><BR>1、作用域public,private,protected,以及不写时的区别 <BR>答：区别如下： <BR>作用域 当前类 同一package 子孙类 其他package <BR>public √ √ √ √ <BR>protected √ √ √ × <BR>friendly √ √ × × <BR>private √ × × × <BR>不写时默认为friendly <BR><BR>2、ArrayList和Vector的区别,HashMap和Hashtable的区别 <BR>答：就ArrayList与Vector主要从二方面来说. <BR>一.同步性:Vector是线程安全的，也就是说是同步的，而ArrayList是线程序不安全的，不是同步的 <BR>二.数据增长:当需要增长时,Vector默认增长为原来一培，而ArrayList却是原来的一半 <BR>就HashMap与HashTable主要从三方面来说。 <BR>一.历史原因:Hashtable是基于陈旧的Dictionary类的，HashMap是Java 1.2引进的Map接口的一个实现 <BR>二.同步性:Hashtable是线程安全的，也就是说是同步的，而HashMap是线程序不安全的，不是同步的 <BR>三.值：只有HashMap可以让你将空值作为一个表的条目的key或value <BR><BR>3、char型变量中能不能存贮一个中文汉字?为什么? <BR>答：是能够定义成为一个中文的，因为java中以unicode编码，一个char占16个字节，所以放一个中文是没问题的 <BR><BR>4、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? <BR>答：多线程有两种实现方法，分别是继承Thread类与实现Runnable接口 <BR>同步的实现方面有两种，分别是synchronized,wait与notify <BR><BR>5、继承时候类的执行顺序问题,一般都是选择题,问你将会打印出什么? <BR>答:父类： <BR>package test; <BR>public class FatherClass <BR>{ <BR>public FatherClass() <BR>{ <BR>System.out.println("FatherClass Create"); <BR>} <BR>} <BR>子类: <BR>package test; <BR>import test.FatherClass; <BR>public class ChildClass extends FatherClass <BR>{ <BR>public ChildClass() <BR>{ <BR>System.out.println("ChildClass Create"); <BR>} <BR>public static void main(String[] args) <BR>{ <BR>FatherClass fc = new FatherClass(); <BR>ChildClass cc = new ChildClass(); <BR>} <BR>} <BR>输出结果： <BR>C:\&gt;java test.ChildClass <BR>FatherClass Create <BR>FatherClass Create <BR>ChildClass Create <BR><BR>6、内部类的实现方式? <BR>答：示例代码如下： <BR>package test; <BR>public class OuterClass <BR>{ <BR>private class InterClass <BR>{ <BR>public InterClass() <BR>{ <BR>System.out.println("InterClass Create"); <BR>} <BR>} <BR>public OuterClass() <BR>{ <BR>InterClass ic = new InterClass(); <BR>System.out.println("OuterClass Create"); <BR>} <BR>public static void main(String[] args) <BR>{ <BR>OuterClass oc = new OuterClass(); <BR>} <BR>} <BR>输出结果: <BR>C:\&gt;java test/OuterClass <BR>InterClass Create <BR>OuterClass Create <BR>再一个例题： <BR>public class OuterClass { <BR>private double d1 = 1.0; <BR>//insert code here <BR>} <BR>You need to insert an inner class declaration at line 3. Which two inner class declarations are <BR><BR>valid?(Choose two.) <BR>A. class InnerOne{ <BR>public static double methoda() {return d1;} <BR>} <BR>B. public class InnerOne{ <BR>static double methoda() {return d1;} <BR>} <BR>C. private class InnerOne{ <BR>double methoda() {return d1;} <BR>} <BR>D. static class InnerOne{ <BR>protected double methoda() {return d1;} <BR>} <BR>E. abstract class InnerOne{ <BR>public abstract double methoda(); <BR>} <BR>说明如下： <BR>一.静态内部类可以有静态成员，而非静态内部类则不能有静态成员。 故 A、B 错 <BR>二.静态内部类的非静态成员可以访问外部类的静态变量，而不可访问外部类的非静态变量；return d1 出错。 <BR><BR>故 D 错 <BR>三.非静态内部类的非静态成员可以访问外部类的非静态变量。 故 C 正确 <BR>四.答案为C、E <BR><BR>7、垃圾回收机制,如何优化程序? <BR>希望大家补上，谢谢 <BR><BR>8、float型float f=3.4是否正确? <BR>答:不正确。精度不准确,应该用强制类型转换，如下所示：float f=(float)3.4 <BR><BR>9、介绍JAVA中的Collection FrameWork(包括如何写自己的数据结构)? <BR>答：Collection FrameWork如下： <BR>Collection <BR>├List <BR>│├LinkedList <BR>│├ArrayList <BR>│└Vector <BR>│　└Stack <BR>└Set <BR>Map <BR>├Hashtable <BR>├HashMap <BR>└WeakHashMap <BR>Collection是最基本的集合接口，一个Collection代表一组Object，即Collection的元素（Elements） <BR>Map提供key到value的映射 <BR><BR>10、Java中异常处理机制，事件机制？ <BR><BR>11、JAVA中的多形与继承？ <BR>希望大家补上，谢谢 <BR><BR>12、抽象类与接口？ <BR>答：抽象类与接口都用于抽象，但是抽象类(JAVA中)可以有自己的部分实现，而接口则完全是一个标识(同时有多重继承的功能)。 <BR><BR>13、Java 的通信编程，编程题(或问答)，用JAVA SOCKET编程，读服务器几个字符，再写入本地显示？ <BR>答:Server端程序: <BR>package test; <BR>import java.net.*; <BR>import java.io.*; <BR><BR>public class Server <BR>{ <BR>private ServerSocket ss; <BR>private Socket socket; <BR>private BufferedReader in; <BR>private PrintWriter out; <BR>public Server() <BR>{ <BR>try <BR>{ <BR>ss=new ServerSocket(10000); <BR>while(true) <BR>{ <BR>socket = ss.accept(); <BR>String RemoteIP = socket.getInetAddress().getHostAddress(); <BR>String RemotePort = ":"+socket.getLocalPort(); <BR>System.out.println("A client come in!IP:"+RemoteIP+RemotePort); <BR>in = new BufferedReader(new <BR><BR>InputStreamReader(socket.getInputStream())); <BR>String line = in.readLine(); <BR>System.out.println("Cleint send is :" + line); <BR>out = new PrintWriter(socket.getOutputStream(),true); <BR>out.println("Your Message Received!"); <BR>out.close(); <BR>in.close(); <BR>socket.close(); <BR>} <BR>}catch (IOException e) <BR>{ <BR>out.println("wrong"); <BR>} <BR>} <BR>public static void main(String[] args) <BR>{ <BR>new Server(); <BR>} <BR>}; <BR>Client端程序: <BR>package test; <BR>import java.io.*; <BR>import java.net.*; <BR><BR>public class Client <BR>{ <BR>Socket socket; <BR>BufferedReader in; <BR>PrintWriter out; <BR>public Client() <BR>{ <BR>try <BR>{ <BR>System.out.println("Try to Connect to 127.0.0.1:10000"); <BR>socket = new Socket("127.0.0.1",10000); <BR>System.out.println("The Server Connected!"); <BR>System.out.println("Please enter some Character:"); <BR>BufferedReader line = new BufferedReader(new <BR><BR>InputStreamReader(System.in)); <BR>out = new PrintWriter(socket.getOutputStream(),true); <BR>out.println(line.readLine()); <BR>in = new BufferedReader(new InputStreamReader(socket.getInputStream())); <BR>System.out.println(in.readLine()); <BR>out.close(); <BR>in.close(); <BR>socket.close(); <BR>}catch(IOException e) <BR>{ <BR>out.println("Wrong"); <BR>} <BR>} <BR>public static void main(String[] args) <BR>{ <BR>new Client(); <BR>} <BR>}; <BR><BR>14、用JAVA实现一种排序，JAVA类实现序列化的方法(二种)？ 如在COLLECTION框架中，实现比较要实现什么样的接口？ <BR>答:用插入法进行排序代码如下 <BR>package test; <BR>import java.util.*; <BR>class InsertSort <BR>{ <BR>ArrayList al; <BR>public InsertSort(int num,int mod) <BR>{ <BR>al = new ArrayList(num); <BR>Random rand = new Random(); <BR>System.out.println("The ArrayList Sort Before:"); <BR>for (int i=0;i&lt;num ;i++ ) <BR>{ <BR>al.add(new Integer(Math.abs(rand.nextInt()) % mod + 1)); <BR>System.out.println("al["+i+"]="+al.get(i)); <BR>} <BR>} <BR>public void SortIt() <BR>{ <BR>Integer tempInt; <BR>int MaxSize=1; <BR>for(int i=1;i&lt;al.size();i++) <BR>{ <BR>tempInt = (Integer)al.remove(i); <BR>if(tempInt.intValue()&gt;=((Integer)al.get(MaxSize-1)).intValue()) <BR>{ <BR>al.add(MaxSize,tempInt); <BR>MaxSize++; <BR>System.out.println(al.toString()); <BR>} else { <BR>for (int j=0;j&lt;MaxSize ;j++ ) <BR>{ <BR>if <BR><BR>(((Integer)al.get(j)).intValue()&gt;=tempInt.intValue()) <BR>{ <BR>al.add(j,tempInt); <BR>MaxSize++; <BR>System.out.println(al.toString()); <BR>break; <BR>} <BR>} <BR>} <BR>} <BR>System.out.println("The ArrayList Sort After:"); <BR>for(int i=0;i&lt;al.size();i++) <BR>{ <BR>System.out.println("al["+i+"]="+al.get(i)); <BR>} <BR>} <BR>public static void main(String[] args) <BR>{ <BR>InsertSort is = new InsertSort(10,100); <BR>is.SortIt(); <BR>} <BR>} <BR>JAVA类实现序例化的方法是实现java.io.Serializable接口 <BR>Collection框架中实现比较要实现Comparable 接口和 Comparator 接口 <BR><BR>15、编程：编写一个截取字符串的函数，输入为一个字符串和字节数，输出为按字节截取的字符串。 但是要保证汉字不被截半个，如“我ABC”4，应该截为“我AB”，输入“我ABC汉DEF”，6，应该输出为“我ABC”而不是“我ABC+汉的半个”。 <BR>答：代码如下： <BR>package test; <BR><BR>class SplitString <BR>{ <BR>String SplitStr; <BR>int SplitByte; <BR>public SplitString(String str,int bytes) <BR>{ <BR>SplitStr=str; <BR>SplitByte=bytes; <BR>System.out.println("The String is:´"+SplitStr+"´;SplitBytes="+SplitByte); <BR>} <BR>public void SplitIt() <BR>{ <BR>int loopCount; <BR><BR>loopCount=(SplitStr.length()%SplitByte==0)?(SplitStr.length()/SplitByte):(SplitStr.length()/Split <BR><BR>Byte+1); <BR>System.out.println("Will Split into "+loopCount); <BR>for (int i=1;i&lt;=loopCount ;i++ ) <BR>{ <BR>if (i==loopCount){ <BR><BR>System.out.println(SplitStr.substring((i-1)*SplitByte,SplitStr.length())); <BR>} else { <BR><BR>System.out.println(SplitStr.substring((i-1)*SplitByte,(i*SplitByte))); <BR>} <BR>} <BR>} <BR>public static void main(String[] args) <BR>{ <BR>SplitString ss = new SplitString("test中dd文dsaf中男大3443n中国43中国人 <BR><BR>0ewldfls=103",4); <BR>ss.SplitIt(); <BR>} <BR>} <BR><BR>16、JAVA多线程编程。 用JAVA写一个多线程程序，如写四个线程，二个加1，二个对一个变量减一，输出。 <BR>希望大家补上，谢谢 <BR><BR>17、STRING与STRINGBUFFER的区别。 <BR>答：STRING的长度是不可变的，STRINGBUFFER的长度是可变的。如果你对字符串中的内容经常进行操作，特别是内容要修改时，那么使用StringBuffer，如果最后需要String，那么使用StringBuffer的toString()方法 <BR><BR>Jsp方面 <BR><BR>1、jsp有哪些内置对象?作用分别是什么? <BR>答:JSP共有以下9种基本内置组件（可与ASP的6种内部组件相对应）： <BR>　request 用户端请求，此请求会包含来自GET/POST请求的参数 <BR>response 网页传回用户端的回应 <BR>pageContext 网页的属性是在这里管理 <BR>session 与请求有关的会话期 <BR>application servlet 正在执行的内容 <BR>out 用来传送回应的输出 <BR>config servlet的构架部件 <BR>page JSP网页本身 <BR>exception 针对错误网页，未捕捉的例外 <BR><BR>2、jsp有哪些动作?作用分别是什么? <BR>答:JSP共有以下6种基本动作 <BR>jsp:include：在页面被请求的时候引入一个文件。 <BR>jsp:useBean：寻找或者实例化一个JavaBean。 <BR>jsp:setProperty：设置JavaBean的属性。 <BR>jsp:getProperty：输出某个JavaBean的属性。 <BR>jsp:forward：把请求转到一个新的页面。 <BR>jsp:plugin：根据浏览器类型为Java插件生成OBJECT或EMBED标记 <BR><BR>3、JSP中动态INCLUDE与静态INCLUDE的区别？ <BR>答：动态INCLUDE用jsp:include动作实现 <BR>&lt;jsp:include page="included.jsp" flush="true" /&gt;它总是会检查所含文件中的变化，适合用于包含动态页面，并且可以带参数 <BR>静态INCLUDE用include伪码实现,定不会检查所含文件的变化，适用于包含静态页面 <BR>&lt;%@ include file="included.htm" %&gt; <BR><BR>4、两种跳转方式分别是什么?有什么区别? <BR>答：有两种，分别为： <BR>&lt;jsp:include page="included.jsp" flush="true"&gt; <BR>&lt;jsp:forward page= "nextpage.jsp"/&gt; <BR>前者页面不会转向include所指的页面，只是显示该页的结果，主页面还是原来的页面。执行完后还会回来，相当于函数调用。并且可以带参数.后者完全转向新页面，不会再回来。相当于go to 语句。 <BR><BR>Servlet方面 <BR><BR>1、说一说Servlet的生命周期? <BR>答:servlet有良好的生存期的定义，包括加载和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。 <BR><BR>2、Servlet版本间(忘了问的是哪两个版本了)的不同? <BR>希望大家补上，谢谢 <BR><BR>3、JAVA SERVLET API中forward() 与redirect()的区别？ <BR>答:前者仅是容器中控制权的转向，在客户端浏览器地址栏中不会显示出转向后的地址；后者则是完全的跳转，浏览器将会得到跳转的地址，并重新发送请求链接。这样，从浏览器的地址栏中可以看到跳转后的链接地址。所以，前者更加高效，在前者可以满足需要时，尽量使用forward()方法，并且，这样也有助于隐藏实际的链接。在有些情况下，比如，需要跳转到一个其它服务器上的资源，则必须使用sendRedirect()方法。 <BR><BR>4、Servlet的基本架构 <BR>public class ServletName extends HttpServlet { <BR>public void doPost(HttpServletRequest request, HttpServletResponse response) throws <BR>ServletException, IOException { <BR>} <BR>public void doGet(HttpServletRequest request, HttpServletResponse response) throws <BR>ServletException, IOException { <BR>} <BR>} <BR><BR>Jdbc、Jdo方面 <BR><BR>1、可能会让你写一段Jdbc连Oracle的程序,并实现数据查询. <BR>答:程序如下： <BR>package hello.ant; <BR>import java.sql.*; <BR>public class jdbc <BR>{ <BR>String dbUrl="jdbc:oracle:thin:@127.0.0.1:1521:orcl"; <BR>String theUser="admin"; <BR>String thePw="manager"; <BR>Connection c=null; <BR>Statement conn; <BR>ResultSet rs=null; <BR>public jdbc() <BR>{ <BR>try{ <BR>Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); <BR>c = DriverManager.getConnection(dbUrl,theUser,thePw); <BR>conn=c.createStatement(); <BR>}catch(Exception e){ <BR>e.printStackTrace(); <BR>} <BR>} <BR>public boolean executeUpdate(String sql) <BR>{ <BR>try <BR>{ <BR>conn.executeUpdate(sql); <BR>return true; <BR>} <BR>catch (SQLException e) <BR>{ <BR>e.printStackTrace(); <BR>return false; <BR>} <BR>} <BR>public ResultSet executeQuery(String sql) <BR>{ <BR>rs=null; <BR>try <BR>{ <BR>rs=conn.executeQuery(sql); <BR>} <BR>catch (SQLException e) <BR>{ <BR>e.printStackTrace(); <BR>} <BR>return rs; <BR>} <BR>public void close() <BR>{ <BR>try <BR>{ <BR>conn.close(); <BR>c.close(); <BR>} <BR>catch (Exception e) <BR>{ <BR>e.printStackTrace(); <BR>} <BR>} <BR>public static void main(String[] args) <BR>{ <BR>ResultSet rs; <BR>jdbc conn = new jdbc(); <BR>rs=conn.executeQuery("select * from test"); <BR>try{ <BR>while (rs.next()) <BR>{ <BR>System.out.println(rs.getString("id")); <BR>System.out.println(rs.getString("name")); <BR>} <BR>}catch(Exception e) <BR>{ <BR>e.printStackTrace(); <BR>} <BR>} <BR>} <BR><BR>2、Class.forName的作用?为什么要用? <BR>答：调用该访问返回一个以字符串指定类名的类的对象。 <BR><BR>3、Jdo是什么? <BR>答:JDO是Java对象持久化的新的规范，为java data object的简称,也是一个用于存取某种数据仓库中的对象的标准化API。JDO提供了透明的对象存储，因此对开发人员来说，存储数据对象完全不需要额外的代码（如JDBC API的使用）。这些繁琐的例行工作已经转移到JDO产品提供商身上，使开发人员解脱出来，从而集中时间和精力在业务逻辑上。另外，JDO很灵活，因为它可以在任何数据底层上运行。JDBC只是面向关系数据库（RDBMS)JDO更通用，提供到任何数据底层的存储功能，比如关系数据库、文件、XML以及对象数据库（ODBMS）等等，使得应用可移植性更强。 <BR><BR>4、在ORACLE大数据量下的分页解决方法。一般用截取ID方法，还有是三层嵌套方法。 <BR>答:一种分页方法 <BR>&lt;% <BR>int i=1; <BR>int numPages=14; <BR>String pages = request.getParameter("page") ; <BR>int currentPage = 1; <BR>currentPage=(pages==null)?(1):{Integer.parseInt(pages)} <BR>sql = "select count(*) from tables"; <BR>ResultSet rs = DBLink.executeQuery(sql) ; <BR>while(rs.next()) i = rs.getInt(1) ; <BR>int intPageCount=1; <BR>intPageCount=(i%numPages==0)?(i/numPages):(i/numPages+1); <BR>int nextPage ; <BR>int upPage; <BR>nextPage = currentPage+1; <BR>if (nextPage&gt;=intPageCount) nextPage=intPageCount; <BR>upPage = currentPage-1; <BR>if (upPage&lt;=1) upPage=1; <BR>rs.close(); <BR>sql="select * from tables"; <BR>rs=DBLink.executeQuery(sql); <BR>i=0; <BR>while((i&lt;numPages*(currentPage-1))&amp;&amp;rs.next()){i++;} <BR>%&gt; <BR>//输出内容 <BR>//输出翻页连接 <BR>合计:&lt;%=currentPage%&gt;/&lt;%=intPageCount%&gt;&lt;a href="List.jsp?page=1"&gt;第一页&lt;/a&gt;&lt;a <BR><BR>href="List.jsp?page=&lt;%=upPage%&gt;"&gt;上一页&lt;/a&gt; <BR>&lt;% <BR>for(int j=1;j&lt;=intPageCount;j++){ <BR>if(currentPage!=j){ <BR>%&gt; <BR>&lt;a href="list.jsp?page=&lt;%=j%&gt;"&gt;[&lt;%=j%&gt;]&lt;/a&gt; <BR>&lt;% <BR>}else{ <BR>out.println(j); <BR>} <BR>} <BR>%&gt; <BR>&lt;a href="List.jsp?page=&lt;%=nextPage%&gt;"&gt;下一页&lt;/a&gt;&lt;a href="List.jsp?page=&lt;%=intPageCount%&gt;"&gt;最后页 <BR><BR>&lt;/a&gt; <BR><BR>Xml方面 <BR><BR>1、xml有哪些解析技术?区别是什么? <BR>答:有DOM,SAX,STAX等 <BR>DOM:处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的，这种结构占用的内存较多，而且DOM必须在解析文件之前把整个文档装入内存,适合对XML的随机访问SAX:不现于DOM,SAX是事件驱动型的XML解析方式。它顺序读取XML文件，不需要一次全部装载整个文件。当遇到像文件开头，文档结束，或者标签开头与标签结束时，它会触发一个事件，用户通过在其回调事件中写入处理代码来处理XML文件，适合对XML的顺序访问 <BR>STAX:Streaming API for XML (StAX) <BR><BR>2、你在项目中用到了xml技术的哪些方面?如何实现的? <BR>答:用到了数据存贮，信息配置两方面。在做数据交换平台时，将不能数据源的数据组装成XML文件，然后将XML文件压缩打包加密后通过网络传送给接收者，接收解密与解压缩后再同XML文件中还原相关信息进行处理。在做软件配置时，利用XML可以很方便的进行，软件的各种配置参数都存贮在XML文件中。 <BR><BR>3、用jdom解析xml文件时如何解决中文问题?如何解析? <BR>答:看如下代码,用编码方式加以解决 <BR>package test; <BR>import java.io.*; <BR>public class DOMTest <BR>{ <BR>private String inFile = "c:\\people.xml"; <BR>private String outFile = "c:\\people.xml"; <BR>public static void main(String args[]) <BR>{ <BR>new DOMTest(); <BR>} <BR>public DOMTest() <BR>{ <BR>try <BR>{ <BR>javax.xml.parsers.DocumentBuilder builder = <BR><BR>javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder(); <BR>org.w3c.dom.Document doc = builder.newDocument(); <BR>org.w3c.dom.Element root = doc.createElement("老师"); <BR>org.w3c.dom.Element wang = doc.createElement("王"); <BR>org.w3c.dom.Element liu = doc.createElement("刘"); <BR>wang.appendChild(doc.createTextNode("我是王老师")); <BR>root.appendChild(wang); <BR>doc.appendChild(root); <BR>javax.xml.transform.Transformer transformer = <BR>javax.xml.transform.TransformerFactory.newInstance().newTransformer(); <BR>transformer.setOutputProperty(javax.xml.transform.OutputKeys.ENCODING, "gb2312"); <BR>transformer.setOutputProperty(javax.xml.transform.OutputKeys.INDENT, "yes"); <BR><BR>transformer.transform(new javax.xml.transform.dom.DOMSource(doc), <BR>new <BR><BR>javax.xml.transform.stream.StreamResult(outFile)); <BR>} <BR>catch (Exception e) <BR>{ <BR>System.out.println (e.getMessage()); <BR>} <BR>} <BR>} <BR><BR>4、编程用JAVA解析XML的方式. <BR>答:用SAX方式解析XML，XML文件如下： <BR>&lt;?xml version="1.0" encoding="gb2312"?&gt; <BR>&lt;person&gt; <BR>&lt;name&gt;王小明&lt;/name&gt; <BR>&lt;college&gt;信息学院&lt;/college&gt; <BR>&lt;telephone&gt;6258113&lt;/telephone&gt; <BR>&lt;notes&gt;男,1955年生,博士，95年调入海南大学&lt;/notes&gt; <BR>&lt;/person&gt; <BR>事件回调类SAXHandler.java <BR>import java.io.*; <BR>import java.util.Hashtable; <BR>import org.xml.sax.*; <BR>public class SAXHandler extends HandlerBase <BR>{ <BR>private Hashtable table = new Hashtable(); <BR>private String currentElement = null; <BR>private String currentValue = null; <BR>public void setTable(Hashtable table) <BR>{ <BR>this.table = table; <BR>} <BR>public Hashtable getTable() <BR>{ <BR>return table; <BR>} <BR>public void startElement(String tag, AttributeList attrs) <BR>throws SAXException <BR>{ <BR>currentElement = tag; <BR>} <BR>public void characters(char[] ch, int start, int length) <BR>throws SAXException <BR>{ <BR>currentValue = new String(ch, start, length); <BR>} <BR>public void endElement(String name) throws SAXException <BR>{ <BR>if (currentElement.equals(name)) <BR>table.put(currentElement, currentValue); <BR>} <BR>} <BR>JSP内容显示源码,SaxXml.jsp: <BR>&lt;HTML&gt; <BR>&lt;HEAD&gt; <BR>&lt;TITLE&gt;剖析XML文件people.xml&lt;/TITLE&gt; <BR>&lt;/HEAD&gt; <BR>&lt;BODY&gt; <BR>&lt;%@ page errorPage="ErrPage.jsp" <BR>contentType="text/html;charset=GB2312" %&gt; <BR>&lt;%@ page import="java.io.*" %&gt; <BR>&lt;%@ page import="java.util.Hashtable" %&gt; <BR>&lt;%@ page import="org.w3c.dom.*" %&gt; <BR>&lt;%@ page import="org.xml.sax.*" %&gt; <BR>&lt;%@ page import="javax.xml.parsers.SAXParserFactory" %&gt; <BR>&lt;%@ page import="javax.xml.parsers.SAXParser" %&gt; <BR>&lt;%@ page import="SAXHandler" %&gt; <BR>&lt;% <BR>File file = new File("c:\\people.xml"); <BR>FileReader reader = new FileReader(file); <BR>Parser parser; <BR>SAXParserFactory spf = SAXParserFactory.newInstance(); <BR>SAXParser sp = spf.newSAXParser(); <BR>SAXHandler handler = new SAXHandler(); <BR>sp.parse(new InputSource(reader), handler); <BR>Hashtable hashTable = handler.getTable(); <BR>out.println("&lt;TABLE BORDER=2&gt;&lt;CAPTION&gt;教师信息表&lt;/CAPTION&gt;"); <BR>out.println("&lt;TR&gt;&lt;TD&gt;姓名&lt;/TD&gt;" + "&lt;TD&gt;" + <BR>(String)hashTable.get(new String("name")) + "&lt;/TD&gt;&lt;/TR&gt;"); <BR>out.println("&lt;TR&gt;&lt;TD&gt;学院&lt;/TD&gt;" + "&lt;TD&gt;" + <BR>(String)hashTable.get(new String("college"))+"&lt;/TD&gt;&lt;/TR&gt;"); <BR>out.println("&lt;TR&gt;&lt;TD&gt;电话&lt;/TD&gt;" + "&lt;TD&gt;" + <BR>(String)hashTable.get(new String("telephone")) + "&lt;/TD&gt;&lt;/TR&gt;"); <BR>out.println("&lt;TR&gt;&lt;TD&gt;备注&lt;/TD&gt;" + "&lt;TD&gt;" + <BR>(String)hashTable.get(new String("notes")) + "&lt;/TD&gt;&lt;/TR&gt;"); <BR>out.println("&lt;/TABLE&gt;"); <BR>%&gt; <BR>&lt;/BODY&gt; <BR>&lt;/HTML&gt; <BR><BR>EJB方面 <BR><BR>1、EJB2.0有哪些内容?分别用在什么场合? EJB2.0和EJB1.1的区别? <BR>答：规范内容包括Bean提供者，应用程序装配者，EJB容器，EJB配置工具，EJB服务提供者，系统管理员。这里面，EJB容器是EJB之所以能够运行的核心。EJB容器管理着EJB的创建，撤消，激活，去活，与数据库的连接等等重要的核心工作。JSP,Servlet,EJB,JNDI,JDBC,JMS..... <BR><BR>2、EJB与JAVA BEAN的区别？ <BR>答:Java Bean 是可复用的组件，对Java Bean并没有严格的规范，理论上讲，任何一个Java类都可以是一个Bean。但通常情况下，由于Java Bean是被容器所创建（如Tomcat)的，所以Java Bean应具有一个无参的构造器，另外，通常Java Bean还要实现Serializable接口用于实现Bean的持久性。Java Bean实际上相当于微软COM模型中的本地进程内COM组件，它是不能被跨进程访问的。Enterprise Java Bean 相当于DCOM，即分布式组件。它是基于Java的远程方法调用（RMI）技术的，所以EJB可以被远程访问（跨进程、跨计算机）。但EJB必须被布署在诸如Webspere、WebLogic这样的容器中，EJB客户从不直接访问真正的EJB组件，而是通过其容器访问。EJB容器是EJB组件的代理，EJB组件由容器所创建和管理。客户通过容器来访问真正的EJB组件。 <BR><BR>3、EJB的基本架构 <BR>答:一个EJB包括三个部分: <BR>Remote Interface 接口的代码 <BR>package Beans; <BR>import javax.ejb.EJBObject; <BR>import java.rmi.RemoteException; <BR>public interface Add extends EJBObject <BR>{ <BR>//some method declare <BR>} <BR>Home Interface 接口的代码 <BR>package Beans; <BR>import java.rmi.RemoteException; <BR>import jaax.ejb.CreateException; <BR>import javax.ejb.EJBHome; <BR>public interface AddHome extends EJBHome <BR>{ <BR>//some method declare <BR>} <BR>EJB类的代码 <BR>package Beans; <BR>import java.rmi.RemoteException; <BR>import javax.ejb.SessionBean; <BR>import javx.ejb.SessionContext; <BR>public class AddBean Implements SessionBean <BR>{ <BR>//some method declare <BR>} <BR><BR>J2EE,MVC方面 <BR><BR>1、MVC的各个部分都有那些技术来实现?如何实现? <BR>答:MVC是Model－View－Controller的简写。"Model" 代表的是应用的业务逻辑（通过JavaBean，EJB组件实现）， "View" 是应用的表示面（由JSP页面产生），"Controller" 是提供应用的处理过程控制（一般是一个Servlet），通过这种设计模型把应用逻辑，处理过程和显示逻辑分成不同的组件实现。这些组件可以进行交互和重用。 <BR><BR>2、应用服务器与WEB SERVER的区别？ <BR>希望大家补上，谢谢 <BR><BR>3、J2EE是什么？ <BR>答:Je22是Sun公司提出的多层(multi-diered),分布式(distributed),基于组件(component-base)的企业级应用模型(enterpriese application model).在这样的一个应用系统中，可按照功能划分为不同的组件，这些组件又可在不同计算机上，并且处于相应的层次(tier)中。所属层次包括客户层(clietn tier)组件,web层和组件,Business层和组件,企业信息系统(EIS)层。 <BR><BR>4、WEB SERVICE名词解释。JSWDL开发包的介绍。JAXP、JAXM的解释。SOAP、UDDI,WSDL解释。 <BR>答：Web Service描述语言WSDL <BR>SOAP即简单对象访问协议(Simple Object Access Protocol)，它是用于交换XML编码信息的轻量级协议。 <BR>UDDI 的目的是为电子商务建立标准；UDDI是一套基于Web的、分布式的、为Web Service提供的、信息注册中心的实现标准规范，同时也包含一组使企业能将自身提供的Web Service注册，以使别的企业能够发现的访问协议的实现标准。 <BR><BR>5、BS与CS的联系与区别。 <BR>希望大家补上，谢谢 <BR><BR>6、STRUTS的应用(如STRUTS架构) <BR>答：Struts是采用Java Servlet/JavaServer Pages技术，开发Web应用程序的开放源码的framework。 采用Struts能开发出基于MVC(Model-View-Controller)设计模式的应用构架。 Struts有如下的主要功能： <BR>一.包含一个controller servlet，能将用户的请求发送到相应的Action对象。 <BR>二.JSP自由tag库，并且在controller servlet中提供关联支持，帮助开发员创建交互式表单应用。 <BR>三.提供了一系列实用对象：XML处理、通过Java reflection APIs自动处理JavaBeans属性、国际化的提示和消息。 <BR><BR>设计模式方面 <BR><BR>1、开发中都用到了那些设计模式?用在什么场合? <BR>答：每个模式都描述了一个在我们的环境中不断出现的问题，然后描述了该问题的解决方案的核心。通过这种方式，你可以无数次地使用那些已有的解决方案，无需在重复相同的工作。主要用到了MVC的设计模式。用来开发JSP/Servlet或者J2EE的相关应用。简单工厂模式等。 <BR><BR>2、UML方面 <BR>答：标准建模语言UML。用例图,静态图(包括类图、对象图和包图),行为图,交互图(顺序图,合作图),实现图, <BR><BR>JavaScript方面 <BR><BR>1、如何校验数字型? <BR>var re=/^\d{1,8}$|\.\d{1,2}$/; <BR>var str=document.form1.all(i).value; <BR>var r=str.match(re); <BR>if (r==null) <BR>{ <BR>sign=-4; <BR>break; <BR>} <BR>else{ <BR>document.form1.all(i).value=parseFloat(str); <BR>} <BR><BR>CORBA方面 <BR><BR>1、CORBA是什么?用途是什么? <BR>答：CORBA 标准是公共对象请求代理结构(Common Object Request Broker Architecture)，由对象管理组织 (Object Management Group，缩写为 OMG)标准化。它的组成是接口定义语言(IDL), 语言绑定(binding:也译为联编)和允许应用程序间互操作的协议。 其目的为： <BR>用不同的程序设计语言书写 <BR>在不同的进程中运行 <BR>为不同的操作系统开发 <BR><BR>LINUX方面 <BR><BR>1、LINUX下线程，GDI类的解释。 <BR>答：LINUX实现的就是基于核心轻量级进程的"一对一"线程模型，一个线程实体对应一个核心轻量级进程，而线程之间的管理在核外函数库中实现。 <BR>GDI类为图像设备编程接口类库。 <BR>
<DIV class=post>
<DIV class=postTitle><A href="http://blog.csdn.net/jery_lee/archive/2004/10/24/149609.aspx"><FONT color=#000080>SCJP一些笔记&amp;&amp;局部类和嵌套类&amp;&amp;JAVA面试题&amp;&amp;XML区别</FONT></A> </DIV>
<DIV class=postText><SPAN id=ArticleContent1_ArticleContent1_lblContent>&nbsp; 
<P>1，初始化 <BR>类变量自动初始化为0或者null，局部变量使用前一定要初始化</P>
<P>2，主类型过载 <BR>类型匹配顺序：按照byte-&gt;short-&gt;char-&gt;int-&gt;long-&gt;float-&gt;double 顺序匹配。<BR>一种主类型只能匹配参数范围不小于其本身和其本身范围最接近的函数 <BR>即有int i;1.f(short s);2.f(long l);i只能适用于第2个f函数 <BR>如果是常数，则编译器作为int处理<BR>&nbsp;<BR>3，主类型计算结果的类型 和最大范围计算子的类型一致，但是最小也要是int，即byte+byte结果为int型。</P>
<P>4，short型和char型不能互相赋值（因为short有符号，char无符号） </P>
<P>5，package一定要放在java文件第一行（除注释空行外） </P>
<P>6，import只能放在第一行或者package下面 </P>
<P>7，多个import的package里面如果有同名class，使用时必须指定package </P>
<P>8，interface中只能有方法宣言和定数 </P>
<P>9，class实现interface必须实现全部方法 </P>
<P>10，同一java文件中class和interface只能有一个public </P>
<P>11，为了宣言定数，在变量前加final修饰子，变量不可改变，但是object的属性可以改变（有点忘记了，请确认，：）） </P>
<P>12，配列不能在宣言的时候用char arr[12]；形式指定，必须要用new指定大小。指定完毕后自动初期化；也可以new的时候用{0,0,0}形式指定 </P>
<P>13，如果一个object为null，使用其属性或者方法，产生NullPointerException </P>
<P>14，如果使用一个越界index访问配列，产生ArrayOfBoundsException</P>
<P>15，配列长用配列名.length </P>
<P>16，constructor如果有返回值，编译器作为一般方法看待 </P>
<P>17，constructor里面如果要用super(..)和this(..)，必须放在第一行，而且只能用一次 </P>
<P>18，如果没有显式调用super和this，编译器自动在第一行插入super();要求超类必须存在无参数的constructor </P>
<P>19，如果没有显式声明constructor，编译器自动生成默认无参数constructor。一旦声明，则无默认constructor </P>
<P>20，修饰子（访问范围大小顺序） <BR>public 完全公开 <BR>protected 同一package或者子类中无同一package <BR>private 本class </P>
<P>21，override的方法不能使访问范围缩小即父类中public方法不能被protected override<BR>&nbsp;<BR>22，static方法不能被override？确认 <BR>23，constructor不能被继承 </P>
<P>24，抽象class不能同时被static修饰子修饰<BR>&nbsp;<BR>25，native：方法被java以外其它语言实现 </P>
<P>26，interface里面： <BR>方法默认为public abstract修饰 <BR>变量默认为public static final修饰 </P>
<P>27，abstract和final，abstract和static，abstract和private不能同时指定 </P>
<P>28，&amp;&amp;，||为短路条件运算符 <BR>&amp;，|为不短路条件运算符 </P>
<P>29，switch()只能判断byte，short，int，char（long，float，double不行）<BR>&nbsp;<BR>30，Exception包括可check Exception和Runtime Exception可check Exception可以被编译器检查，Runtime Exception不被编译器检查，但是可以被catch捕捉 </P>
<P>31，try{}catch{}catch{}多个catch语句按照声明顺序检查，一旦被捕捉，以后catch就直接跳过，超类Exception可以捕捉子类Exception </P>
<P>32，try中即使有return，finally段也会被执行 </P>
<P>33，method声明用throws，抛出Exception用throw </P>
<P>34，强制垃圾回收，system.gc()；促使垃圾回收，但不是马上回收 </P>
<P>35，finalize()；在垃圾回收的时候自动调用；建议显式调用super.finalize()；<BR>&nbsp;<BR>36，main方法的args[0]是第一个参数，例如：java Test a b c，args[0]是"a"<BR>&nbsp;<BR>37，类中static段中不能throw异常，constructor里面不能throw异常 </P>
<P>38，对于除零：整数运算抛出ArithmeticException实数运算不抛出异常；返回Infinity或者-Infinity </P>
<P>39，instanceof运算子，is的意思，例如：betty instanceof girl，返回true，：）<BR>&nbsp;<BR>40，override和overload的区别 <BR>很简单，不多写了 </P>
<P>41，inner class（内部类：重点注意）<BR>nest class：class内部定义的class包括<BR>（member class：作为class的member定义的class <BR>local class：作为method局部变量定义的class <BR>anonymous class：用new生成的没有名字的class） </P>
<P>42，inner class：除了static member class以外的所有nest class总称 <BR>inner class中不能定义static段 <BR>inner class里面不能定义没有final修饰子修饰的static变量 <BR>inner class不能定义interface？（记不清了，自己确认一下） </P>
<P>43，member class的使用方法：TopClass.memberClass </P>
<P>44，static宣言的member class的生成方法： <BR>TopClass的instance.new memberClass()或者new TopClass.memberClass(); </P>
<P>45，local class不能显式被修饰子修饰 </P>
<P>46，local class只能存取被final修饰子修饰的上级变量（注意） </P>
<P>47，anonymous class instance生成方法： <BR>new SuperClass名(){.......}或者 <BR>new Interface名(){......} </P>
<P>48，anonymous class <BR>不能定义sub class（因为自己没有名字） <BR>不能定义为abstract class <BR>不能定义constructor（注意） </P>
<P>49，Thread生成方法 <BR>继承java.lang.Thread <BR>实现java.lang.Runnable interface，然后用new Thread(实现Runnable接口的class)来生成Thread instance </P>
<P>50，Thread的join方法，等待Thread结束 </P>
<P>51，Object的wait()方法和notify()，notifyAll()方法（线程同期化，自己好好看看） </P>
<P>52，同期化保留字:synchronized（有可能要求拼写） </P>
<P>53，如果用synchronized修饰static方法，static写在前头 </P>
<P>54，String和StringBuffer区别：String初始化后不可改变，StringBuffer可以改变 <BR>String s1="hello";<BR>String s2="hello"; <BR>if (s1==s2){System.out.println("OK");} <BR>执行结果是打印出OK </P>
<P>55, &gt;&gt;&gt;运算符高位填0，是为逻辑移位 <BR><BR><BR></P>
<DIV class=postbody>
<P><STRONG><FONT class=title color=#ff0000>局部类和嵌套类</FONT></STRONG></P>
<P>局部类<BR><BR>　　在一个函数体内定义的类称为局部类。局部类中只能使用它的外围作用域中的对象和函数进行联系，因为外围作用域中的变量与该局部类的对象无关。在定义局部类时需要注意：局部类中不能说明静态成员函数，并且所有成员函数都必须定义在类体内。在实践中，局部类是很少使用的。下面是一个局部类的例子。<BR><BR>int a;<BR>void fun()<BR>{<BR>　　static int s;<BR>　　class A<BR>　　　{<BR>　　　　public:<BR>　　　　　void init(int i) { s = i; }<BR>　　　　};<BR>　　A m;<BR>　　m.init(10);<BR>}<BR><BR><BR>　　嵌套类<BR><BR>　　在一个类中定义的类称为嵌套类，定义嵌套类的类称为外围类。<BR><BR>　　定义嵌套类的目的在于隐藏类名，减少全局的标识符，从而限制用户能否使用该类建立对象。这样可以提高类的抽象能力，并且强调了两个类(外围类和嵌套类)之间的主从关系。下面是一个嵌套类的例子：<BR><BR>class A<BR>{<BR>　public:<BR>　class B<BR>　　{　<BR>　　　public:<BR>　　　　…<BR>　　　private:<BR>　　　　…<BR>　　};<BR>　void f();<BR>　private:<BR>　int a;<BR>}<BR><BR><BR>　　其中，类B是一个嵌套类，类A是外围类，类B定义在类A的类体内。<BR><BR>　　对嵌套类的若干说明：<BR><BR>　　1、从作用域的角度看，嵌套类被隐藏在外围类之中，该类名只能在外围类中使用。如果在外围类的作用域内使用该类名时，需要加名字限定。<BR><BR>　　2、从访问权限的角度来看，嵌套类名与它的外围类的对象成员名具有相同的访问权限规则。不能访问嵌套类的对象中的私有成员函数，也不能对外围类的私有部分中的嵌套类建立对象。<BR><BR>　　3、嵌套类中的成员函数可以在它的类体外定义。<BR><BR>　　4、嵌套类中说明的成员不是外围类中对象的成员，反之亦然。嵌套类的成员函数对外围类的成员没有访问权，反之亦然。国此，在分析嵌套类与外围类的成员访问关系时，往往把嵌套类看作非嵌套类来处理。这样，上述的嵌套类可写成如下格式：<BR><BR>class A<BR>{<BR>　public:<BR>　void f();<BR>　private:<BR>　int a;<BR>　};<BR><BR>class B<BR>{<BR>　public:<BR>　　…<BR>　private:<BR>　　…<BR>};<BR><BR><BR>　　由引可见，嵌套类仅仅是语法上的嵌入。<BR><BR>　　5、在嵌套类中说明的友元对外围类的成员没有访问权。<BR><BR>　　6、如果嵌套类比较复杂，可以只在外围类中对嵌套类进行说明，关于嵌套的详细的内容可在外围类体外的文件域中进行定义。<BR></P></DIV></SPAN></DIV>
<DIV class=postFoot>&nbsp;</DIV></DIV><LINK href="http://blog.csdn.net/jery_lee/Services/Pingback.aspx" rel=pingback><!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
<rdf:Description
rdf:about="http://blog.csdn.net/jery_lee/archive/2004/10/24/149609.aspx"
dc:identifier="http://blog.csdn.net/jery_lee/archive/2004/10/24/149609.aspx"
dc:title="SCJP一些笔记&&局部类和嵌套类&&JAVA面试题&&XML区别"
trackback:ping="http://blog.csdn.net/jery_lee/services/trackbacks/149609.aspx" />
</rdf:RDF>
--><BR>
<DIV id=comments>
<H3></H3>
<DIV class=post>
<DIV class=postTitle>&nbsp;&nbsp;</DIV>
<DIV class=postText>个人在国内做IT已经有五年了，我从事JAVA也有三年了，有一些个人在面试后的对面试问题总结，在些写出来： <BR>1.J2EE是什么？ <BR><BR>2.介绍JAVA中的Collection FrameWork(包括如何写自己的数据结构)? <BR><BR>如COLLECTION中遗留类(HASHTABLE、VECTOR)和现有类的区别？(同步) <BR><BR>3.Java中异常处理机制，事件机制？ <BR><BR>　 <BR><BR>4.EJB与JAVA BEAN的区别？ <BR><BR>EJB与JAVA BEAN是SUN的不同组件规范，EJB是在容器中运行的，分步式的，而JAVA BEAN主要是一种可利用的组件，主要在客户端UI表现上。 <BR><BR>5.JAVA中的多形与继承？ <BR><BR>可出编程，选择题。 <BR><BR>6.抽象类与接口？ <BR><BR>接口的好处是将实现与表现分离。 <BR><BR>抽象类与接口都用于抽象，但是抽象类(JAVA中)可以有自己的部分实现，而接口则完全是一个标识(同时有多重继承的功能)。 <BR><BR>　 <BR><BR>7.Java 的通信编程，编程题(或问答)，用JAVA SOCKET编程，读服务器几个字符，再写入本地显示？ <BR><BR>　 <BR><BR>8.JAVA SERVLET API中forward() 与redirect()的区别？ <BR><BR>forward()方法可以使用原来的对象，而且速度较快。 <BR><BR>9.JAVA解析XML的方式？ <BR><BR>SAX、DOM <BR><BR><BR><BR>10.用JAVA实现数据库查询，这是一道编程题。 <BR><BR>基本操作，不用讲了。 <BR><BR>11.用JAVA实现一种排序 ，比较，JAVA类实现序列化的方法(二种)？ <BR><BR>如在COLLECTION框架中，实现比较要实现什么样的接口。 <BR><BR>12.JSP中动态INCLUDE与静态INCLUDE的区别？ <BR><BR>老一套，动态可以带参数，静态相当于一段静态HTML文件。 <BR><BR>　 <BR><BR>13.应用服务器与WEB SERVER的区别？ <BR><BR>　 <BR><BR>14.设计模式与UML方面。 <BR><BR>如工厂模式，解决多数据库支持问题。 <BR><BR>15。 编程：编写一个截取字符串的函数，输入为一个字符串和字节数，输出为按字节截取的字符串。 <BR><BR>但是要保证汉字不被截半个，如“我ABC”4，应该截为“我AB”，输入“我ABC汉DEF”，6，应该输出为“我ABC”而不是“我ABC+汉的半个”。 <BR><BR>16。在ORACLE大数据量下的分页解决方法。 一般用截取ID方法，还有是三层嵌套方法。 <BR><BR>17。WEB SERVICE名词解释。JSWDL开发包的介绍。JAXP、JAXM的解释。SOAP、UDDI解释。 <BR><BR>18。BS与CS的联系与区别。 <BR><BR>19。LINUX下线程，GDI类的解释。 <BR><BR>20。JAVA多线程编程。 <BR><BR>用JAVA写一个多线程程序，如写四个线程，二个加1，二个对一个变量减一，输出。 <BR><BR>21。JAVA的基本功： STRING与STRINGBUFFER的区别。 <BR><BR>22。STRUTS的应用(如STRUTS架构) <BR><BR>
<DIV class=postText>一、DOM （文档对象模型） <BR>为 XML 文档的已解析版本定义了一组接口。解析器读入整个文档，然后构建一个驻留内存的树结构，然后代码就可以使用 DOM 接口来操作这个树结构。 <BR>优点：整个文档树在内存中，便于操作；支持删除、修改、重新排列等多种功能； <BR>缺点：将整个文档调入内存（包括无用的节点），浪费时间和空间； <BR>使用场合：一旦解析了文档还需多次访问这些数据； <BR>硬件资源充足（内存、CPU） <BR><BR>二、SAX <BR>为解决DOM的问题，出现了SAX。 <BR>SAX ，事件驱动。当解析器发现元素开始、元素结束、文本、文档的开始或结束等时，发送事件，程序员编写响应这些事件的代码，保存数据。 <BR>优点：不用事先调入整个文档，占用资源少； <BR>SAX解析器代码比DOM解析器代码小，适于Applet，下载 <BR>缺点：不是持久的；事件过后，若没保存数据，那么数据就丢了； <BR>无状态性；从事件中只能得到文本，但不知该文本属于哪个元素； <BR>使用场合：Applet; <BR>只需XML文档的少量内容，很少回头访问； <BR>机器内存少； <BR><BR>三、JDOM <BR>为减少DOM、SAX的编码量，出现了JDOM； <BR>优点：20-80原则，极大减少了代码量 <BR>使用场合：要实现的功能简单，如解析、创建等 <BR>Java程序 <BR><BR>但在底层，JDOM还是使用SAX（最常用）、DOM、Xanan <BR><BR>四、JAPX <BR>为多个XML解析器提供了统一编程接口 <BR>更换解析器，不用更改代码 <BR>使用场合：若不用Jdom，一般建议使用JAPX，将代码与各种解析器的实现细节隔离。 <BR>
<DIV class=postText>16。在ORACLE大数据量下的分页解决方法。 一般用截取ID方法，还有是三层嵌套方法。 <BR><BR>select * from ( select row_.*, rownum rownum_ from (sql) row_ where rownum &lt;= ?) where rownum_ &gt; ? <BR>
<DIV class=postText><FONT color=#000000><FONT size=2>一些著名的大公司面试题目往往很基础.</FONT> </FONT>
<P><FONT color=#000000 size=2>一、Java基础知识<BR>1. Java有那些基本数据类型，String是不是基本数据类型，他们有何区别。<BR></FONT><FONT color=#000000 size=2>&nbsp;Integer literals,Floating-point literals,character literals,Boolean literal,String iteral.<BR>&nbsp;String 不是基本数据类型<BR>2. 字符串的操作：<BR>写一个方法，实现字符串的反转，如：输入abc，输出cba<BR></FONT><FONT color=#000000 size=2>&nbsp;&nbsp;&nbsp; public static String reverse(String s){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int length=s.length();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StringBuffer result=new StringBuffer(length);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=length-1;i&gt;=0;i--)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result.append(s.charAt(i));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return result.toString();<BR>&nbsp;&nbsp;&nbsp; }<BR>写一个方法，实现字符串的替换，如：输入bbbwlirbbb，输出bbbhhtccc。<BR>3. 数据类型之间的转换<BR>如何将数值型字符转换为数字（Integer，Double）<BR>如何将数字转换为字符<BR>如何去小数点前两位，并四舍五入。<BR>4. 日期和时间<BR>如何取得年月日，小时分秒<BR></FONT><FONT color=#000000 size=2>Date dat=new Date();<BR>dat.getYear();dat.getMonth();dat.getDay();dat.getHours();...<BR>如何取得从1970年到现在的毫秒数<BR>long now=dat.getTime();<BR>如何获取某个日期是当月的最后一天<BR>如何格式化日期<BR></FONT><FONT color=#000000 size=2>DateFormate df=DateFormate.getInstance();<BR>df.Format(dat);<BR>5. 数组和集合<BR>6. 文件和目录（I/O）操作<BR>如何列出某个目录下的所有文件<BR>如何列出某个目录下的所有子目录<BR>判断一个文件或目录是否存在<BR>如何读写文件<BR>7. Java多态的实现（继承、重载、覆盖）<BR>8. 编码转换，怎样实现将GB2312编码的字符串转换为ISO-8859-1编码的字符串。<BR>9. Java中访问数据库的步骤，Statement和PreparedStatement之间的区别。<BR>10. 找出下列代码可能存在的错误，并说明原因：<BR>二、JSP&amp;Servlet技术<BR>1. 描述JSP和Servlet的区别、共同点、各自应用的范围<BR>2. 在Web开发中需要处理HTML标记时，应做什么样的处理，要筛选那些字符（&lt; &gt; &amp; “”）<BR>3. 在JSP中如何读取客户端的请求，如何访问CGI变量，如何确定某个Jsp文件的真实路径。<BR>4. 描述Cookie和Session的作用，区别和各自的应用范围，Session工作原理。<BR>5. 列出Jsp中包含外部文件的方式，两者有何区别。<BR>6. 说明Jsp中errorPage的作用，应用范围。<BR>7. 介绍在Jsp中如何使用JavaBeans。<BR>8. 简单介绍JSP的标记库<BR>9. Jsp和Servlet中的请求转发分别如何实现。<BR>三、J2EE相关知识<BR>1. 介绍J2EE、J2SE、J2SE的区别。<BR>2. J2EE是一种技术还是一种平台，他提供了那些技术。<BR>3. 什么是Application Server，它有什么功能和优点。<BR>4. 简单介绍连接池的优点和原理。<BR>5. Web.xml的作用<BR>四、其他<BR>1. Web安全性的考虑（表单验证、浏览器Basic方式的验证，应用程序的安全性，SSL，代码考虑）<BR>2. 简单介绍您所了解的MVC。<BR>3. 简单介绍所了解的XML。<BR>4. 文档和编码规范<BR>5. Java中的分页、效率考虑。<BR>6. 简单介绍您所了解的structs。</FONT></P>
<P><BR><FONT color=#000000 size=2>找出以下程序错误。<BR>Class Test{<BR>&nbsp;&nbsp;&nbsp; private String par1;<BR>&nbsp;&nbsp;&nbsp; private String par2;<BR>&nbsp;&nbsp;&nbsp; Test(){<BR>&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp; public static void main(String[] arg){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int a ;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(a){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("par1="+par1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("par2=" + par2);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR>}</FONT></P></DIV></DIV></DIV></DIV></DIV></DIV><img src ="http://www.blogjava.net/caid/aggbug/31217.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caid/" target="_blank">caid'weblog</a> 2006-02-17 16:17 <a href="http://www.blogjava.net/caid/archive/2006/02/17/31217.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【转载 王森】程序设计师真情忏悔录 </title><link>http://www.blogjava.net/caid/archive/2006/02/17/31216.html</link><dc:creator>caid'weblog</dc:creator><author>caid'weblog</author><pubDate>Fri, 17 Feb 2006 08:13:00 GMT</pubDate><guid>http://www.blogjava.net/caid/archive/2006/02/17/31216.html</guid><wfw:comment>http://www.blogjava.net/caid/comments/31216.html</wfw:comment><comments>http://www.blogjava.net/caid/archive/2006/02/17/31216.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caid/comments/commentRss/31216.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caid/services/trackbacks/31216.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不久前,蔡学庸先生发表了两篇分别叫做"程序与香鸡排"，"再论香鸡排"的文章，受到的回响之大，据说连作者本人都接到该文的转寄。足以见得该文的内容道出了台湾程序设计师心里最深处的想法。所以,本文想针对台湾程序设计师来做讨论，看看身为一个程序设计师，究竟犯了什么过错，导致大家宁愿卖鸡排也不愿再继续写程序。璩美凤小姐为自己惊动台湾社会的行为写了真情忏悔录,我们也该真诚地检讨一下自己。 <BR><BR>本文: <BR>在台湾，大部分的人都有个认知，就是"搞硬件的比搞软件的要好赚"，"做SA/SD比coding地位要高"。那些做ID Design的家伙待的公司所发的股票，永远比搞Software Design的人待的公司发的还多，股价也高出好几倍。搞SA/SD的人，在公司地位好象也比单纯写程序的人高。于是我的父亲有一次问我:"是不是搞硬件的人智商比较高?"，"是不是搞分析设计的人比较有地位?" <BR><BR>事实上，在学生时期我就认识不少人，有的人因为程序写不过别人，所以转换跑道专攻硬件;也有人觉得每天面对示波器和逻辑分析仪让他们头痛，工程数学也学不过人家，所以转行搞软件。到了实际上面对许多前来接受教育训练的学员之后，发现有人是因为写了十几年BIOS和driver，觉得乏味而没有前途，所以想试看看应用程序的开发;有人则是因为受不了客户每天改需求，而且写IOS和driver的人好象比较少，价格比较高，因此想学习如何撰写系统软件。询问那些上高阶课程的朋友，有的人发现自己只会胡做SA/SD唬烂老板和客户，所以希望重新打好基础，从基本的coding做起;有的人则因为写程序写太久，觉得应该往上走向SA/SD的路子，毕竟老了程序就写不动了。这个世界上什么样的人都有，绝对不能以小羡大。就很像搞政治的老是骗我们台湾只分成外省人和本省人;搞帮派的人告诉我们警察是带着枪的流氓。实际上，每个族群大家在没有被分化之前都相处的和乐融融，而虽然有警察掳勒索，上班时间跑去聚赌,但是也有开我们罚单时酌情轻罚的警察，和保护我们身家性命的警察。 <BR><BR>即使如此，身为一个程序设计师还是要问，那为什么写程序的好象地位就是比较低? 笔者认为，这是进入门槛的问题。会做相同事情的人多了，就会削弱那样技能的价值。就很像考过MCSE/MCSD证照的人，通常比起考过SCJP/SCJD证照的人要来的没价值，前者因为考过的人实在太多，而后者考过的人少，仅是如此而已。但是绝不是代表考过MCSE的人，素质就比考过SCJP的人要差，也不代表考过SCJP的人，实力真的比较高段。相信求学的时候您一定遇过一种人，他实力也不怎样样，可是考试的时候他x的就是考的比我们高，怎么我们心里就是不服，可是大多数老师偏偏就是比较喜欢分数高的人。因此，满坑满谷的人自称会写程序，老板不愁找不到可以做project的人，你要求的薪水和价格很高? 没关系，找个学校刚毕业的小子，写的比你快，写的比你好，用的技术比你新，更重要的，价格比你这个老屁股便宜一半。所以程序设计师在雇主心中的地位日益低落，自然有迹可循。 <BR><BR>"那么，为什么写程序的进入门槛比较低?" <BR><BR>在各位信息从业人员的身边，非科班出生的比率非常高(当然没还卖鸡排的高)，科班出生的学生，搞不好在老板眼中的地位，还比不上一个半路出家的自学者。那位自学者会ASP、JSP、PHP、C++、C+、Java、Linux、Windows、Oracle...等，十八般武艺样样精通。而我们科班出生的学生，只会离散数学、数据结构和算法，Visual Basic搞不好没有用的没人家熟，网站的架设搞不好也没人家熟，更何况科班出生的学生，他的基础学问搞不好根基也不扎实(问看看您身旁的科班学生)，难怪最常见的就是很多非科班的"高手"看不起科班的学生，觉得他们无三小路用，连个Windows操作都比他们差，甚至有的还大言不惭的说:"我这辈子写程序从没用过书上的数据结构和演算法，读那些干啥?"。 长期下来，科班的学生也开始质疑自己的所学，甚至考虑转行，当然，也有曲高和寡，孤芳自赏之人。 总之，没办法受到老板垂青，薪水永远那么少，想卖鸡排的念头就开始萌生。 <BR><BR>之所以会有这种情况，笔者个人认为有两种主要原因，一是技术的流通性，二是台湾软件市场的需求。为什么技术的流通性可以产生大量半路出家的非科班生? 这都要感谢台湾大量作者，写出大量的入门书籍，大幅减低的进入程序设计领域的门槛。即使在各位眼中，繁体中文的烂书很多，而且非常。但是，大家眼中的烂书，常常是再版多次的入门书，对某些人认为是垃圾的东西，常常是另外一批人进入信息业的最佳踏脚石。不信各位到书店看看，是"24小时学C++"、"快快乐乐学Java"的书比较多，还是"轻轻松松学微分方程式"、"21天学复变"、"电子学不求人"的书多? 两者的差距是 N:0。是微分方程序和复变比++,Java难学吗?笔者两个都学过，至少我可以发誓，就一个有基本学习能力的人来说，难度是一样的，学成所需要的时间和功夫也是一样的。再看我们的公开讨论区(BBS或Forum)，我们可以看到大量的软件技术讨论区，却看不到硬件技术讨论区(喔,请别跟笔者说那些每天问哪家主机板比较好，哪台烧录器较稳定、或者说CPU时脉越高速度就越快越好，或是说x86的Out-Of-Order Executon是"故障执行" 这一类浑话的讨论区和我说的硬件技术讨论区是一样的喔!)书籍和讨论区促进知识的流通,造成了大量的软件人才,更何况,学习设计软件只要一台PC就能写出好用的软件，而学习硬件设计，需要的设备更是天价。 <BR>更重要的一点，就是学软件的人，充分发挥儒家分享的精神，只要不是在BBS上冒充小妹妹想要骗取大哥哥的同情来帮你写程序作业，只要不是很差劲的乱问一通，通常至少会有热心人士愿意留下一个URL，让我们可以找到参考文件，更具热诚的，如新竹师院BBS站Java版的TAHO先生，还擅用很多生动的比喻让初学者体会技术的真义。在这种知识充分流通的环境下，当然产生出非常多的信息从业人员，每买一台PC，上头各种软件的需求是无穷无尽的，每天都有各行各业的人需要各种软件，所以程序设计师的需求有一定的量。难怪有人说:"写程式的人饿不死,但是也不会发大财。" <BR><BR>再来就是台湾软件市场需求所引发的问题.一般我们把软件分成系统软件(System Software)和应用软件(Application Software). 编译器,组译器,除错器,操作系统,驱动程序,都是属于系统软件的一部分. <BR><BR>台湾除了硬件厂商,IC Design House之外,甚少有撰写驱动程序的需求. <BR>前几年Linux被炒的热时,也有许多高手投入操作系统,编译器以及简化标准函式库的研究.而台湾所需求的软件,极大多数是属于应用软件,这些需求的应用软件其中很大比例是和数据库有关系的(其实不只是台湾,其它地方也是约略相同的情形).所以VB,Delphi和PowerBuilder这类IDE大行其道,因为他们容易上手,可以快速开发数据库应用程序,相关入门书籍很多,会的人更多. 因此符合我们前面所说的:"会的人越多,价值就越低"的理论. <BR><BR>但是别忘了,系统软件有部分是偏向应用软件的,比方说开发软件用的JBuildr和Visual Studio;制图用的AutoCAD;一套IC Design用的Xilinx或Altera;做OOA/OOD的Rational Rose和TogetherJ,笔者习惯称这些软件叫做"软件的软件"(Meta Software). <BR><BR>在一般程序设计师眼中,这类软件"理所当然"地认为都是由国外所发展. <BR>这类软件有极高的进入门槛,所以国外这类软件公司的获利率很高,所以该公司的程序设计师可是身价非凡. 要知道,先前在媒体上有报导过,能够让Microsoft买软件来用的公司,只有Rational Rose(当然,不可能只买Rose来用). 如果做IC Design的人没有你的软件就没办法做事,身为一个程序设计师,你会觉得你的身价和地位比做IC Design的人低吗? 如果你做的软体像SoftICE或DriverWorks那样被做硬件的工程师大量地倚赖,你会觉得搞硬件的人比你厉害吗? <BR><BR>问题是,知道该如何设计一套这类软件的人,恐怕才是真正的异数. 而且需要跨领域的专才.要不是许多OpenSource的project(例如:KDeveloper)正在进行,恐怕很少人知道该如何设计一套IDE. 既然会制作这类软件的人在国内少之又少,那么他们的身价高吗? <BR><BR>很抱歉,台湾没有公司发展出足以和国外大厂竞争的开发工具. 举IDE为例,国内早期有家公司开发出一套名为DBtools的产品勉强可以算的上是这类产品, <BR>旗标也曾为它出版过入门手册,可是使用这套软件的人好象...没看过(如果该产品有不错的占有率,请原谅我是井底之蛙),没有市场,公司无法赚钱,即使你是少数能做制作某类型产品的高手,公司最后关门大吉了,您也只能算是"少数能让公司赔钱的程序设计师"罢了.所以我大胆假设, Games Golsing或Anders Hejlsberg如果学李敖一样50年不离开这个小岛,大概早饿死了. <BR><BR>以上的讨论,真正优秀的高手看了之后,或许会产生有时不我予,不得已必须远渡他乡的想法. 程序设计师的价值就如同书的价值一般,国内和国外有不同的看法.国内教科书比较便宜,应用的书比较贵.国外教科书比较贵,应用的书比较便宜. 国外重内容,薄薄一本How Debuger Work可以卖44.99美金.而国内,都是看页数来计价(侯俊杰先生的书有努力在打破这个页数的迷思,也做的蛮成功).有很多原因导致这两种文化之间的差异,但是,市场因素肯定是其中重要的一项. <BR><BR>好了,程序设计师价值低落的原因讨论过了,如果您同意笔者的论点,那么不禁疑惑,大家彼此毫不保留地让知识得以流通,技术得以扩散,本意是好的,结果反到造成自己和别人身价的低落,这样我们是不是从此不再和别人分享我们的心得? <BR><BR>王森:程序设计师真情忏悔录(下) <BR>(2002.03.28) <BR>所以从今天开始,如果你对程序设计有一股热爱,那么我们一起努力,做个真正的程序设计师,而不要做一个杂碎且破坏别人行情的程序设计师.做一个真正写的出有用软件的工程师,不要做一个只会写程序的程序设计师.当然,如"意外的计算机王国 / 联经出版社"一书所言,很多技术都是用来原本没有预料到的地方而大行其道.许多科学研究无法有立即的贡献,但是影响深远,我们也期许有意从事基础研究的科班研究生,认真的作研究,不要老是研究一些别人已经研究过的研究,不要老是冀望骗国科会等研究机构的经费,到了最后计划结案时,才匆匆忙忙交出另外一篇骗更多钱的计划书,或是拿不出台面的研究. <BR><BR>最后,我们反省自己是不是也是一个只会"写程序"的程序设计师呢? 请自行测验底下几个问题,这些问题都不可能有客观的答案,所以每个问题都附上笔者主观的答案,作为笔者自己的反省. <BR><BR>Q1: 你尊重专门技术吗? 换句话说,你认为术业有专攻吗? <BR><BR>当你接受外面的教育训练课程时,你总是崇拜看起来什么都懂的老师? <BR><BR>换句话说,你认为那些遇到课外问题就跟你说他不懂的讲师是烂老师? <BR><BR>你老觉得真正的高手应该精通各门各派的技术,如果你会XML,他不会,你就觉得你比他厉害.你觉得他的履历上写的技能太少,证照太少,所以你认为你比他优秀? <BR><BR>有人老是觉得自己蛮会用MFC开发软件,所以直觉认为那些只喜欢,或是只会用VB的人程度应该不高.问题是,有人用VB的程度是,当他觉得组件不好用,所以自己写程序处理HTTP,因为他懂HTTP协议的运作方式.组件盘里附的浏览器组件太烂,就自己用公认语法不是很顶尖的Basic语言来写parser. <BR><BR>相反的,有人号称会用MFC,但是除了靠Help找出名为Cxxxxx的类别来用,再 <BR><BR>自己补上事件处理的部分之外,其它什么事都做不出来. <BR><BR>有人认为写Java程序应该善用工具,用UltraEdit根本是重新造轮子的行为,所以一开始就学JBuilder的使用,其实他用JBuilder写了老半天GUI程序,哪天回头叫他用文字编辑器写个简单的Frame + Button, 他却写不出来,因为他从没弄懂过Java的事件处理模型. 他只会不断地: 选择组件-&gt;放在容器里头-&gt;调整位置和大小-&gt;调整属性-&gt;按两下-&gt;填写事件处理函式,成为一个名副其实的"程序女工". <BR><BR>有人觉得他精通各家厂商的数据库,所以看不起那些只会下SQL指令或是只会写store procedure的人, 因为这个人精通ODBC, JDBC, ADO, ADO.NET各种程序的写法.问题是,一个精通SQL的专家和只会写SQL指令的人,在数据库表格交互参考,资料量很大的时候,要从中取出我们需要的资料, <BR><BR>所下的指令在效率上是几秒钟和几个小时的差别. SQL也是个专门学问,要能够巧妙的操作它,必须下非常多功夫做研究,而且一研究可能就是十几年才有办法累积丰富的经验. 如果贵公司的项目老是苦于数据库存取的效能不够,你猜老板会花钱找一个有能力彻底改善所有SQL命令之中效能问题的稀有专家,还是再找一个号称他什么都会,结果一点用场也派不上的"数据库女工" ? <BR><BR>我们常常看到某人列出他的履历,好象会很多就是很厉害.但是当我们完全深入一项技术时(喔,我是说你真正下工夫的时候),通常我们会越来越感觉到自己的渺小. <BR><BR>蔡学镛先生就是一个非常尊重专业技术的例子.我们看到他在 <A href="http://www.csdn.net/expert/cxy" target=_blank><FONT color=#000080>www.csdn.net/expert/cxy</FONT></A>/ 上写的,他说他只精通 lots of Java APIs.我和学镛聊过三次,有一次,我听他说:"干麻叫我搞Linux,我又不懂Linux!" 如果是你听到这句话,你会不会真的以为他玩起Linux来肯定比你逊色? <BR><BR>笔者突然想起神雕侠侣里头的独孤求败,晚年只会拿树枝和别人比武,可是你拿再厉害的刀剑就是无法打败他.所以,请尊重专业技术,不要以为人家没说他会,你就比他厉害.真正厉害的人很多都不在台面上,而是躲在后面偷偷笑我们呢! 而我们一辈子永远不知道我们被别人偷偷取笑了.中国文化数千年来都是文人相轻的历史,够了,大家尊重专业吧! <BR><BR>Q2: 你觉得算法和数据结构无三小路用,因为你从没使用过? <BR><BR>我们承认"无招胜有招"是内功心法的最高境界,但是在信手拈来之际,后面所代表的是对各家武功路数的彻底了解.由于台湾几乎只有应用软件的开发需求,没有系统软件的需求,所以大多数的程序设计师都是站在"程序女工"的角度看世界,只要有钱,只要有人贩售组件,有什么搞不定的. 但是今天如果你想设计一个XML parser,不懂数据结构和算法可以吗? <BR><BR>好吧! 你说我们不该重新造轮子,我们应该站在巨人的肩膀上看世界,如果什么都自己硬干,世界是会退步的. 那么试问,当你在使用Java提供的Collection Framework时,你了解ArrayList, LinkedList, TreeSet, HashSet之间的差别吗? 你知道他们的优缺点吗? 你知道他的特性吗? 不了解ArrayList和LinkedList的差异,用哪种去写程序执行结果都一样,可是效率差很多. <BR><BR>大多数的人连了解特性都谈不上,更别说很多每天想发展自己的语言,自己的编译器,自己的操作系统的人,没有基础学问的了解,如何去设计一个Collection Framework或STL?你说数据结构和算法没有用,你去做看看现在IDE中普遍有的code insight功能看看?以Borland C++ Builder来说,要在短时间内搜寻所有的标头文件并找出某函数的prototype,如果没有对数据结构和算法有充分了解,一样做的出来,只是产品会卖不出去罢了. <BR><BR>我在课堂上常常举一个scalability的例子给学生看: <BR><BR>我希望写一个1+2+3 ... + 100的程序,大多数的人都是写 <BR><BR>int sum = 0 ; <BR><BR>for(int i = 1 ; i &lt; 101 ; i++) <BR><BR>sum = sum + i ; <BR><BR>而真正受到数学观念熏陶的人会写成 <BR><BR>int sum = 100(100+1) / 2 <BR><BR>前者的复杂度是O(n),后者是O(1),当项数很多时,运算时间是不是差很多? <BR><BR>这些都是我们的教育所产生的问题(当然笔者也是其中一位受害者),老师只叫你写好作业,助教只叫你run出正确的结果,认真一点的还会测试你是不是抄来的. 却从来没告诉你程序中不能只有一个main函式,程序代码不能第一行写到第一千行从不切割成其它子程序. 你的程序代码看起来不堪入目,老师助教从没告诉你,你的.class檔被decompiler反编译之后,长的比你写的还漂亮. <BR><BR>但是从今天开始,我们可以开始认真思考每行程序,不要再做一个杂碎程序设计师. <BR><BR>试想发展MP3算法的人和写WinAmp的人,哪个比较厉害? 你会说都很厉害,可是没有前者就没有后者,前者搞不好还可以坐收权利金,后者只能苦哈哈的赚些小钱或等人购并. 我们停留在崇拜应用程序技巧的阶段,而真正值得崇拜的是那些难得一见的创意. <BR><BR>笔者遇过一个朋友,叫他撰写一个费式数列的小程序,比请他写一个可以浏览数据库表格内容的程序还难.(请不要与我讨论费式数列的小程序没有实用价值的问题,这里讨论的重点不是这个)前者需要稍微动点小脑筋,后者只要会拖拖组件,设定property就搞定. RAD本身不是罪,但是没学好九阳神功就妄想几小时练成乾坤大挪移.最后只会走火入魔而死,彻底变成一个"程序女工". <BR><BR>Q3: 你常常以科班和或非科班自居? <BR><BR>你是科班生,瞧不起非科班生? 因为你是正统? <BR><BR>你是非科班生,瞧不起科班生? 因为你觉得会的东西比科班生的还多. <BR><BR>烂学校会出现好学生,好学校也会有烂学生. <BR><BR>因为比例一样多,所以我们不能以偏概全. <BR><BR>如果仗着受过几年正规教育,自己又从未好好深入学习,就自己为是正统,比较学术的说法这叫做"阳具文化".有些创新的idea是一般制式脑袋的科班学生很难想出来的,因为专家是训练有素的狗. <BR><BR>如果你是学电信的朋友,你发现交换机是一个葬仪社的老板因为生意被别人抢走而发明的,那你会不会气死? <BR><BR>如果自学有成的程序设计师仗着自己会的东西比较多,你说你精通Java的各种技术,你看不起从没写过JSP的科班学生. <BR><BR>但是有人告诉你发展Java的Games Golsing博士是一个正统出生的科班生,知道了这件事情,会不会让你更加尊重幕后认真打拼的科班生? <BR><BR>Q4: 你是学计算器科学的,可是逻辑能力并没有比较好,还常常受骗? <BR><BR>你会被潮流所鼓动吗? 你常常被别人的思考牵着走? <BR><BR>人家鼓吹Linux多好多好,你的脑袋连转都没转过就发愤努力地考Linux认证 ? <BR><BR>------------------------------------------------------------------- <BR><BR>别人把公司里的server全换成Linux,客户端也都改成Linux,公司仍然正常地运作,结果你学了Linux之后,看到电视上BSA同法务部做的广告仍然吓的你冷汗直留. <BR><BR>深怕明天去住套房. <BR><BR>Sun跟你说Java跨平台,你没试过也跟人家说跨平台的优点? <BR><BR>--------------------------------------------------- <BR><BR>Borland已经可以做到一份光盘里同时附上Solaris, Linux, Windows, MacOS X的JBuilder, <BR><BR>你却为了EJB无法deploy到不同公司的Application Server忙的像无头苍蝇. <BR><BR>之前一窝峰人鼓吹XML,结果你盲目追求流行,做出来的东西tag比data还多? <BR><BR>----------------------------------------------------------------- <BR><BR>会用的人彻底了改变了公司里资料交换的流程,而你整天只会SAX来,DOM去的写XML数据库(用XML来储存资料的数据库) <BR><BR>微软的广告告诉你XP和IE将不支持Java,你都还没试过就跟别人嚷嚷Java已死? <BR><BR>-------------------------------------------------------------------- <BR><BR>套句BBS上moga先生的名言:"那我现在在Windows 2000上跑的Java程序是神迹?" <BR><BR>现在一票人每天宣传web service的好处,你连想都没想过就急着想要把公司的旧系统全部改成web service来做,结果浪费一堆钱,糟糕的速度让你每天被客户臭骂 ? <BR><BR>---------------------------------------------------------------------- <BR><BR>Web service当然是美好的前景,但是并非适用于每个角落,目前世界上并不存在完美的solution. <BR><BR>人家说不能写程序一辈子,写程序的人生命周期很短,你也跟着别人开始往SA/SD前进 ? <BR><BR>--------------------------------------------------------------------------- <BR><BR>如果世界上每个工程师都可以经由经验就成为优秀的SA/SD人员,那么理论上咱们应该有些象样的软件产品才对. 有些人写了几十年, <BR><BR>还是一个优秀的程序设计师,你问问他,如果没有遇到糟糕的老板, <BR><BR>糟糕的待遇和糟糕的制度,他愿不愿意写一辈子程序? 我愿意. <BR><BR>顾问告诉你要多用RAD,不该重新造轮子,所以你努力的问how而不问why ? <BR><BR>--------------------------------------------------------------- <BR><BR>结果真正赚到钱的都是那些像JReport做软件组件的软件公司. <BR><BR>微软说J2EE Blueprint的Pet Store,用.NET技术做比用J2EE做还要快许多,然后你就相信了,最近, IBM和Oracle重新加强Java版的Pet Store,让它比.NET版的还要快18%~22%,你又改口说Java比较好. <BR><BR>-------------------------------------------------------------------------------------------- <BR><BR>一个系统在设计的时候有很多考量,有人以扩充性为主,有的以安全性为主,有人以效能为主. <BR><BR>如果没有设计理念,大家程序里头的function全部改成inline就好了,管他编译出来的执行档有多大. <BR><BR>系统只以效能做考量,我们还需要Design Pattern做什么? <BR><BR>那些王八蛋数据和我们选举时的民调一模一样...对一个脑袋清楚的人完全没有参考的价值. <BR><BR>当然,以情感因素来看民调的人例外. <BR><BR>如果你没有经过自己的自主判断就盲目的跟随潮流,那么下次当你看到有人排队买米酒,买蛋塔,抢购卫生纸的时候,请不要投以排队的人们奇怪的眼光. <BR><BR>Q5:你尊重老前辈吗? <BR><BR>我们都相信,世界上唯一不用努力就可以获的东西就是老. <BR><BR>所以吃过的盐巴比你吃过的米还多的人,没有任何值得尊重的. <BR><BR>我们更相信,信息业永远是年轻人出头,而英雄少年也常在心里想: <BR><BR>"李杜诗篇万口传,至今已觉不新鲜,江山代有才人出,各领风骚数百年." <BR><BR>但是我们认真想想,从Apple 2的时代到现在随便一颗CPU都是1 GHz的时代, <BR><BR>计算器的本质有什么改变吗? 不就是一台不断对内存作处理和I/O动作的机器. <BR><BR>你笑那些只会用Fortran或COBOL的老前辈,那你学的Java或C#比起这些老语言又高明到哪里去? 写程序不过是 宣告,循环和函式三大要素.时间久了,产生了一堆新名词,配上一些新的发展理念但本质上没有改变. <BR><BR>如果你是推倒前浪的后浪,当你看到李维先生撰写的 "[长篇] 我的回忆和有趣的故事"或侯捷老师最近两期在Run!PC撰写的"侯捷观点"这些老前辈写的文章,你有把握写出比它们更高明,更有深度的东西吗? <BR><BR>最重要的问题, <BR><BR>Q6:你骗过老板吗? <BR><BR>你在履历上写的十八般武艺样样精通,结果是梧鼠技穷(注:比喻技能虽多，而不能专一),一录取之后什么东西都做不出来,笔者至少听过20个老板跟我讲过这件事情.你以为你的身价比较高,只因为你从事"软件研发"的工作? <BR><BR>然而现实的生活中,"获利"是真正决定成败的关键.除非你的东西帮老板赚了钱. <BR><BR>如果没有,你凭什么要求更多薪水,凭什么要求50张价值数千万元的股票? <BR><BR>如果你写的东西品质很差,bug超多,客户抱怨不断,老板赚不到很多钱, <BR><BR>你还老是在外头痛骂老板不尊重技术人员.如果把行业换成色情行业,那老板不就等于被干洗? <BR><BR>这样看来,程序设计师和詹惠华(黄显洲3P案女主角)干的事情有什么两样? <BR><BR>如果这样的杂碎程序设计师太多了,真正要去卖香鸡排的,不是写程序的人, <BR><BR>而是雇用了这些杂碎的老板才对. 不过很遗憾,真的很多软件公司的老板要改行了,鸡排太多人卖了,我建议某位感同身受老板写篇"程序员的老板与蚵仔煎", <BR><BR>请踊跃投稿. <BR><BR>............全文完 <BR>Sun计算机教育训练中心 王森 (moli@pchome.com.tw)<img src ="http://www.blogjava.net/caid/aggbug/31216.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caid/" target="_blank">caid'weblog</a> 2006-02-17 16:13 <a href="http://www.blogjava.net/caid/archive/2006/02/17/31216.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>试题strcpy的写法</title><link>http://www.blogjava.net/caid/archive/2006/02/07/29820.html</link><dc:creator>caid'weblog</dc:creator><author>caid'weblog</author><pubDate>Tue, 07 Feb 2006 07:46:00 GMT</pubDate><guid>http://www.blogjava.net/caid/archive/2006/02/07/29820.html</guid><wfw:comment>http://www.blogjava.net/caid/comments/29820.html</wfw:comment><comments>http://www.blogjava.net/caid/archive/2006/02/07/29820.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caid/comments/commentRss/29820.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caid/services/trackbacks/29820.html</trackback:ping><description><![CDATA[转载：bbs<BR>题目： <BR>&nbsp;&nbsp;&nbsp;&nbsp;已知strcpy函数的原型是： <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*&nbsp;strcpy(char&nbsp;*&nbsp;strDest,const&nbsp;char&nbsp;*&nbsp;strSrc); <BR>&nbsp;&nbsp;&nbsp;&nbsp;1.不调用库函数，实现strcpy函数。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;2.解释为什么要返回char&nbsp;*。 <BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;解说： <BR>&nbsp;&nbsp;&nbsp;&nbsp;1.strcpy的实现代码 <BR><PRE><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*&nbsp;strcpy(char&nbsp;*&nbsp;strDest,const&nbsp;char&nbsp;*&nbsp;strSrc)
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;((strDest==NULL)||(strSrc==NULL))&nbsp;//[1]
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;"Invalid&nbsp;argument(s)";&nbsp;//[2]
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*&nbsp;strDestCopy=strDest;&nbsp;&nbsp;//[3]
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;((*strDest++=*strSrc++)!='\0');&nbsp;//[4]
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;strDestCopy;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
<BR></PRE><BR>&nbsp;&nbsp;&nbsp;&nbsp;错误的做法： <BR>&nbsp;&nbsp;&nbsp;&nbsp;[1] <BR>&nbsp;&nbsp;&nbsp;&nbsp;(A)不检查指针的有效性，说明答题者不注重代码的健壮性。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;(B)检查指针的有效性时使用((!strDest)||(!strSrc))或(!(strDest&amp;&amp;strSrc))，说明答题者对C语言中类型的隐式转换没有深刻认识。在本例中char&nbsp;*转换为bool即是类型隐式转换，这种功能虽然灵活，但更多的是导致出错概率增大和维护成本升高。所以C++专门增加了bool、true、false三个关键字以提供更安全的条件表达式。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;(C)检查指针的有效性时使用((strDest==0)||(strSrc==0))，说明答题者不知道使用常量的好处。直接使用字面常量（如本例中的0）会减少程序的可维护性。0虽然简单，但程序中可能出现很多处对指针的检查，万一出现笔误，编译器不能发现，生成的程序内含逻辑错误，很难排除。而使用NULL代替0，如果出现拼写错误，编译器就会检查出来。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;[2] <BR>&nbsp;&nbsp;&nbsp;&nbsp;(A)return&nbsp;new&nbsp;string("Invalid&nbsp;argument(s)");，说明答题者根本不知道返回值的用途，并且他对内存泄漏也没有警惕心。从函数中返回函数体内分配的内存是十分危险的做法，他把释放内存的义务抛给不知情的调用者，绝大多数情况下，调用者不会释放内存，这导致内存泄漏。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;(B)return&nbsp;0;，说明答题者没有掌握异常机制。调用者有可能忘记检查返回值，调用者还可能无法检查返回值（见后面的链式表达式）。妄想让返回值肩负返回正确值和异常值的双重功能，其结果往往是两种功能都失效。应该以抛出异常来代替返回值，这样可以减轻调用者的负担、使错误不会被忽略、增强程序的可维护性。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;[3] <BR>&nbsp;&nbsp;&nbsp;&nbsp;(A)忘记保存原始的strDest值，说明答题者逻辑思维不严密。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;[4] <BR>&nbsp;&nbsp;&nbsp;&nbsp;(A)循环写成while&nbsp;(*strDest++=*strSrc++);，同[1](B)。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;(B)循环写成while&nbsp;(*strSrc!='\0')&nbsp;*strDest++=*strSrc++;，说明答题者对边界条件的检查不力。循环体结束后，strDest字符串的末尾没有正确地加上'\0'。 <BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;2.返回strDest的原始值使函数能够支持链式表达式，增加了函数的“附加值”。同样功能的函数，如果能合理地提高的可用性，自然就更加理想。 <BR>&nbsp;&nbsp;&nbsp;&nbsp;链式表达式的形式如： <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;iLength=strlen(strcpy(strA,strB)); <BR>&nbsp;&nbsp;&nbsp;&nbsp;又如： <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*&nbsp;strA=strcpy(new&nbsp;char[10],strB); <BR>&nbsp;&nbsp;&nbsp;&nbsp;返回strSrc的原始值是错误的。其一，源字符串肯定是已知的，返回它没有意义。其二，不能支持形如第二例的表达式。其三，为了保护源字符串，形参用const限定strSrc所指的内容，把const&nbsp;char&nbsp;*作为char&nbsp;*返回，类型不符，编译报错。<BR><BR>Linux&nbsp;下的定义是这样的： <BR>/usr/lib/string.h <BR><PRE><BR>&nbsp;string.h:
<BR>char&nbsp;*strcpy&nbsp;(char&nbsp;*__restrict&nbsp;__dest,&nbsp;__const&nbsp;char&nbsp;*__restrict&nbsp;__src)
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__THROW;
<BR></PRE><BR>/usr/src/linux-2.6.0-test3/lib/string.c <BR><PRE><BR>/**
<BR>&nbsp;*&nbsp;strcpy&nbsp;-&nbsp;Copy&nbsp;a&nbsp;%NUL&nbsp;terminated&nbsp;string
<BR>&nbsp;*&nbsp;@dest:&nbsp;Where&nbsp;to&nbsp;copy&nbsp;the&nbsp;string&nbsp;to
<BR>&nbsp;*&nbsp;@src:&nbsp;Where&nbsp;to&nbsp;copy&nbsp;the&nbsp;string&nbsp;from
<BR>&nbsp;*/
<BR>char&nbsp;*&nbsp;strcpy(char&nbsp;*&nbsp;dest,const&nbsp;char&nbsp;*src)
<BR>{
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;char&nbsp;*tmp&nbsp;=&nbsp;dest;
<BR>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while&nbsp;((*dest++&nbsp;=&nbsp;*src++)&nbsp;!=&nbsp;'\0')
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;nothing&nbsp;*/;
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;tmp;
<BR>}
<BR></PRE><BR>在&nbsp;string.h&nbsp;中有&nbsp;__THROW&nbsp;这个宏,我们来查看一下在哪里定义的： <BR>$&nbsp;grep&nbsp;__THROW&nbsp;/usr/include/*.h&nbsp;|grep&nbsp;define <BR><PRE><BR>...
<BR>usr/include/malloc.h:#&nbsp;&nbsp;define&nbsp;__THROW&nbsp;throw&nbsp;()
<BR>...
<BR></PRE><BR>而且几乎每个预处理指令都由&nbsp;__THROW&nbsp;来处理，可以这样查看： <BR>$&nbsp;grep&nbsp;-R&nbsp;__THROW&nbsp;/usr/include/*&nbsp;|&nbsp;grep&nbsp;"#" <BR><BR>linux&nbsp;里的和高质量C/C++&nbsp;里的其实是一样的，除了异常处理哪里稍不同而已。<BR><img src ="http://www.blogjava.net/caid/aggbug/29820.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caid/" target="_blank">caid'weblog</a> 2006-02-07 15:46 <a href="http://www.blogjava.net/caid/archive/2006/02/07/29820.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>calloc(), malloc(), realloc(), free() </title><link>http://www.blogjava.net/caid/archive/2006/02/07/29809.html</link><dc:creator>caid'weblog</dc:creator><author>caid'weblog</author><pubDate>Tue, 07 Feb 2006 06:55:00 GMT</pubDate><guid>http://www.blogjava.net/caid/archive/2006/02/07/29809.html</guid><wfw:comment>http://www.blogjava.net/caid/comments/29809.html</wfw:comment><comments>http://www.blogjava.net/caid/archive/2006/02/07/29809.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/caid/comments/commentRss/29809.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caid/services/trackbacks/29809.html</trackback:ping><description><![CDATA[<P>
<TABLE width="100%">
<TBODY>
<TR>
<TD vAlign=top><FONT face=宋体 size=2>转自：<A href="http://man.chinaunix.net/develop/c&amp;c++/linux_c/function/03.html">http://man.chinaunix.net/develop/c&amp;c++/linux_c/function/03.html</A><BR>calloc（配置内存空间） </FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>相关函数 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>malloc，free，realloc，brk<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>表头文件 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>#include &lt;stdlib.h&gt;<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>定义函数 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>void *calloc(size_t nmemb，size_t size);<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>函数说明 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>calloc()用来配置nmemb个相邻的内存单位，每一单位的大小为size，并返回指向第一个元素的指针。这和使用下列的方式效果相同:malloc(nmemb*size);不过，在利用calloc()配置内存时会将内存内容初始化为0。<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>返回值 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>若配置成功则返回一指针，失败则返回NULL。<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>范例 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>/* 动态配置10个struct test 空间*/<BR>#include&lt;stdlib.h&gt;<BR>struct test<BR>{<BR>int a[10];<BR>char b[20];<BR>}<BR>main()<BR>{<BR>struct test *ptr=calloc(sizeof(struct test),10);<BR>}<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>　 
<DIV align=right><BR><FONT face=宋体 size=2><A name=linuxc26></A></FONT></DIV></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2><BR></FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2><BR>free（释放原先配置的内存） </FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>相关函数 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>malloc，calloc，realloc，brk<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>表头文件 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>#include&lt;stdlib.h&gt;<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>定义函数 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>void free(void *ptr);<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>函数说明 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>参数ptr为指向先前由malloc()、calloc()或realloc()所返回的内存指针。调用free()后ptr所指的内存空间便会被收回。假若参数ptr所指的内存空间已被收回或是未知的内存地址，则调用free()可能会有无法预期的情况发生。若参数ptr为NULL，则free()不会有任何作用。<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>　 
<DIV align=right><BR><FONT face=宋体 size=2><A name=linuxc27></A></FONT></DIV></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2><BR></FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2><BR>getpagesize（取得内存分页大小） </FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>相关函数 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>sbrk<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>表头文件 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>#include&lt;unistd.h&gt;<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>定义函数 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>size_t getpagesize(void);<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>函数说明 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>返回一分页的大小，单位为字节（byte）。此为系统的分页大小，不一定会和硬件分页大小相同。<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>返回值 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>内存分页大小。附加说明在Intel x86 上其返回值应为4096bytes。<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>范例 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>#include &lt;unistd.h&gt;<BR>main()<BR>{<BR>printf(“page size = %d\n”,getpagesize( ) );<BR>}<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>　 
<DIV align=right><BR><FONT face=宋体 size=2><A name=linuxc28></A></FONT></DIV></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2><BR></FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2><BR>malloc（配置内存空间） </FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>相关函数 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>calloc，free，realloc，brk<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>表头文件 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>#include&lt;stdlib.h&gt;<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>定义函数 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>void * malloc(size_t size);<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>函数说明 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>malloc()用来配置内存空间，其大小由指定的size决定。<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>返回值 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>若配置成功则返回一指针，失败则返回NULL。<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>范例 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>void p = malloc(1024); /*配置1k的内存*/<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>　 
<DIV align=right><BR><FONT face=宋体 size=2><A name=linuxc29></A></FONT></DIV></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2><BR></FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2><BR>mmap（建立内存映射） </FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>相关函数 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>munmap，open<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>表头文件 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>#include &lt;unistd.h&gt;<BR>#include &lt;sys/mman.h&gt;<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>定义函数 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offsize);<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>函数说明 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>mmap()用来将某个文件内容映射到内存中，对该内存区域的存取即是直接对该文件内容的读写。参数start指向欲对应的内存起始地址，通常设为NULL，代表让系统自动选定地址，对应成功后该地址会返回。参数length代表将文件中多大的部分对应到内存。<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>参数 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>prot代表映射区域的保护方式有下列组合<BR>PROT_EXEC 映射区域可被执行<BR>PROT_READ 映射区域可被读取<BR>PROT_WRITE 映射区域可被写入<BR>PROT_NONE 映射区域不能存取<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>参数 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>flags会影响映射区域的各种特性<BR>MAP_FIXED 如果参数start所指的地址无法成功建立映射时，则放弃映射，不对地址做修正。通常不鼓励用此旗标。<BR>MAP_SHARED对映射区域的写入数据会复制回文件内，而且允许其他映射该文件的进程共享。<BR>MAP_PRIVATE 对映射区域的写入操作会产生一个映射文件的复制，即私人的“写入时复制”（copy on write）对此区域作的任何修改都不会写回原来的文件内容。<BR>MAP_ANONYMOUS建立匿名映射。此时会忽略参数fd，不涉及文件，而且映射区域无法和其他进程共享。<BR>MAP_DENYWRITE只允许对映射区域的写入操作，其他对文件直接写入的操作将会被拒绝。<BR>MAP_LOCKED 将映射区域锁定住，这表示该区域不会被置换（swap）。<BR>在调用mmap()时必须要指定MAP_SHARED 或MAP_PRIVATE。参数fd为open()返回的文件描述词，代表欲映射到内存的文件。参数offset为文件映射的偏移量，通常设置为0，代表从文件最前方开始对应，offset必须是分页大小的整数倍。<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>返回值 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>若映射成功则返回映射区的内存起始地址，否则返回MAP_FAILED(－1)，错误原因存于errno 中。<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>错误代码 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>EBADF 参数fd 不是有效的文件描述词<BR>EACCES 存取权限有误。如果是MAP_PRIVATE 情况下文件必须可读，使用MAP_SHARED则要有PROT_WRITE以及该文件要能写入。<BR>EINVAL 参数start、length 或offset有一个不合法。<BR>EAGAIN 文件被锁住，或是有太多内存被锁住。<BR>ENOMEM 内存不足。<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>范例 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>/* 利用mmap()来读取/etc/passwd 文件内容*/<BR>#include&lt;sys/types.h&gt;<BR>#include&lt;sys/stat.h&gt;<BR>#include&lt;fcntl.h&gt;<BR>#include&lt;unistd.h&gt;<BR>#include&lt;sys/mman.h&gt;<BR>main()<BR>{<BR>int fd;<BR>void *start;<BR>struct stat sb;<BR>fd=open(“/etc/passwd”,O_RDONLY); /*打开/etc/passwd*/<BR>fstat(fd,&amp;sb); /*取得文件大小*/<BR>start=mmap(NULL,sb.st_size,PROT_READ,MAP_PRIVATE,fd,0);<BR>if(start= = MAP_FAILED) /*判断是否映射成功*/<BR>return;<BR>printf(“%s”,start);<BR>munma(start,sb.st_size); /*解除映射*/<BR>closed(fd);<BR>}<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>执行 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>root : x : 0 : root : /root : /bin/bash<BR>bin : x : 1 : 1 : bin : /bin :<BR>daemon : x : 2 : 2 :daemon : /sbin<BR>adm : x : 3 : 4 : adm : /var/adm :<BR>lp : x :4 :7 : lp : /var/spool/lpd :<BR>sync : x : 5 : 0 : sync : /sbin : bin/sync :<BR>shutdown : x : 6 : 0 : shutdown : /sbin : /sbin/shutdown<BR>halt : x : 7 : 0 : halt : /sbin : /sbin/halt<BR>mail : x : 8 : 12 : mail : /var/spool/mail :<BR>news : x :9 :13 : news : /var/spool/news :<BR>uucp : x :10 :14 : uucp : /var/spool/uucp :<BR>operator : x : 11 : 0 :operator : /root:<BR>games : x : 12 :100 : games :/usr/games:<BR>gopher : x : 13 : 30 : gopher : /usr/lib/gopher-data:<BR>ftp : x : 14 : 50 : FTP User : /home/ftp:<BR>nobody : x :99: 99: Nobody : /:<BR>xfs :x :100 :101 : X Font Server : /etc/xll/fs : /bin/false<BR>gdm : x : 42 :42 : : /home/gdm: /bin/bash<BR>kids : x : 500 :500 :/home/kids : /bin/bash<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>　 
<DIV align=right><BR><FONT face=宋体 size=2><A name=linuxc30></A></FONT></DIV></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2><BR></FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2><BR>munmap（解除内存映射） </FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>相关函数 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>mmap<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>表头文件 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>#include&lt;unistd.h&gt;<BR>#include&lt;sys/mman.h&gt;<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>定义函数 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>int munmap(void *start,size_t length);<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>函数说明 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>munmap()用来取消参数start所指的映射内存起始地址，参数length则是欲取消的内存大小。当进程结束或利用exec相关函数来执行其他程序时，映射内存会自动解除，但关闭对应的文件描述词时不会解除映射。<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>返回值 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>如果解除映射成功则返回0，否则返回－1，错误原因存于errno中错误代码EINVAL<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>参数 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>start或length 不合法。<BR></FONT></TD></TR>
<TR>
<TD vAlign=top width=80>
<DIV align=right><FONT face=宋体 size=2>范例 </FONT></DIV></TD>
<TD vAlign=top><FONT face=宋体 size=2>参考mmap（）<BR></FONT></TD></TR></TBODY></TABLE></P><img src ="http://www.blogjava.net/caid/aggbug/29809.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caid/" target="_blank">caid'weblog</a> 2006-02-07 14:55 <a href="http://www.blogjava.net/caid/archive/2006/02/07/29809.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Q : 如何实现每天定时对数据库的操作 </title><link>http://www.blogjava.net/caid/archive/2006/01/22/28967.html</link><dc:creator>caid'weblog</dc:creator><author>caid'weblog</author><pubDate>Sun, 22 Jan 2006 14:35:00 GMT</pubDate><guid>http://www.blogjava.net/caid/archive/2006/01/22/28967.html</guid><wfw:comment>http://www.blogjava.net/caid/comments/28967.html</wfw:comment><comments>http://www.blogjava.net/caid/archive/2006/01/22/28967.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/caid/comments/commentRss/28967.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/caid/services/trackbacks/28967.html</trackback:ping><description><![CDATA[转自：<A href="http://community.csdn.net/Expert/FAQ/FAQ_Index.asp?id=209284">http://community.csdn.net/Expert/FAQ/FAQ_Index.asp?id=209284</A><BR>
<TABLE cellSpacing=1 cellPadding=3 width=620 border=0>
<TBODY>
<TR bgColor=#eeeeee>
<TD vAlign=top align=right><FONT color=red><B>主要解答者:</B></FONT></TD>
<TD>rixin1980</TD>
<TD align=right><FONT color=red><B>提交人:</B></FONT></TD>
<TD>xuyang821225</TD></TR></TBODY></TABLE><BR>现在有一个很棘手的问题：客户要赠加一个功能，就是每天晚上11点要统计一下数据，并存到一个文件中，我试着用线程，但是总达不到理想的效果。请给点思路，多谢了。 &nbsp;<BR>我们的开发环境是tomcat和servlet，我是这样处理的，在启动tomcat时就开一个线程来检测时间并判断睡眠多长时间， &nbsp;还有没有其他的方式？真的没思路了。请各位指点指点吧！ &nbsp;<BR>================================== &nbsp;<BR>如何在Web工程中实现任务计划调度，好多朋友用过Windows的任务计划 &nbsp;<BR>经过查阅较多相关资料，发现Java定时器（java.util.Timer）有定时触发计划任务的功能，通过配置定时器的间隔时间，在某一间隔时间段之后会自动有规律的调用预先所安排的计划任务（java.util.TimerTask）。另外，由于我们希望当Web工程启动时，定时器能自动开始计时，在整个Web工程的生命期里，定时器能在每晚深夜触发一次报表计算引擎。因此定时器的存放位置也值得考查，不能简单的存在于单个Servlet或JavaBean中，必须能让定时器宿主的存活期为整个Web工程生命期，在工程启动时能自动加载运行。结合这两点，跟Servlet上下文有关的侦听器就最合适不过了，通过在工程的配置文件中加以合理配置，会在工程启动时自动运行，并在整个工程生命期中处于监听状态。 &nbsp;<BR>&nbsp; &nbsp; &nbsp; &nbsp;下面就Servlet侦听器结合Java定时器来讲述整个实现过程。要运用Servlet侦听器需要实现javax.servlet.ServletContextListener接口，同时实现它的contextInitialized(ServletContextEvent &nbsp;event)和contextDestroyed(ServletContextEvent &nbsp;event)两个接口函数。考虑定时器有个建立和销毁的过程，看了前面两个接口函数，就不容置疑的把建立的过程置入contextInitialized，把销毁的过程置入contextDestroyed了。 &nbsp;<BR>&nbsp; &nbsp; &nbsp; &nbsp;我把ServletContextListener的实现类取名为ContextListener,在其内添加一个定时器，示例代码如下所示（为考虑篇幅，仅提供部分代码供读者参考）： &nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>&nbsp;<BR>1. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;private &nbsp;java.util.Timer &nbsp;timer &nbsp;= &nbsp;null; &nbsp; &nbsp;<BR>2. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;public &nbsp;void &nbsp;contextInitialized(ServletContextEvent &nbsp;event) &nbsp;{ &nbsp; &nbsp;<BR>3. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;timer &nbsp;= &nbsp;new &nbsp;java.util.Timer(true); &nbsp; &nbsp;<BR>4. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;event.getServletContext().log("定时器已启动"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<BR>5. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;timer.schedule(new &nbsp;MyTask(event.getServletContext()), &nbsp;0, &nbsp;60*60*1000); &nbsp; &nbsp;<BR>6. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;event.getServletContext().log("已经添加任务调度表"); &nbsp; &nbsp;<BR>7. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;<BR>8. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;public &nbsp;void &nbsp;contextDestroyed(ServletContextEvent &nbsp;event) &nbsp;{ &nbsp; &nbsp;<BR>9. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;timer.cancel(); &nbsp; &nbsp;<BR>10. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;event.getServletContext().log("定时器销毁"); &nbsp; &nbsp;<BR>11. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;<BR>&nbsp;<BR>&nbsp; &nbsp; &nbsp; &nbsp;以上代码中, &nbsp;timer.schedule(new &nbsp;MyTask(event.getServletContext()), &nbsp;0, &nbsp;60*60*1000)这一行为定时器调度语句，其中MyTask是自定义需要被调度的执行任务（在我的财政数据中心项目中就是报表计算引擎入口），从java.util.TimerTask继承，下面会重点讲述，第三个参数表示每小时(即60*60*1000毫秒)被触发一次，中间参数0表示无延迟。其它代码相当简单，不再详细说明。 &nbsp;<BR>&nbsp; &nbsp; &nbsp;下面介绍MyTask的实现，上面的代码中看到了在构造MyTask时，传入了javax.servlet.ServletContext类型参数,是为记录Servlet日志方便而传入，因此需要重载MyTask的构造函数（其父类java.util.TimerTask原构造函数是没有参数的）。在timer.schedule()的调度中,设置了每小时调度一次,因此如果想实现调度任务每24小时被执行一次，还需要判断一下时钟点，以常量C_SCHEDULE_HOUR表示(晚上12点，也即0点)。同时为防止24小时执行下来，任务还未执行完（当然，一般任务是没有这么长的），避免第二次又被调度以引起执行冲突，设置了当前是否正在执行的状态标志isRunning。示例代码如下所示： &nbsp;<BR>1. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;private &nbsp;static &nbsp;final &nbsp;int &nbsp;C_SCHEDULE_HOUR &nbsp; &nbsp; &nbsp;= &nbsp;0; &nbsp; &nbsp;<BR>2. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;private &nbsp;static &nbsp;boolean &nbsp;isRunning &nbsp;= &nbsp;false; &nbsp; &nbsp;<BR>3. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;private &nbsp;ServletContext &nbsp;context &nbsp;= &nbsp;null; &nbsp; &nbsp;<BR>4. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;public &nbsp;MyTask(ServletContext &nbsp;context) &nbsp;{ &nbsp; &nbsp;<BR>5. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;this.context &nbsp;= &nbsp;context; &nbsp; &nbsp;<BR>6. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;<BR>7. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;public &nbsp;void &nbsp;run() &nbsp;{ &nbsp; &nbsp;<BR>8. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Calendar &nbsp;cal &nbsp;= &nbsp;Calendar.getInstance(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<BR>9. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if &nbsp;(!isRunning) &nbsp; &nbsp;{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<BR>10. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if &nbsp;(C_SCHEDULE_HOUR &nbsp;== &nbsp;cal.get(Calendar.HOUR_OF_DAY)) &nbsp;{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<BR>11. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;isRunning &nbsp;= &nbsp;true; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<BR>12. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;context.log("开始执行指定任务"); &nbsp; &nbsp;<BR>13. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<BR>14. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//TODO &nbsp;添加自定义的详细任务，以下只是示例 &nbsp; &nbsp;<BR>15. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;int &nbsp;i &nbsp;= &nbsp;0; &nbsp; &nbsp;<BR>16. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;while &nbsp;(i++ &nbsp;&lt; &nbsp;10) &nbsp;{ &nbsp; &nbsp;<BR>17. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;context.log("已完成任务的" &nbsp;+ &nbsp;i &nbsp;+ &nbsp;"/" &nbsp;+ &nbsp;10); &nbsp; &nbsp;<BR>18. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;<BR>19. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;<BR>20. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;isRunning &nbsp;= &nbsp;false; &nbsp; &nbsp;<BR>21. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;context.log("指定任务执行结束"); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<BR>22. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<BR>23. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp;else &nbsp;{ &nbsp; &nbsp;<BR>24. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;context.log("上一次任务执行还未结束"); &nbsp; &nbsp;<BR>25. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;<BR>26. &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;<BR>&nbsp;<BR>&nbsp; &nbsp; &nbsp; &nbsp;上面代码中“//TODO……”之下四行是真正被调度执行的演示代码(在我的财政数据中心项目中就是报表计算过程)，您可以换成自己希望执行的语句。 &nbsp;<BR>到这儿，ServletContextListener和MyTask的代码都已完整了。最后一步就是把ServletContextListener部署到您的Web工程中去，在您工程的web.xml配置文件中加入如下三行： &nbsp;<BR>&nbsp; &nbsp; &nbsp; &nbsp;&lt;listener&gt; &nbsp;<BR>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&lt;listener-class&gt;com.test.ContextListener&lt;/listener-class&gt; &nbsp;<BR>&nbsp; &nbsp; &nbsp; &nbsp;&lt;/listener&gt; &nbsp; &nbsp;<BR>&nbsp; &nbsp; &nbsp; &nbsp;当然，上面的com.test得换成您自己的包名了。保存web.xml文件后，把工程打包部署到Tomcat中即可。任务会在每晚12点至凌晨1点之间被执行，上面的代码会在Tomcat的日志文件中记录如下： &nbsp;<BR>2003-12-05 &nbsp;0：21：39 &nbsp;开始执行指定任务 &nbsp;<BR>2003-12-05 &nbsp;0：21：39 &nbsp;已完成任务的1/10 &nbsp;<BR>&nbsp; &nbsp; &nbsp; &nbsp;…… &nbsp;<BR>2003-12-05 &nbsp;0：21：39 &nbsp;已完成任务的10/10 &nbsp;<BR>2003-12-05 &nbsp;0：21：39 &nbsp;指定任务执行结束&nbsp;&nbsp;<img src ="http://www.blogjava.net/caid/aggbug/28967.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/caid/" target="_blank">caid'weblog</a> 2006-01-22 22:35 <a href="http://www.blogjava.net/caid/archive/2006/01/22/28967.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>