﻿<?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-翠湖月色-随笔分类-Java基础编程</title><link>http://www.blogjava.net/matthew2006/category/12638.html</link><description>No Buddha tree at all,And bright mirror nor.Now nothing at all,How dusts any more ? </description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 10:31:06 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 10:31:06 GMT</pubDate><ttl>60</ttl><item><title>Java的内存泄漏－转贴</title><link>http://www.blogjava.net/matthew2006/archive/2007/01/16/94114.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Tue, 16 Jan 2007 01:56:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2007/01/16/94114.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/94114.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2007/01/16/94114.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/94114.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/94114.html</trackback:ping><description><![CDATA[问题的提出 <br />Java的一个重要优点就是通过垃圾收集器(Garbage Collection，GC)自动管理内存的回收，程序员不需要通过调用函数来释放内存。因此，很多程序员认为Java不存在内存泄漏问题，或者认为即使有内存泄漏也不是程序的责任，而是GC或JVM的问题。其实，这种想法是不正确的，因为Java也存在内存泄露，但它的表现与C++不同。 随着越来越多的服务器程序采用Java技术，例如JSP，Servlet， EJB等，服务器程序往往长期运行。另外，在很多嵌入式系统中，内存的总量非常有限。内存泄露问题也就变得十分关键，即使每次运行少量泄漏，长期运行之后，系统也是面临崩溃的危险。 Java是如何管理内存 为了判断Java中是否有内存泄露，我们首先必须了解Java是如何管理内存的。Java的内存管理就是对象的分配和释放问题。在Java中，程序员需要通过关键字new为每个对象申请内存空间 (基本类型除外)，所有的对象都在堆 (Heap)中分配空间。另外，对象的释放是由GC决定和执行的。在Java中，内存的分配是由程序完成的，而内存的释放是有GC完成的，这种收支两条线的方法确实简化了程序员的工作。但同时，它也加重了JVM的工作。这也是Java程序运行速度较慢的原因之一。因为，GC为了能够正确释放对象，GC必须监控每一个对象的运行状态，包括对象的申请、引用、被引用、赋值等，GC都需要进行监控。 监视对象状态是为了更加准确地、及时地释放对象，而释放对象的根本原则就是该对象不再被引用。 为了更好理解GC的工作原理，我们可以将对象考虑为有向图的顶点，将引用关系考虑为图的有向边，有向边从引用者指向被引对象。另外，每个线程对象可以作为一个图的起始顶点，例如大多程序从main进程开始执行，那么该图就是以main进程顶点开始的一棵根树。在这个有向图中，根顶点可达的对象都是有效对象，GC将不回收这些对象。如果某个对象 (连通子图)与这个根顶点不可达(注意，该图为有向图)，那么我们认为这个(这些)对象不再被引用，可以被GC回收。 以下，我们举一个例子说明如何用有向图表示内存管理。对于程序的每一个时刻，我们都有一个有向图表示JVM的内存分配情况。以下右图，就是左边程序运行到第6行的示意图。 Java使用有向图的方式进行内存管理，可以消除引用循环的问题，例如有三个对象，相互引用，只要它们和根进程不可达的，那么GC也是可以回收它们的。这种方式的优点是管理内存的精度很高，但是效率较低。另外一种常用的内存管理技术是使用计数器，例如COM模型采用计数器方式管理构件，它与有向图相比，精度行低(很难处理循环引用的问题)，但执行效率很高。 <br /><br />什么是Java中的内存泄露 <br />下面，我们就可以描述什么是内存泄漏。在Java中，内存泄漏就是存在一些被分配的对象，这些对象有下面两个特点，首先，这些对象是可达的，即在有向图中，存在通路可以与其相连；其次，这些对象是无用的，即程序以后不会再使用这些对象。如果对象满足这两个条件，这些对象就可以判定为Java中的内存泄漏，这些对象不会被GC所回收，然而它却占用内存。 在C++中，内存泄漏的范围更大一些。有些对象被分配了内存空间，然后却不可达，由于C++中没有GC，这些内存将永远收不回来。在Java中，这些不可达的对象都由GC负责回收，因此程序员不需要考虑这部分的内存泄露。 通过分析，我们得知，对于C++，程序员需要自己管理边和顶点，而对于Java程序员只需要管理边就可以了(不需要管理顶点的释放)。通过这种方式，Java提高了编程的效率。 因此，通过以上分析，我们知道在Java中也有内存泄漏，但范围比C++要小一些。因为Java从语言上保证，任何对象都是可达的，所有的不可达对象都由GC管理。 对于程序员来说，GC基本是透明的，不可见的。虽然，我们只有几个函数可以访问GC，例如运行GC的函数System.gc()，但是根据Java语言规范定义， 该函数不保证JVM的垃圾收集器一定会执行。因为，不同的JVM实现者可能使用不同的算法管理GC。通常，GC的线程的优先级别较低。JVM调用GC的策略也有很多种，有的是内存使用到达一定程度时，GC才开始工作，也有定时执行的，有的是平缓执行GC，有的是中断式执行GC。但通常来说，我们不需要关心这些。除非在一些特定的场合，GC的执行影响应用程序的性能，例如对于基于Web的实时系统，如网络游戏等，用户不希望GC突然中断应用程序执行而进行垃圾回收，那么我们需要调整GC的参数，让GC能够通过平缓的方式释放内存，例如将垃圾回收分解为一系列的小步骤执行，Sun提供的HotSpot JVM就支持这一特性。 <br /><br />下面给出了一个简单的内存泄露的例子。在这个例子中，我们循环申请Object对象，并将所申请的对象放入一个Vector中，如果我们仅仅释放引用本身，那么Vector仍然引用该对象，所以这个对象对GC来说是不可回收的。因此，如果对象加入到Vector后，还必须从Vector中删除，最简单的方法就是将Vector对象设置为null。 Vector v=new Vector(10); for (int i=1;i&lt;100; i++) { Object o=new Object(); v.add(o); o=null; } //此时，所有的Object对象都没有被释放，因为变量v引用这些对象。 如何检测内存泄漏 最后一个重要的问题，就是如何检测Java的内存泄漏。目前，我们通常使用一些工具来检查Java程序的内存泄漏问题。市场上已有几种专业检查Java内存泄漏的工具，它们的基本工作原理大同小异，都是通过监测Java程序运行时，所有对象的申请、释放等动作，将内存管理的所有信息进行统计、分析、可视化。开发人员将根据这些信息判断程序是否有内存泄漏问题。这些工具包括Optimizeit Profiler，JProbe Profiler，JinSight , Rational 公司的Purify等。<br /> <br />下面，我们将简单介绍Optimizeit的基本功能和工作原理。 Optimizeit Profiler版本4.11支持Application，Applet，Servlet和Romote Application四类应用，并且可以支持大多数类型的JVM，包括SUN JDK系列，IBM的JDK系列，和Jbuilder的JVM等。并且，该软件是由Java编写，因此它支持多种操作系统。Optimizeit系列还包括Thread Debugger和Code Coverage两个工具，分别用于监测运行时的线程状态和代码覆盖面。 当设置好所有的参数了，我们就可以在OptimizeIt环境下运行被测程序，在程序运行过程中，Optimizeit可以监视内存的使用曲线(如下图)，包括JVM申请的堆(heap)的大小，和实际使用的内存大小。另外，在运行过程中，我们可以随时暂停程序的运行，甚至强行调用GC，让GC进行内存回收。通过内存使用曲线，我们可以整体了解程序使用内存的情况。这种监测对于长期运行的应用程序非常有必要，也很容易发现内存泄露。 在运行过程中，我们还可以从不同视角观查内存的使用情况，Optimizeit提供了四种方式： 堆视角。 这是一个全面的视角，我们可以了解堆中的所有的对象信息(数量和种类)，并进行统计、排序，过滤。了解相关对象的变化情况。 方法视角。通过方法视角，我们可以得知每一种类的对象，都分配在哪些方法中，以及它们的数量。 对象视角。给定一个对象，通过对象视角，我们可以显示它的所有出引用和入引用对象，我们可以了解这个对象的所有引用关系。 引用图。 给定一个根，通过引用图，我们可以显示从该顶点出发的所有出引用。 在运行过程中，我们可以随时观察内存的使用情况，通过这种方式，我们可以很快找到那些长期不被释放，并且不再使用的对象。我们通过检查这些对象的生存周期，确认其是否为内存泄露。在实践当中，寻找内存泄露是一件非常麻烦的事情，它需要程序员对整个程序的代码比较清楚，并且需要丰富的调试经验，但是这个过程对于很多关键的Java程序都是十分重要的。 综上所述，Java也存在内存泄露问题，其原因主要是一些对象虽然不再被使用，但它们仍然被引用。为了解决这些问题，我们可以通过软件工具来检查内存泄露，检查的主要原理就是暴露出所有堆中的对象，让程序员寻找那些无用但仍被引用的对象。 <br /><br />作者简介 <br />欧阳辰，北京大学计算机硕士毕业，98年起开始研究基于java的软件开发、测试，参与开发、测试过多个基于Java的应用程序和Web服务项目。 <br />周欣，北京大学计算机系在读博士生，主要研究方向：程序理解、逆向工程及软件度量，联系方式 zhouxin@sei.pku.edu.cn<img src ="http://www.blogjava.net/matthew2006/aggbug/94114.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2007-01-16 09:56 <a href="http://www.blogjava.net/matthew2006/archive/2007/01/16/94114.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Servlet容器工作原理讲解(2)－转贴</title><link>http://www.blogjava.net/matthew2006/archive/2006/12/06/85799.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Wed, 06 Dec 2006 04:37:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/12/06/85799.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/85799.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/12/06/85799.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/85799.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/85799.html</trackback:ping><description><![CDATA[HttpServer1 类 <br /><br />此应用程序内的 HttpServer1类 与前文简单的 WEB 服务器应用程序中的HttpServer 十分相似。但是，此应用程序内的 HttpServer1 能服务静态资源和 servlet。如果要请求一个静态资源，请输入以下 URL： <br /><br /><b><a href="http://machinename:port/staticResource">http://machineName:port/staticResource</a> </b><br /><br />它就是前文中提到的怎样在 WEB 服务器应用程序里请求静态资源。如果要请求一个 servlet，请输入以下 URL： <br /><br /><b><a href="http://machinename:port/servlet/servletClass">http://machineName:port/servlet/servletClass</a> </b><br /><br />如果您想在本地浏览器请求一个 PrimitiveServle servlet ，请输入以下 URL： <br /><br /><b><a href="http://localhost:8080/servlet/PrimitiveServlet">http://localhost:8080/servlet/PrimitiveServlet</a></b> <br /><br />下面 Listing 2.2 类的 await 方法，是等待一个 HTTP 请求，直到一个发布 shutdown 命令。与前文的 await 方法相似。 <br /><br /><b>Listing 2.2. HttpServer1 类的 await 方法<br />public void await() {<br />ServerSocket serverSocket = null;<br />int       port  = 8080;<br />try {<br />serverSocket =  new ServerSocket(port, 1,InetAddress.getByName("127.0.0.1"));<br />    }catch (IOException e) {<br />e.printStackTrace();<br />System.exit(1);<br />    }<br />// 循环，等待一个请求<br />while (!shutdown) {<br />Socket socket       = null;<br />InputStream input   = null;<br />OutputStream output = null;<br />try {<br />socket = serverSocket.accept();<br />input  = socket.getInputStream();<br />output = socket.getOutputStream();<br />// 创建请求对象并解析<br />Request request = new Request(input);<br />request.parse();<br />// 创建回应对象<br />Response response = new Response(output);<br />response.setRequest(request);<br />//检测是否是 servlet 或静态资源的请求<br />//servlet 请求以 "/servlet/" 开始 <br />if (request.getUri().startsWith("/servlet/")) {<br />ServletProcessor1 processor = new ServletProcessor1();<br />processor.process(request, response);<br />            }<br />else {<br />StaticResourceProcessor processor =new StaticResourceProcessor();<br />processor.process(request, response);<br />      }<br />// 关闭socket<br />socket.close();<br />//检测是否前面的 URI 是一个 shutdown 命令<br />shutdown = request.getUri().equals(SHUTDOWN_COMMAND);<br />        }catch (Exception e) {<br />e.printStackTrace();System.exit(1);<br />        }    <br />}<br />}</b> <br /><br />此文 await 方法和前文的不同点就是，此文的 await 方法中的请求调度到StaticResourceProcessor 或 ervletProcessor 。 <br />如果 URI中包含 "/servlet/."，请求推进到后面，否则，请求传递到 StaticResourceProcessor 实例 <br /><br />Request 类 <br /><br />Servlet service 方法接受 servlet 容器的 javax.servlet.ServletRequest 和javax.servlet.ServletResponse 实例。因此，容器必须构建 ServletRequest和ServletResponse对象，然后将其传递到正在被服务的service 方法。 <br /><br />ex02.pyrmont.Request 类代表一个请求对象传递到 service 方法。同样地，它必须实现 javax.servlet.ServletRequest 接口。这个类必须提供接口内所有方法的实现。这里尽量简化它并只实现几个方法。要编译 Request 类的话，必须提供这些方法的空实现。再来看看 request 类，内部所有需要返回一个对象实例都返回null，如下： <br /><br /><b>public Object getAttribute(String attribute) {<br />     return null;<br />  }<br />public Enumeration getAttributeNames() {<br />     return null;<br />  }<br />public String getRealPath(String path) {<br />     return null;<br />  }</b><br />另外，request 类仍需有前文有介绍的 parse 和getUri 方法。 <br /><br />Response 类 <br /><br />response 类实现 javax.servlet.ServletResponse，同样，该类也必须提供接口内所有方法的实现。类似于 Request 类，除 getWriter 方法外，其他方法的实现都为空。 <br /><br /><b>public PrintWriter getWriter() {<br />// autoflush is true, println() will flush,<br />// but print() will not.<br />writer = new PrintWriter(output, true);<br />return writer;<br />}</b><br /><br />PrintWriter 类构建器的第二个参数是一个代表是否启用 autoflush 布尔值，如果为真，所有调用println 方法都 flush 输出。而 print 调用则不 flush 输出。因此，如果在servelt 的service 方法的最后一行调用 print方法，则从浏览器上看不到此输出 。这个不完整性在后面的应用程序内会有调整。 <br /><br />response 类也包含有前文中介绍的 sendStaticResource方法。 <br /><br />StaticResourceProcessor 类 <br /><br />StaticResourceProcessor 类用于服务静态资源的请求。它唯一的方法是 process。 <br /><br /><b>Listing 2.3.StaticResourceProcessor 类的 process方法.<br />public void process(Request request, Response response) {<br />try {<br />response.sendStaticResource();<br />    }catch (IOException e) {<br />e.printStackTrace();<br />    }<br />}</b><br />process 方法接受两个参数：Request 和 Response 实例。它仅仅是调用 response 类的 sendStaticResource 方法。<img src ="http://www.blogjava.net/matthew2006/aggbug/85799.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-12-06 12:37 <a href="http://www.blogjava.net/matthew2006/archive/2006/12/06/85799.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java调用存储过程－转贴</title><link>http://www.blogjava.net/matthew2006/archive/2006/11/18/81950.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Sat, 18 Nov 2006 11:12:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/11/18/81950.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/81950.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/11/18/81950.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/81950.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/81950.html</trackback:ping><description><![CDATA[本文阐述了怎么使用DBMS存储过程。我阐述了使用存储过程的基本的和高级特性，比如返回ResultSet。本文假设你对DBMS和JDBC已经非常熟悉，也假设你能够毫无障碍地阅读其它语言写成的代码（即不是Java的语言），但是，并不要求你有任何存储过程的编程经历。 <br /><br />    存储过程是指保存在数据库并在数据库端执行的程序。你可以使用特殊的语法在Java类中调用存储过程。在调用时，存储过程的名称及指定的参数通过JDBC连接发送给DBMS，执行存储过程并通过连接（如果有）返回结果。 <br />使用存储过程拥有和使用基于EJB或CORBA这样的应用服务器一样的好处。区别是存储过程可以从很多流行的DBMS中免费使用，而应用服务器大都非常昂贵。这并不只是许可证费用的问题。使用应用服务器所需要花费的管理、编写代码的费用，以及客户程序所增加的复杂性，都可以通过DBMS中的存储过程所整个地替代。 <br /><br />    你可以使用Java，Python，Perl或C编写存储过程，但是通常使用你的DBMS所指定的特定语言。Oracle使用PL/SQL，PostgreSQL使用pl/pgsql，DB2使用Procedural SQL。这些语言都非常相似。在它们之间移植存储过程并不比在Sun的EJB规范不同实现版本之间移植Session Bean困难。并且，存储过程是为嵌入SQL所设计，这使得它们比Java或C等语言更加友好地方式表达数据库的机制。 <br /><br />    因为存储过程运行在DBMS自身，这可以帮助减少应用程序中的等待时间。不是在Java代码中执行4个或5个SQL语句，而只需要在服务器端执行1个存储过程。网络上的数据往返次数的减少可以戏剧性地优化性能。 <br /><br />使用存储过程 <br /><br />    简单的老的JDBC通过CallableStatement类支持存储过程的调用。该类实际上是PreparedStatement的一个子类。假设我们有一个poets数据库。数据库中有一个设置诗人逝世年龄的存储过程。下面是对老酒鬼Dylan Thomas（old soak Dylan Thomas，不指定是否有关典故、文化，请批评指正。译注）进行调用的详细代码： <br /><br />try{ <br />int age = 39;<br />String poetName = "dylan thomas"; <br />CallableStatement proc = connection.prepareCall("{ call set_death_age?, ?) }"); <br />proc.setString(1, poetName); <br />proc.setInt(2, age); <br />cs.execute(); <br />}catch (SQLException e){ // ....} <br /><br />    传给prepareCall方法的字串是存储过程调用的书写规范。它指定了存储过程的名称，？代表了你需要指定的参数。 <br />和JDBC集成是存储过程的一个很大的便利：为了从应用中调用存储过程，不需要存根（stub）类或者配置文件，除了你的DBMS的JDBC驱动程序外什么也不需要。 <br /><br />    当这段代码执行时，数据库的存储过程就被调用。我们没有去获取结果，因为该存储过程并不返回结果。执行成功或失败将通过例外得知。失败可能意味着调用存储过程时的失败（比如提供的一个参数的类型不正确），或者一个应用程序的失败（比如抛出一个例外指示在poets数据库中并不存在“Dylan Thomas”） <br /><br />结合SQL操作与存储过程 <br /><br />    映射Java对象到SQL表中的行相当简单，但是通常需要执行几个SQL语句；可能是一个SELECT查找ID，然后一个INSERT插入指定ID的数据。在高度规格化（符合更高的范式，译注）的数据库模式中，可能需要多个表的更新，因此需要更多的语句。Java代码会很快地膨胀，每一个语句的网络开销也迅速增加。 <br />将这些SQL语句转移到一个存储过程中将大大简化代码，仅涉及一次网络调用。所有关联的SQL操作都可以在数据库内部发生。并且，存储过程语言，例如PL/SQL，允许使用SQL语法，这比Java代码更加自然。下面是我们早期的存储过程，使用Oracle的PL/SQL语言编写： <br /><br />create procedure set_death_age(poet VARCHAR2, poet_age NUMBER) <br />poet_id NUMBER; <br />begin SELECT id INTO poet_id FROM poets WHERE name = poet; <br />INSERT INTO deaths (mort_id, age) VALUES (poet_id, poet_age); <br />end set_death_age; <br /><br />    很独特？不。我打赌你一定期待看到一个poets表上的UPDATE。这也暗示了使用存储过程实现是多么容易的一件事情。set_death_age几乎可以肯定是一个很烂的实现。我们应该在poets表中添加一列来存储逝世年龄。Java代码中并不关心数据库模式是怎么实现的，因为它仅调用存储过程。我们以后可以改变数据库模式以提高性能，但是我们不必修改我们代码。 <br /><br />下面是调用上面存储过程的Java代码： <br /><br />public static void setDeathAge(Poet dyingBard, int age) throws SQLException{ <br />Connection con = null; <br />CallableStatement proc = null; <br />try { <br />con = connectionPool.getConnection(); <br />proc = con.prepareCall("{ call set_death_age(?, ?) }"); <br />proc.setString(1, dyingBard.getName()); <br />proc.setInt(2, age); proc.execute(); <br />} finally { <br />try { <br />proc.close(); <br />} catch (SQLException e) { <br />con.close();  } }<br /><br />    为了确保可维护性，建议使用像这儿这样的static方法。这也使得调用存储过程的代码集中在一个简单的模版代码中。如果你用到许多存储过程，就会发现仅需要拷贝、粘贴就可以创建新的方法。因为代码的模版化，甚至也可以通过脚本自动生产调用存储过程的代码。 <br /><br />Functions <br /><br />    存储过程可以有返回值，所以CallableStatement类有类似getResultSet这样的方法来获取返回值。当存储过程返回一个值时，你必须使用registerOutParameter方法告诉JDBC驱动器该值的SQL类型是什么。你也必须调整存储过程调用来指示该过程返回一个值。 <br /><br />下面接着上面的例子。这次我们查询Dylan Thomas逝世时的年龄。这次的存储过程使用PostgreSQL的pl/pgsql： <br /><br />create function snuffed_it_when (VARCHAR) returns integer ''declare <br />poet_id NUMBER; <br />poet_age NUMBER; <br />begin <br />--first get the id associated with the poet. <br />SELECT id INTO poet_id FROM poets WHERE name = $1; <br />--get and return the age. <br />SELECT age INTO poet_age FROM deaths WHERE mort_id = poet_id; <br />return age; <br />end;'' language ''pl/pgsql''; <br /><br />    另外，注意pl/pgsql参数名通过Unix和DOS脚本的$n语法引用。同时，也注意嵌入的注释，这是和Java代码相比的另一个优越性。在Java中写这样的注释当然是可以的，但是看起来很凌乱，并且和SQL语句脱节，必须嵌入到Java String中。 <br /><br />下面是调用这个存储过程的Java代码： <br /><br />connection.setAutoCommit(false); <br />CallableStatement proc = connection.prepareCall("{ ? = call snuffed_it_when(?) }"); <br />proc.registerOutParameter(1, Types.INTEGER); <br />proc.setString(2, poetName); <br />cs.execute(); <br />int age = proc.getInt(2); <br /><br />    如果指定了错误的返回值类型会怎样？那么，当调用存储过程时将抛出一个RuntimeException，正如你在ResultSet操作中使用了一个错误的类型所碰到的一样。 <br /><br />复杂的返回值 <br /><br />    关于存储过程的知识，很多人好像就熟悉我们所讨论的这些。如果这是存储过程的全部功能，那么存储过程就不是其它远程执行机制的替换方案了。存储过程的功能比这强大得多。 <br />    当你执行一个SQL查询时，DBMS创建一个叫做cursor（游标）的数据库对象，用于在返回结果中迭代每一行。ResultSet是当前时间点的游标的一个表示。这就是为什么没有缓存或者特定数据库的支持，你只能在ResultSet中向前移动。 <br /><br />    某些DBMS允许从存储过程中返回游标的一个引用。JDBC并不支持这个功能，但是Oracle、PostgreSQL和DB2的JDBC驱动器都支持在ResultSet上打开到游标的指针（pointer）。 <br /><br />    设想列出所有没有活到退休年龄的诗人，下面是完成这个功能的存储过程，返回一个打开的游标，同样也使用PostgreSQL的pl/pgsql语言： <br /><br />create procedure list_early_deaths () return refcursor as ''declare <br />toesup refcursor; <br />begin open toesup for SELECT poets.name, deaths.age FROM poets, deaths <br />-- all entries in deaths are for poets. <br />-- but the table might become generic. <br />WHERE poets.id = deaths.mort_id AND deaths.age &lt; 60; <br />return toesup; <br />end;'' language ''plpgsql''; <br /><br />下面是调用该存储过程的Java方法，将结果输出到PrintWriter： <br />PrintWriter: <br />static void sendEarlyDeaths(PrintWriter out){ <br />Connection con = null; <br />CallableStatement toesUp = null; <br />try { <br />con = ConnectionPool.getConnection(); // PostgreSQL needs a transaction to do this... con. <br />setAutoCommit(false); // Setup the call. <br />CallableStatement toesUp = connection.prepareCall("{ ? = call list_early_deaths () }"); <br />toesUp.registerOutParameter(1, Types.OTHER); <br />toesUp.execute(); <br />ResultSet rs = (ResultSet) toesUp.getObject(1); <br />while (rs.next()) { <br />String name = rs.getString(1); <br />int age = rs.getInt(2); <br />out.println(name + " was " + age + " years old."); <br />} <br />rs.close(); <br />} catch (SQLException e) { <br />// We should protect these calls. <br />toesUp.close(); <br />con.close(); <br />} <br />} <br /><br />    因为JDBC并不直接支持从存储过程中返回游标，我们使用Types.OTHER来指示存储过程的返回类型，然后调用getObject()方法并对返回值进行强制类型转换。 <br /><br />    这个调用存储过程的Java方法是mapping的一个好例子。Mapping是对一个集上的操作进行抽象的方法。不是在这个过程上返回一个集，我们可以把操作传送进去执行。本例中，操作就是把ResultSet打印到一个输出流。这是一个值得举例的很常用的例子，下面是调用同一个存储过程的另外一个方法实现： <br /><br />public class ProcessPoetDeaths{ <br />public abstract void sendDeath(String name, int age); <br />} <br />static void mapEarlyDeaths(ProcessPoetDeaths mapper){ <br />Connection con = null; <br />CallableStatement toesUp = null; <br />try { <br />con = ConnectionPool.getConnection(); <br />con.setAutoCommit(false); <br />CallableStatement toesUp = connection.prepareCall("{ ? = call list_early_deaths () }"); <br />toesUp.registerOutParameter(1, Types.OTHER); <br />toesUp.execute(); <br />ResultSet rs = (ResultSet) toesUp.getObject(1); <br />while (rs.next()) { <br />String name = rs.getString(1); <br />int age = rs.getInt(2); <br />mapper.sendDeath(name, age); <br />} <br />rs.close(); <br />} catch (SQLException e) { <br />// We should protect these calls. <br />toesUp.close(); <br />con.close(); <br />} <br />} <br /><br />这允许在ResultSet数据上执行任意的处理，而不需要改变或者复制获取ResultSet的方法： <br /><br />static void sendEarlyDeaths(final PrintWriter out){ <br />ProcessPoetDeaths myMapper = new ProcessPoetDeaths() { <br />public void sendDeath(String name, int age) { <br />out.println(name + " was " + age + " years old."); <br />} <br />}; <br />mapEarlyDeaths(myMapper); <br />} <br /><br />   这个方法使用ProcessPoetDeaths的一个匿名实例调用mapEarlyDeaths。该实例拥有sendDeath方法的一个实现，和我们上面的例子一样的方式把结果写入到输出流。当然，这个技巧并不是存储过程特有的，但是和存储过程中返回的ResultSet结合使用，是一个非常强大的工具。 <br /><br />结论 <br /><br />存储过程可以帮助你在代码中分离逻辑，这基本上总是有益的。这个分离的好处有： <br />• 快速创建应用，使用和应用一起改变和改善的数据库模式。 <br />• 数据库模式可以在以后改变而不影响Java对象，当我们完成应用后，可以重新设计更好的模式。 <br />• 存储过程通过更好的SQL嵌入使得复杂的SQL更容易理解。 <br />• 编写存储过程比在Java中编写嵌入的SQL拥有更好的工具－－大部分编辑器都提供语法高亮！ <br />• 存储过程可以在任何SQL命令行中测试，这使得调试更加容易。 <br /><br />并不是所有的数据库都支持存储过程，但是存在许多很棒的实现，包括免费/开源的和非免费的，所以移植并不是一个问题。Oracle、PostgreSQL和DB2都有类似的存储过程语言，并且有在线的社区很好地支持。 <br />存储过程工具很多，有像TOAD或TORA这样的编辑器、调试器和IDE，提供了编写、维护PL/SQL或pl/pgsql的强大的环境。 <br /><br />存储过程确实增加了你的代码的开销，但是它们和大多数的应用服务器相比，开销小得多。<br /><br /><font color="#ff33cc"><a title="原文地质" href="http://www.javaresearch.org/article/58088.htm">查看原文</a></font><img src ="http://www.blogjava.net/matthew2006/aggbug/81950.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-11-18 19:12 <a href="http://www.blogjava.net/matthew2006/archive/2006/11/18/81950.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中文乱码问题－转贴</title><link>http://www.blogjava.net/matthew2006/archive/2006/11/16/81448.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Thu, 16 Nov 2006 02:09:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/11/16/81448.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/81448.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/11/16/81448.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/81448.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/81448.html</trackback:ping><description><![CDATA[1.字节和unicode<br />    java内核是unicode的，就连class文件也是，但是很多媒体，包括文件/流的保存方式是使用字节流的。因此java要对这些字节流经行转化。char是unicode的，而byte是字节。java中byte/char互转的函数在sun.io的包中间有。其中ByteToCharConverter类是中调度，可以用来告诉你，你用的convertor。其中两个很常用的静态函数是 <br />public static ByteToCharConverter getDefault(); <br />public static ByteToCharConverter getConverter(String encoding); <br />如果你不指定converter，则系统会自动使用当前的encoding,gb平台上用gbk,en平台上用8859_1。<br />byte ――〉char：<br /> "你"的gb码是：0xc4e3 ,unicode是0x4f60<br />  String encoding = "gb2312";<br />  byte b[] = {(byte)'\u00c4',(byte)'\u00e3'};<br />  ByteToCharConverter converter = ByteToCharConverter.getConverter(encoding);<br />  char c[] = converter.convertAll(b);<br />  for (int i = 0; i &lt; c.length; i++) {<br />      System.out.println(Integer.toHexString(c[i]));<br />  }<br /> 结果是什么？0x4f60<br /> 如果encoding ="8859_1"，结果又是什么？0x00c4,0x00e3<br /> 如果代码改为<br /> byte b[] = {(byte)'\u00c4',(byte)'\u00e3'};<br /> ByteToCharConverter converter = ByteToCharConverter. getDefault();<br /> char c[] = converter.convertAll(b);<br /> for (int i = 0; i &lt; c.length; i++) {<br />    System.out.println(Integer.toHexString(c[i]));<br /> }<br /> 结果将又是什么？根据平台的编码而定。<br /><br /> char ――〉byte：<br />    String encoding = "gb2312";<br />    char c[] = {'\u4f60'};<br />    CharToByteConverter converter = CharToByteConverter.getConverter(encoding);<br />    byte b[] = converter.convertAll(c);<br />    for (int i = 0; i &lt; b.length; i++) {<br />       System.out.println(Integer.toHexString(b[i]));<br />    }<br />结果是什么？0x00c4,0x00e3<br />如果encoding ="8859_1"，结果又是什么？0x3f<br />如果代码改为<br />String encoding = "gb2312";<br />    char c[] = {'\u4f60'};<br />    CharToByteConverter converter = CharToByteConverter.getDefault();<br />    byte b[] = converter.convertAll(c);<br />    for (int i = 0; i &lt; b.length; i++) {<br />       System.out.println(Integer.toHexString(b[i]));<br />    }<br />结果将又是什么？根据平台的编码而定。<br />很多中文问题就是从这两个最简单的类派生出来的。而却有很多类不直接支持把encoding输入，这给我们带来诸多不便。很多程序难得用encoding了，直接用default的encoding，这就给我们移植带来了很多困难。<br /><br />2.utf-8<br />utf-8是和unicode一一对应的，其实现很简单<br />7位的unicode: 0 _ _ _ _ _ _ _ <br />11位的unicode: 1 1 0 _ _ _ _ _ 1 0 _ _ _ _ _ _ <br />16位的unicode: 1 1 1 0 _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ <br />21位的unicode: 1 1 1 1 0 _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ <br />大多数情况是只使用到16位以下的unicode: <br />"你"的gb码是：0xc4e3 ,unicode是0x4f60<br />    0xc4e3的二进制：<br />          1100 ，0100 ，1110 ，0011<br />由于只有两位我们按照两位的编码来排，但是我们发现这行不通，因为第７位不是0因此，返回"?"<br />    0x4f60的二进制：<br />               0100 ，1111 ，0110 ，0000<br />         我们用utf-8补齐，变成：<br />               1110 ，0100 ，1011 ，1101 ，1010 ，0000<br />         e4--bd-- a0<br />         于是返回：0xe4,0xbd,0xa0。<br /><br />3.string和byte[]<br />string其实核心是char[],然而要把byte转化成string，必须经过编码。string.length()其实就是char数组的长度，如果使用不同的编码，很可能会错分，造成散字和乱码。<br />例如：<br />String encoding = “”;<br />byte [] b={(byte)'\u00c4',(byte)'\u00e3'}; <br />String str=new String(b,encoding);　　<br />如果encoding=8859_1，会有两个字，但是encoding=gb2312只有一个字这个问题在处理分页是经常发生 。<br /><br />4.Reader,Writer / InputStream,OutputStream<br />Reader和Writer核心是char，InputStream和OutputStream核心是byte。但是Reader和Writer的主要目的是要把char读/写InputStream/OutputStream。<br />例如：<br />文件test.txt只有一个"你"字，0xc4,0xe3<br />String encoding = "gb2312";<br />    InputStreamReader reader = new InputStreamReader(new FileInputStream(<br />        "text.txt"), encoding);<br />    char c[] = new char[10];<br />    int length = reader.read(c);<br />    for (int i = 0; i &lt; length; i++) {<br />       System.out.println(c[i]);<br />    }<br />结果是什么？你<br />如果encoding ="8859_1"，结果是什么？??两个字符，表示不认识。<br />反过来的例子自己做。<br /><br />5.我们要对java的编译器有所了解：<br />javac ?encoding<br />我们常常没有用到encoding这个参数。其实encoding这个参数对于跨平台的操作是很重要的。如果没有指定encoding，则按照系统的默认encoding,gb平台上是gb2312，英文平台上是iso8859_1。<br />java的编译器实际上是调用sun.tools.javac.main的类，对文件进行编译，这个类有compile函数中间有一个encoding的变量,-encoding的参数其实直接传给encoding变量。编译器就是根据这个变量来读取java文件的，然后把用utf-8形式编译成class文件。<br />例子代码：<br />String str = "你";<br />    FileWriter writer = new FileWriter("text.txt");<br />    write.write(str);<br />    writer.close();<br /><br />如果用gb2312编译，你会找到e4 bd a0的字段 ；<br />如果用8859_1编译， 00c4 00e3的二进制： <br />0000，0000 ，1100，0100 ，0000，0000 ，1110，0011<br />因为每个字符都大于7位，因此用11位编码： <br />1100，0001，1000，0100，1100，0011，1010，0011 <br />c1-- 84--　c3--　 a3 <br />你会找到c1 84 c3 a3 。<br /><br />但是我们往往忽略掉这个参数，因此这样往往会有跨平台的问题：<br />样例代码在中文平台上编译，生成zhclass<br />样例代码在英文平台上编译，输出enclass<br />  (1).　 zhclass在中文平台上执行ok,但是在英文平台上不行 <br />  (2).    enclass在英文平台上执行ok,但是在中文平台上不行<br />原因：<br />  (1).    在中文平台上编译后，其实str在运行态的char[]是0x4f60,　在中文平台上运行，filewriter的缺省编码是gb2312,因此 chartobyteconverter会自动用调用gb2312的converter,把str转化成byte输入到fileoutputstream中，于是0xc4,0xe3放进了文件。 <br />但是如果是在英文平台下，chartobyteconverter的缺省值是8859_1, filewriter会自动调用8859_1去转化str,但是他无法解释，因此他会输出"?"<br />  (2).    在英文平台上编译后，其实str在运行态的char[]是0x00c4 0x00e3, 在中文平台上运行，中文无法识别，因此会出现??；<br />在英文平台上，0x00c4--&gt;0xc4,0x00e3-&gt;0xe3，因此0xc4,0xe3被放进了文件。<br /><br />6.    其它原因：&lt;%@ page contentType="text/html; charset=GBK" %&gt;<br />设置浏览器的显示编码，如果response的数据是utf8编码，显示将是乱码，但是乱码和上述原因还不一样。<br /><br />7.    发生编码的地方：<br />    从数据库到java程序 byte――〉char<br />    从java程序到数据库 char――〉byte<br />    从文件到java程序 byte――〉char<br />    从java程序到文件 char――〉byte<br />    从java程序到页面显示 char――〉byte<br />    从页面form提交数据到java程序byte――〉char<br />    从流到java程序byte――〉char<br />    从java程序到流char――〉byte<br /><br />谢志钢的解决方法：<br />我是使用配置过滤器的方法解决中文乱码的：<br /><br />&lt;web-app&gt;<br />  &lt;filter&gt;<br />    &lt;filter-name&gt;RequestFilter&lt;/filter-name&gt;<br />    &lt;filter-class&gt;net.golden.uirs.util.RequestFilter&lt;/filter-class&gt;<br />    &lt;init-param&gt;<br />      &lt;param-name&gt;charset&lt;/param-name&gt;<br />      &lt;param-value&gt;gb2312&lt;/param-value&gt;<br />    &lt;/init-param&gt;<br />  &lt;/filter&gt;<br />  &lt;filter-mapping&gt;<br />    &lt;filter-name&gt;RequestFilter&lt;/filter-name&gt;<br />    &lt;url-pattern&gt;*.jsp&lt;/url-pattern&gt;<br />  &lt;/filter-mapping&gt;<br />&lt;/web-app&gt;<br /><br /><br />  public void doFilter(ServletRequest req, ServletResponse res,<br />                       FilterChain fChain) throws IOException, ServletException {<br />    HttpServletRequest request = (HttpServletRequest) req;<br />    HttpServletResponse response = (HttpServletResponse) res;<br />    HttpSession session = request.getSession();<br />    String userId = (String) session.getAttribute("userid");<br />req.setCharacterEncoding(this.filterConfig.getInitParameter("charset")); // 设置字符集？<br />实际上是设置了byte ――〉char的encoding<br />    try {<br />      if (userId == null || userId.equals("")) {<br />        if (!request.getRequestURL().toString().matches(<br />            ".*/uirs/logon/logon(Controller){0,1}\\x2Ejsp$")) {<br />          session.invalidate();<br />          response.sendRedirect(request.getContextPath() +<br />                                "/uirs/logon/logon.jsp");<br />        }<br />      }<br />      else { // 看看是否具有信息上报系统的权限<br />        if (!net.golden.uirs.util.UirsChecker.check(userId, "信息上报系统",<br />            net.golden.uirs.util.UirsChecker.ACTION_DO)) {<br />          if (!request.getRequestURL().toString().matches(<br />              ".*/uirs/logon/logon(Controller){0,1}\\x2Ejsp$")) {<br />            response.sendRedirect(request.getContextPath() +<br />                                  "/uirs/logon/logonController.jsp");<br />          }<br />        }<br />      }<br />    }<br />    catch (Exception ex) {<br />      response.sendRedirect(request.getContextPath() +<br />                            "/uirs/logon/logon.jsp");<br />    }<br />    fChain.doFilter(req, res);<br />  }<br /><br /><font color="#99cc33"><a title="原文" href="http://www.javaresearch.org/article/8065.htm">点击查看原文</a></font><img src ="http://www.blogjava.net/matthew2006/aggbug/81448.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-11-16 10:09 <a href="http://www.blogjava.net/matthew2006/archive/2006/11/16/81448.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java变量类型间的相互转换－转帖</title><link>http://www.blogjava.net/matthew2006/archive/2006/11/15/81161.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Wed, 15 Nov 2006 01:14:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/11/15/81161.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/81161.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/11/15/81161.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/81161.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/81161.html</trackback:ping><description><![CDATA[我们知道，Java的数据类型分为三大类，即布尔型、字符型和数值型，而其中数值型又分为整型和浮点型；相对于数据类型，Java的变量类型为布尔型boolean；字符型char；整型byte、short、int、long；浮点型float、double。其中四种整型变量和两种浮点型变量分别对应于不同的精度和范围。此外，我们还经常用到两种类变量，即String和Date。对于这些变量类型之间的相互转换在我们编程中经常要用到，在我们今天的这篇文章中，我们将来看看如何实现这些转换。<br /><br />一、 整型、实型、字符型变量中的相互转换<br />在Java中整型、实型、字符型被视为同一类数据，这些类型由低级到高级分别为(byte，short，char)??int??long??float??double，低级变量可以直接转换为高级变量，例如，下面的语句可以在Java中直接通过：<br />byte b;<br />int i=b;<br />而将高级变量转换为低级变量时，情况会复杂一些，你可以使用强制类型转换。即你必须采用下面这种语句格式：<br />int i;<br />byte b=(byte)i;<br />可以想象，这种转换肯定可能会导致溢出或精度的下降，因此我们并不推荐使用这种转换。<br /><br />二、Java的包装类<br />在我们讨论其它变量类型之间的相互转换时，我们需要了解一下Java的包装类，所谓包装类，就是可以直接将简单类型的变量表示为一个类，在执行变量类型的相互转换时，我们会大量使用这些包装类。Java共有六个包装类，分别是Boolean、Character、Integer、Long、Float和 Double，从字面上我们就可以看出它们分别对应于 boolean、char、int、long、float和double。而String和Date本身就是类。所以也就不存在什么包装类的概念了。<br /><br />三、简单类型变量和包装类之间的相互转换<br />简单类型的变量转换为相应的包装类，可以利用包装类的构造函数。即：<br />Boolean(boolean value)、Character(char value)、Integer(int value)、Long(long value)、Float(float value)、Double(double value)<br />而在各个包装类中，总有形为××Value()的方法，来得到其对应的简单类型数据。利用这种方法，也可以实现不同数值型变量间的转换，例如，对于一个双精度实型类，intValue()可以得到其对应的整型变量，而doubleValue()可以得到其对应的双精度实型变量。<br /><br />四、String类和其它数据类型的相互转换<br />对于上面的这些包装类，除了Character以外，都有可以直接使用字符串参数的构造函数，这也就使得我们将String类转换为这些数据类型变得相当之简单，即：<br />Boolean(String s)、Integer(String s)、Long(String s)、Float(String s)、Double(String s)<br />而将String类转换为Date类也可以使用这样的构造函数：Date(String s)<br />现在我们还剩下一个字符型变量，事实上String类可以理解为一个char型数组，因此我们可以在String类中找到这样的方法来实现这种转换： charAt(int index)可以得到String类中某一位置上的字符，toCharArray()更可以将整个String类转换成一个char的数组。<br />对于所有的包装类都存在一个名为toString()的方法可以将其转换成对应的String类，而对于整型类和长整型类，还可以使用 toBinaryString(int i)、toHexString(int i)、toOctalString(int i)分别以二进制、十六进制和八进制的形式进行到String类的转换。<br /><br />五、将字符型直接做为数值转换为其它数据类型<br />将字符型变量转换为数值型变量实际上有两种对应关系，在我们在第一部分所说的那种转换中，实际上是将其转换成对应的ASCII码，但是我们有时还需要另一种转换关系，例如，‘1’就是指的数值1，而不是其ASCII码，对于这种转换，我们可以使用Character的getNumericValue(char ch)方法。<br /><br />六、Date类与其它数据类型的相互转换<br />整型和Date类之间并不存在直接的对应关系，只是你可以使用int型为分别表示年、月、日、时、分、秒，这样就在两者之间建立了一个对应关系，在作这种转换时，你可以使用Date类构造函数的三种形式：<br />Date(int year, int month, int date)：以int型表示年、月、日<br />Date(int year, int month, int date, int hrs, int min)：以int型表示年、月、日、时、分<br />Date(int year, int month, int date, int hrs, int min, int sec)：以int型表示年、月、日、时、分、秒<br />在长整型和Date类之间有一个很有趣的对应关系，就是将一个时间表示为距离格林尼治标准时间1970年1月1日0时0分0秒的毫秒数。对于这种对应关系，Date类也有其相应的构造函数：Date(long date)<br />获取Date类中的年、月、日、时、分、秒以及星期你可以使用Date类的getYear()、getMonth()、getDate()、 getHours()、getMinutes()、getSeconds()、getDay()方法，你也可以将其理解为将Date类转换成int。<br />而Date类的getTime()方法可以得到我们前面所说的一个时间对应的长整型数，与包装类一样，Date类也有一个toString()方法可以将其转换为String类。<br />在Java的数据类型转换中，你还有一些其它方法可用，但是，上面所介绍的这些方法对于你的实际编程已经足够了，不是吗？<br /><br /><br /><a title="原文地址" href="http://www.javaresearch.org/article/57963.htm">原文地址</a><br /><img src ="http://www.blogjava.net/matthew2006/aggbug/81161.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-11-15 09:14 <a href="http://www.blogjava.net/matthew2006/archive/2006/11/15/81161.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA字符集－转贴</title><link>http://www.blogjava.net/matthew2006/archive/2006/11/15/81159.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Wed, 15 Nov 2006 01:11:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/11/15/81159.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/81159.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/11/15/81159.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/81159.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/81159.html</trackback:ping><description><![CDATA[1. 概述 <br /><br />本文主要包括以下几个方面：编码基本知识，java，系统软件，url，工具软件等。 <br /><br />在下面的描述中，将以"中文"两个字为例，经查表可以知道其GB2312编码是"d6d0 cec4"，Unicode编码为"4e2d 6587"， UTF编码就是"e4b8ad e69687"。注意，这两个字没有iso8859-1编码，但可以用iso8859-1编码来"表示"。 <br /><br />2. 编码基本知识 <br /><br />最早的编码是iso8859-1，和ascii编码相似。但为了方便表示各种各样的语言，逐渐出现了很多标准编码，重要的有如下几个。 <br /><br />2.1. iso8859-1 <br /><br />属于单字节编码，最多能表示的字符范围是0-255，应用于英文系列。比如，字母'a'的编码为0x61=97。 <br /><br />很明显，iso8859-1编码表示的字符范围很窄，无法表示中文字符。但是，由于是单字节编码，和计算机最基础的表示单位一致，所以很多时候，仍旧使用 iso8859-1编码来表示。而且在很多协议上，默认使用该编码。比如，虽然"中文"两个字不存在iso8859-1编码，以gb2312编码为例，应该是"d6d0 cec4"两个字符，使用iso8859-1编码的时候则将它拆开为4个字节来表示："d6 d0 ce c4"（事实上，在进行存储的时候，也是以字节为单位处理的）。而如果是UTF编码，则是6个字节"e4 b8 ad e6 96 87"。很明显，这种表示方法还需要以另一种编码为基础。 <br /><br />2.2. GB2312/GBK <br /><br />这就是汉子的国标码，专门用来表示汉字，是双字节编码，而英文字母和iso8859-1一致（兼容iso8859-1编码）。其中gbk编码能够用来同时表示繁体字和简体字，而gb2312只能表示简体字，gbk是兼容gb2312编码的。 <br /><br />2.3. unicode <br /><br />这是最统一的编码，可以用来表示所有语言的字符，而且是定长双字节（也有四字节的）编码，包括英文字母在内。所以可以说它是不兼容iso8859-1编码的，也不兼容任何编码。不过，相对于iso8859-1编码来说，uniocode编码只是在前面增加了一个0字节，比如字母'a'为"00 61"。 <br /><br />需要说明的是，定长编码便于计算机处理（注意GB2312/GBK不是定长编码），而unicode又可以用来表示所有字符，所以在很多软件内部是使用unicode编码来处理的，比如java。 <br /><br />2.4. UTF <br /><br />考虑到unicode编码不兼容iso8859-1编码，而且容易占用更多的空间：因为对于英文字母，unicode也需要两个字节来表示。所以 unicode不便于传输和存储。因此而产生了utf编码，utf编码兼容iso8859-1编码，同时也可以用来表示所有语言的字符，不过，utf编码是不定长编码，每一个字符的长度从1-6个字节不等。另外，utf编码自带简单的校验功能。一般来讲，英文字母都是用一个字节表示，而汉字使用三个字节。  <br /><br />注意，虽然说utf是为了使用更少的空间而使用的，但那只是相对于unicode编码来说，如果已经知道是汉字，则使用 GB2312/GBK无疑是最节省的。不过另一方面，值得说明的是，虽然utf编码对汉字使用3个字节，但即使对于汉字网页，utf编码也会比 unicode编码节省，因为网页中包含了很多的英文字符。 <br /><br />3. java对字符的处理 <br /><br />在java应用软件中，会有多处涉及到字符集编码，有些地方需要进行正确的设置，有些地方需要进行一定程度的处理。 <br /><br />3.1. getBytes(charset) <br /><br />这是java字符串处理的一个标准函数，其作用是将字符串所表示的字符按照charset编码，并以字节方式表示。注意字符串在java内存中总是按 unicode编码存储的。比如"中文"，正常情况下（即没有错误的时候）存储为"4e2d 6587"，如果charset为"gbk"，则被编码为 "d6d0 cec4"，然后返回字节"d6 d0 ce c4"。如果charset为"utf8"则最后是"e4 b8 ad e6 96 87"。如果是"iso8859-1"，则由于无法编码，最后返回 "3f 3f"（两个问号）。 <br /><br />3.2. new String(charset) <br /><br />这是java字符串处理的另一个标准函数，和上一个函数的作用相反，将字节数组按照charset编码进行组合识别，最后转换为unicode存储。参考上述getBytes的例子，"gbk" 和"utf8"都可以得出正确的结果"4e2d 6587"，但iso8859-1最后变成了 "003f 003f"（两个问号）。 <br /><br />因为utf8可以用来表示/编码所有字符，所以new String( str.getBytes( "utf8" ), "utf8" ) === str，即完全可逆。 <br /><br />3.3. setCharacterEncoding() <br /><br />该函数用来设置http请求或者相应的编码。 <br /><br />对于request，是指提交内容的编码，指定后可以通过getParameter()则直接获得正确的字符串，如果不指定，则默认使用iso8859-1 编码，需要进一步处理。参见下述"表单输入"。值得注意的是在执行setCharacterEncoding()之前，不能执行任何 getParameter()。java doc上说明： This method must be called prior to reading request parameters or reading input using getReader ()。而且，该指定只对POST方法有效，对GET方法无效。分析原因，应该是在执行第一个getParameter()的时候，java将会按照编码分析所有的提交内容，而后续的getParameter()不再进行分析，所以setCharacterEncoding()无效。而对于GET方法提交表单是，提交的内容在URL中，一开始就已经按照编码分析所有的提交内容，setCharacterEncoding()自然就无效。 <br /><br />对于response，则是指定输出内容的编码，同时，该设置会传递给浏览器，告诉浏览器输出内容所采用的编码。 <br /><br />3.4. 处理过程 <br /><br />下面分析两个有代表性的例子，说明java对编码有关问题的处理方法。 <br /><br />3.4.1. 表单输入 <br /><br />User input  * (gbk:d6d0 cec4)  browser  *(gbk:d6d0 cec4)  web server  iso8859-1(00d6 00d 000ce 00c4)   class，需要在class中进行处理：getbytes("iso8859-1")为d6 d0 ce c4，new String ("gbk")为d6d0 cec4，内存中以unicode编码则为4e2d 6587。 <br /><br />l 用户输入的编码方式和页面指定的编码有关，也和用户的操作系统有关，所以是不确定的，上例以gbk为例。 <br /><br />l 从browser到web server，可以在表单中指定提交内容时使用的字符集，否则会使用页面指定的编码。而如果在url中直接用?的方式输入参数，则其编码往往是操作系统本身的编码，因为这时和页面无关。上述仍旧以gbk编码为例。 <br /><br />l Web server 接收到的是字节流，默认时（getParameter）会以iso8859-1编码处理之，结果是不正确的，所以需要进行处理。但如果预先设置了编码（通过request. setCharacterEncoding ()），则能够直接获取到正确的结果。 <br /><br />l 在页面中指定编码是个好习惯，否则可能失去控制，无法指定正确的编码。 <br /><br />3.4.2. 文件编译 <br /><br />假设文件是gbk编码保存的，而编译有两种编码选择：gbk或者iso8859-1，前者是中文windows的默认编码，后者是linux的默认编码，当然也可以在编译时指定编码。 <br /><br />Jsp  * (gbk:d6d0 cec4)  java file  *(gbk:d6d0 cec4)  compiler read  uincode(gbk:  4e2d 6587; iso8859-1: 00d6 00d 000ce 00c4)  compiler write  utf(gbk: e4b8ad e69687;  iso8859-1: *)  compiled file  unicode(gbk: 4e2d 6587; iso8859-1: 00d6 00d 000ce 00c4)   class。所以用gbk编码保存，而用iso8859-1编译的结果是不正确的。 <br /><br />class  unicode(4e2d 6587)  system.out / jsp.out  gbk(d6d0 cec4)  os console / browser。 <br /><br />l 文件可以以多种编码方式保存，中文windows下，默认为ansi/gbk。 <br /><br />l  编译器读取文件时，需要得到文件的编码，如果未指定，则使用系统默认编码。一般class文件，是以系统默认编码保存的，所以编译不会出问题，但对于 jsp文件，如果在中文windows下编辑保存，而部署在英文linux下运行/编译，则会出现问题。所以需要在jsp文件中用 pageEncoding指定编码。 <br /><br />l Java编译的时候会转换成统一的unicode编码处理，最后保存的时候再转换为utf编码。 <br /><br />l  当系统输出字符的时候，会按指定编码输出，对于中文windows下，System.out将使用gbk编码，而对于response（浏览器），则使用 jsp文件头指定的contentType，或者可以直接为response指定编码。同时，会告诉browser网页的编码。如果未指定，则会使用 iso8859-1编码。对于中文，应该为browser指定输出字符串的编码。 <br /><br />l browser显示网页的时候，首先使用response中指定的编码（jsp文件头指定的contentType最终也反映在response上），如果未指定，则会使用网页中meta项指定中的contentType。 <br /><br />3.5. 几处设置 <br /><br />对于web应用程序，和编码有关的设置或者函数如下。 <br /><br />3.5.1. jsp编译 <br /><br />指定文件的存储编码，很明显，该设置应该置于文件的开头。例如：&lt;%@page pageEncoding="GBK"%&gt;。另外，对于一般class文件，可以在编译的时候指定编码。 <br /><br />3.5.2. jsp输出 <br /><br />指定文件输出到browser是使用的编码，该设置也应该置于文件的开头。例如：&lt;%@ page contentType="text/html;  charset= GBK" %&gt;。该设置和response.setCharacterEncoding("GBK")等效。 <br /><br />3.5.3. meta设置 <br /><br />指定网页使用的编码，该设置对静态网页尤其有作用。因为静态网页无法采用jsp的设置，而且也无法执行response.setCharacterEncoding()。例如： <br /><br />如果同时采用了jsp输出和meta设置两种编码指定方式，则jsp指定的优先。因为jsp指定的直接体现在response中。 <br /><br />需要注意的是，apache有一个设置可以给无编码指定的网页指定编码，该指定等同于jsp的编码指定方式，所以会覆盖静态网页中的meta指定。所以有人建议关闭该设置。 <br /><br />3.5.4. form设置 <br /><br />当浏览器提交表单的时候，可以指定相应的编码。例如：。一般不必不使用该设置，浏览器会直接使用网页的编码。 <br /><br />4. 系统软件 <br /><br />下面讨论几个相关的系统软件。 <br /><br />4.1. mysql数据库 <br /><br />很明显，要支持多语言，应该将数据库的编码设置成utf或者unicode，而utf更适合与存储。但是，如果中文数据中包含的英文字母很少，其实unicode更为适合。 <br /><br />数据库的编码可以通过mysql的配置文件设置，例如default-character-set=utf8。还可以在数据库链接URL中设置，例如：  useUnicode=true&amp;characterEncoding=UTF-8。注意这两者应该保持一致，在新的sql版本里，在数据库链接URL里可以不进行设置，但也不能是错误的设置。 <br /><br />4.2. apache <br /><br />appache和编码有关的配置在httpd.conf中，例如AddDefaultCharset UTF-8。如前所述，该功能会将所有静态页面的编码设置为UTF-8，最好关闭该功能。 <br /><br />另外，apache还有单独的模块来处理网页响应头，其中也可能对编码进行设置。 <br /><br />4.3. linux默认编码 <br /><br />这里所说的linux默认编码，是指运行时的环境变量。两个重要的环境变量是LC_ALL和LANG，默认编码会影响到java URLEncode的行为，下面有描述。 <br /><br />建议都设置为"zh_CN.UTF-8"。 <br /><br />4.4. 其它 <br /><br />为了支持中文文件名，linux在加载磁盘时应该指定字符集，例如：mount /dev/hda5 /mnt/hda5/ -t ntfs -o iocharset=gb2312。 <br /><br />另外，如前所述，使用GET方法提交的信息不支持request.setCharacterEncoding()，但可以通过tomcat的配置文件指定字符集，在tomcat的server.xml文件中，形如：。这种方法将统一设置所有请求，而不能针对具体页面进行设置，也不一定和browser使用的编码相同，所以有时候并不是所期望的。 <br /><br />5. URL地址 <br /><br />URL地址中含有中文字符是很麻烦的，前面描述过使用GET方法提交表单的情况，使用GET方法时，参数就是包含在URL中。 <br /><br />5.1. URL编码 <br /><br />对于URL中的一些特殊字符，浏览器会自动进行编码。这些字符除了"/?&amp;"等外，还包括unicode字符，比如汉子。这时的编码比较特殊。 <br /><br />IE 有一个选项"总是使用UTF-8发送URL"，当该选项有效时，IE将会对特殊字符进行UTF-8编码，同时进行URL编码。如果改选项无效，则使用默认编码"GBK"，并且不进行URL编码。但是，对于URL后面的参数，则总是不进行编码，相当于UTF-8选项无效。比如"中文.html?a=中文"，当UTF-8选项有效时，将发送链接"%e4%b8%ad%e6%96%87.html?a=\x4e\x2d\x65\x87"；而UTF-8选项无效时，将发送链接"\x4e\x2d\x65\x87.html?a=\x4e\x2d\x65\x87"。注意后者前面的"中文"两个字只有4个字节，而前者却有18个字节，这主要时URL编码的原因。 <br /><br />当web server（tomcat）接收到该链接时，将会进行URL解码，即去掉 "%"，同时按照ISO8859-1编码（上面已经描述，可以使用URLEncoding来设置成其它编码）识别。上述例子的结果分别是"\ue4\ ub8\uad\ue6\u96\u87.html?a=\u4e\u2d\u65\u87"和"\u4e\u2d\u65\u87.html?a=\ u4e\u2d\u65\u87"，注意前者前面的"中文"两个字恢复成了6个字符。这里用"\u"，表示是unicode。 <br /><br />所以，由于客户端设置的不同，相同的链接，在服务器上得到了不同结果。这个问题不少人都遇到，却没有很好的解决办法。所以有的网站会建议用户尝试关闭UTF-8选项。不过，下面会描述一个更好的处理办法。 <br /><br />5.2. rewrite <br /><br />熟悉的人都知道，apache有一个功能强大的rewrite模块，这里不描述其功能。需要说明的是该模块会自动将URL解码（去除%），即完成上述 web server（tomcat）的部分功能。有相关文档介绍说可以使用[NE]参数来关闭该功能，但我试验并未成功，可能是因为版本（我使用的是 apache 2.0.54）问题。另外，当参数中含有"?&amp; "等符号的时候，该功能将导致系统得不到正常结果。 <br /><br />rewrite本身似乎完全是采用字节处理的方式，而不考虑字符串的编码，所以不会带来编码问题。 <br /><br />5.3. URLEncode.encode() <br /><br />这是Java本身提供对的URL编码函数，完成的工作和上述UTF-8选项有效时浏览器所做的工作相似。值得说明的是，java已经不赞成不指定编码来使用该方法（deprecated）。应该在使用的时候增加编码指定。 <br /><br />当不指定编码的时候，该方法使用系统默认编码，这会导致软件运行结果得不确定。比如对于"中文"，当系统默认编码为"gb2312"时，结果是"%4e% 2d%65%87"，而默认编码为"UTF-8"，结果却是"%e4%b8%ad%e6%96%87"，后续程序将难以处理。另外，这儿说的系统默认编码是由运行tomcat时的环境变量LC_ALL和LANG等决定的，曾经出现过tomcat重启后就出现乱码的问题，最后才郁闷的发现是因为修改修改了这两个环境变量。 <br /><br />建议统一指定为"UTF-8"编码，可能需要修改相应的程序。 <br /><br />5.4. 一个解决方案 <br /><br />上面说起过，因为浏览器设置的不同，对于同一个链接，web server收到的是不同内容，而软件系统有无法知道这中间的区别，所以这一协议目前还存在缺陷。 <br /><br />针对具体问题，不应该侥幸认为所有客户的IE设置都是UTF-8有效的，也不应该粗暴的建议用户修改IE设置，要知道，用户不可能去记住每一个web server的设置。所以，接下来的解决办法就只能是让自己的程序多一点智能：根据内容来分析编码是否UTF-8。 <br /><br />比较幸运的是UTF-8编码相当有规律，所以可以通过分析传输过来的链接内容，来判断是否是正确的UTF-8字符，如果是，则以UTF-8处理之，如果不是，则使用客户默认编码（比如"GBK"），下面是一个判断是否UTF-8的例子，如果你了解相应规律，就容易理解。 <br /><br />public static boolean isValidUtf8(byte[] b,int aMaxCount){ <br /><br />       int lLen=b.length,lCharCount=0; <br /><br />       for(int i=0;i<br /><br />              byte lByte=b[i++];//to fast operation, ++ now, ready for the following for(;;) <br /><br />              if(lByte&gt;=0) continue;//&gt;=0 is normal ascii <br /><br />              if(lByte&lt;(byte)0xc0 || lByte&gt;(byte)0xfd) return false; <br /><br />              int lCount=lByte&gt;(byte)0xfc?5:lByte&gt;(byte)0xf8?4 <br /><br />                     :lByte&gt;(byte)0xf0?3:lByte&gt;(byte)0xe0?2:1; <br /><br />              if(i+lCount&gt;lLen) return false; <br /><br />              for(int j=0;j=(byte)0xc0) return false; <br /><br />       } <br /><br />       return true; <br /><br />} <br /><br />相应地，一个使用上述方法的例子如下： <br /><br />public static String getUrlParam(String aStr,String aDefaultCharset) <br /><br />throws UnsupportedEncodingException{ <br /><br />       if(aStr==null) return null; <br /><br />       byte[] lBytes=aStr.getBytes("ISO-8859-1"); <br /><br />       return new String(lBytes,StringUtil.isValidUtf8(lBytes)?"utf8":aDefaultCharset); <br /><br />} <br /><br />不过，该方法也存在缺陷，如下两方面： <br /><br />l 没有包括对用户默认编码的识别，这可以根据请求信息的语言来判断，但不一定正确，因为我们有时候也会输入一些韩文，或者其他文字。 <br /><br />l 可能会错误判断UTF-8字符，一个例子是"学习"两个字，其GBK编码是" \xd1\xa7\xcf\xb0"，如果使用上述isValidUtf8方法判断，将返回true。可以考虑使用更严格的判断方法，不过估计效果不大。 <br /><br />有一个例子可以证明google也遇到了上述问题，而且也采用了和上述相似的处理方法，比如，如果在地址栏中输入"http: //www.google.com/search?hl=zh-CN&amp;newwindow=1&amp;q=学习"，google将无法正确识别，而其他汉字一般能够正常识别。 <br /><br />最后，应该补充说明一下，如果不使用rewrite规则，或者通过表单提交数据，其实并不一定会遇到上述问题，因为这时可以在提交数据时指定希望的编码。另外，中文文件名确实会带来问题，应该谨慎使用。 <br /><br />6. 其它 <br /><br />下面描述一些和编码有关的其他问题。 <br /><br />6.1. SecureCRT <br /><br />除了浏览器和控制台与编码有关外，一些客户端也很有关系。比如在使用SecureCRT连接linux时，应该让SecureCRT的显示编码（不同的session，可以有不同的编码设置）和linux的编码环境变量保持一致。否则看到的一些帮助信息，就可能是乱码。 <br /><br />另外，mysql有自己的编码设置，也应该保持和SecureCRT的显示编码一致。否则通过SecureCRT执行sql语句的时候，可能无法处理中文字符，查询结果也会出现乱码。 <br /><br />对于Utf-8文件，很多编辑器（比如记事本）会在文件开头增加三个不可见的标志字节，如果作为mysql的输入文件，则必须要去掉这三个字符。（用 linux的vi保存可以去掉这三个字符）。一个有趣的现象是，在中文windows下，创建一个新txt文件，用记事本打开，输入"连通"两个字，保存，再打开，你会发现两个字没了，只留下一个小黑点。 <br /><br />6.2. 过滤器 <br /><br />如果需要统一设置编码，则通过filter进行设置是个不错的选择。在filter class中，可以统一为需要的请求或者回应设置编码。参加上述setCharacterEncoding()。这个类apache已经给出了可以直接使用的例子SetCharacterEncodingFilter。 <br /><br />6.3. POST和GET <br /><br />很明显，以POST提交信息时，URL有更好的可读性，而且可以方便的使用setCharacterEncoding()来处理字符集问题。但GET方法形成的URL能够更容易表达网页的实际内容，也能够用于收藏。 <br /><br />从统一的角度考虑问题，建议采用GET方法，这要求在程序中获得参数是进行特殊处理，而无法使用setCharacterEncoding()的便利，如果不考虑rewrite，就不存在IE的UTF-8问题，可以考虑通过设置URIEncoding来方便获取URL中的参数。 <br /><br />6.4. 简繁体编码转换 <br /><br />GBK 同时包含简体和繁体编码，也就是说同一个字，由于编码不同，在GBK编码下属于两个字。有时候，为了正确取得完整的结果，应该将繁体和简体进行统一。可以考虑将UTF、GBK中的所有繁体字，转换为相应的简体字，BIG5编码的数据，也应该转化成相应的简体字。当然，仍旧以UTF编码存储。 <br /><br />例如，对于"语言 ?言"，用UTF表示为"\xE8\xAF\xAD\xE8\xA8\x80 \xE8\xAA\x9E\xE8\xA8\x80"，进行简繁体编码转换后应该是两个相同的 "\xE8\xAF\xAD\xE8\xA8\x80&gt;"。 <br /><img src ="http://www.blogjava.net/matthew2006/aggbug/81159.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-11-15 09:11 <a href="http://www.blogjava.net/matthew2006/archive/2006/11/15/81159.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MD5加密及Java的实现方式－ 转贴</title><link>http://www.blogjava.net/matthew2006/archive/2006/08/10/62719.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Thu, 10 Aug 2006 01:51:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/08/10/62719.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/62719.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/08/10/62719.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/62719.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/62719.html</trackback:ping><description><![CDATA[
		<strong>首先<br /></strong>   我看到很多贴子，上面描述MD5加密解密等话题，因此写此文章为了把MD5加密问题简单的说个透彻，并且给大家已经实践过的代码。<br /><br /><b>其次</b><br />   MD5加密并不是把原文加密，这个大家得注意，既然没有把原文加密何来的解密呢？简直是个笑话。MD5的用途就是把一段原文数据通过一定的算法生成16字节的密文，通过这个密文我们可以检查原文的数据是否被修改过。常用在网络中明文数据传输，防止传输过程中内容被恶意修改。典型的应用协议为radius，radius协议中有16byte就是MD5所留的，把用户的密码加在报文尾部进行MD5，把结果存在网络中，所以明文部分看不到用户的密码，当服务器收到此包，用同样的方法进行MD5，如果加密出来的16byte一样，说明是有效的未被恶意修改的网络包。<br /><br /><b>最后</b><br />附上实现的代码<br /><br /><div class="codeStyle"><ol><li></li><li><b><font color="#0000ff">import</font></b> java.security.*; 
</li><li></li><li><b><font color="#0000ff">public</font></b> <b><font color="#0000ff">class</font></b> MD5 { 
</li><li>  <i><font color="#339900">/**</font></i></li><li><i><font color="#339900">   * MD5</font></i></li><li><i><font color="#339900">   *</font></i></li><li><i><font color="#339900">   * @author Dreamer</font></i></li><li><i><font color="#339900">   */</font></i></li><li>  <b><font color="#0000ff">public</font></b> MD5() { 
</li><li>  } 
</li><li></li><li>  <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">static</font></b> <b><font color="#0000ff">byte</font></b>[] md5(<b><font color="#0000ff">byte</font></b>[] in) { 
</li><li>    <b><a href="http://www.javaresearch.org/source/jdk142/java/security/MessageDigest.java.html" target="_blank"><font class="classLink"><u>MessageDigest</u></font></a></b> md = <b><font color="#0000ff">null</font></b>; 
</li><li>    <b><font color="#0000ff">byte</font></b>[] out = <b><font color="#0000ff">new</font></b> <b><font color="#0000ff">byte</font></b>[16]; 
</li><li>    <b><font color="#0000ff">try</font></b> { 
</li><li>      md = <b><a href="http://www.javaresearch.org/source/jdk142/java/security/MessageDigest.java.html" target="_blank"><font class="classLink"><u>MessageDigest</u></font></a></b>.getInstance(<font color="#ff33ff">"MD5"</font>); 
</li><li>    } 
</li><li>    <b><font color="#0000ff">catch</font></b> (<b><a href="http://www.javaresearch.org/source/jdk142/java/security/NoSuchAlgorithmException.java.html" target="_blank"><font class="classLink"><u>NoSuchAlgorithmException</u></font></a></b> ex) { 
</li><li>      <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/System.java.html" target="_blank"><font class="classLink"><u>System</u></font></a></b>.out.println(ex.toString()); 
</li><li>    } 
</li><li>    md.reset(); 
</li><li>    md.update(in); 
</li><li>    out = md.digest(); 
</li><li>    <b><font color="#0000ff">return</font></b> out; 
</li><li>  } 
</li><li></li><li>  <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">static</font></b> <b><font color="#0000ff">byte</font></b>[] md5(<b><font color="#0000ff">byte</font></b>[] in, <b><font color="#0000ff">int</font></b> len) { 
</li><li>    <b><a href="http://www.javaresearch.org/source/jdk142/java/security/MessageDigest.java.html" target="_blank"><font class="classLink"><u>MessageDigest</u></font></a></b> md = <b><font color="#0000ff">null</font></b>; 
</li><li>    <b><font color="#0000ff">byte</font></b>[] out = <b><font color="#0000ff">new</font></b> <b><font color="#0000ff">byte</font></b>[16]; 
</li><li>    <b><font color="#0000ff">try</font></b> { 
</li><li>      md = <b><a href="http://www.javaresearch.org/source/jdk142/java/security/MessageDigest.java.html" target="_blank"><font class="classLink"><u>MessageDigest</u></font></a></b>.getInstance(<font color="#ff33ff">"MD5"</font>); 
</li><li>    } 
</li><li>    <b><font color="#0000ff">catch</font></b> (<b><a href="http://www.javaresearch.org/source/jdk142/java/security/NoSuchAlgorithmException.java.html" target="_blank"><font class="classLink"><u>NoSuchAlgorithmException</u></font></a></b> ex) { 
</li><li>      <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/System.java.html" target="_blank"><font class="classLink"><u>System</u></font></a></b>.out.println(ex.toString()); 
</li><li>    } 
</li><li>    md.reset(); 
</li><li>    md.update(in, 0, len); 
</li><li>    out = md.digest(); 
</li><li>    <b><font color="#0000ff">return</font></b> out; 
</li><li>  } 
</li><li></li><li>} </li></ol></div><img src ="http://www.blogjava.net/matthew2006/aggbug/62719.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-08-10 09:51 <a href="http://www.blogjava.net/matthew2006/archive/2006/08/10/62719.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java中的日期处理－转贴</title><link>http://www.blogjava.net/matthew2006/archive/2006/07/15/58325.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Sat, 15 Jul 2006 06:52:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/07/15/58325.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/58325.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/07/15/58325.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/58325.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/58325.html</trackback:ping><description><![CDATA[近来上网查了些java日期处理的资料，其中有些内容觉得比较有实际用处。贴出来做个记录：<br /><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><font size="6"><strong><span lang="ZH-CN" style="FONT-SIZE: 22pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt; mso-fareast-language: ZH-CN"></span></strong></font><strong><span lang="EN-US" style="FONT-SIZE: 22pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt; mso-fareast-language: ZH-CN"><?XML:NAMESPACE PREFIX = O /?><o:p><font size="4">1 日期模板</font></o:p></span></strong></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="ZH-CN" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt; mso-fareast-language: ZH-CN">模板定义如下：</span><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt; mso-fareast-language: ZH-CN"><o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt; mso-fareast-language: ZH-CN">y </span><span lang="ZH-CN" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt; mso-fareast-language: ZH-CN">年号，如</span><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt; mso-fareast-language: ZH-CN">1996<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">M 月份，如July 或者07<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">d 月中第几天，如12<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt; mso-fareast-language: ZH-CN">H </span><span lang="ZH-CN" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt; mso-fareast-language: ZH-CN">小时</span><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt; mso-fareast-language: ZH-CN">(24 </span><span lang="ZH-CN" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt; mso-fareast-language: ZH-CN">制</span><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt; mso-fareast-language: ZH-CN">)</span><span lang="ZH-CN" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt; mso-fareast-language: ZH-CN">，如</span><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt; mso-fareast-language: ZH-CN">0</span><span lang="ZH-CN" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt; mso-fareast-language: ZH-CN">、</span><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt; mso-fareast-language: ZH-CN">17<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">m 分钟,如32<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">s 钞钟，如55<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">S 微钞，如978<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">E 星期几，如Tuesday<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">D 一年中的第几天，如189<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">w week in year (Number) 27<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">W week in month (Number) 2<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">a am/pm marker (Text) PM<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">k hour in day (1~24) (Number) 24<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">K hour in am/pm (0~11) (Number) 0<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">z time zone (Text) Pacific Standard Time<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">' escape for text (Delimiter)<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">'' single quote (Literal) '<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><strong><span lang="EN-US" style="FONT-SIZE: 22pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt"><o:p><font size="4">2 日期格式</font></o:p></span></strong></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">使用<span lang="EN-US">SimpleDateFormat 类格式化日期，如果日期格式不对，会产生异常。<o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">import java.text.*;<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">import java.util.*;<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">public class TestDate {<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">public static void main(String[] args) {<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">String dStr = "2001.12.12-08.23.21";<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">Date d = null;<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd- HH.mm.ss");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">try {</span><span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt"><o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: blue; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">http://www.54he.com </span><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">何海平<span lang="EN-US">hp54@163.com<o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">d = sdf.parse(dStr);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">} catch (ParseException pe) {<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">System.out.println(pe.getMessage());<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">}<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">System.out.println(d);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">System.out.println(d.getTime());<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">}<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">}<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">在<span lang="EN-US">java.text 包中找到那个SimpleDateFormat 类，给它一个模板，可以parse 成一个Date，然后使用Date<o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">类的<span lang="EN-US">getItme() 方法，可以得到一个Long 数据。<o:p></o:p></span></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt"><font size="4"><strong>3 取得当前日期</strong></font><br />public String GetDateTime()<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">{<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">Calendar cal = Calendar.getInstance();<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">SimpleDateFormat formatter = new SimpleDateFormat("yyyy- MM-dd HH:mm:ss");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">String mDateTime=formatter.format(cal.getTime());<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">return (mDateTime);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">}<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">public java.sql.Date GetDate()<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">{<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">java.sql.Date mDate;<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">Calendar cal = Calendar.getInstance();<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">SimpleDateFormat formatter = new SimpleDateFormat("yyyy- MM-dd HH:mm:ss");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">String mDateTime=formatter.format(cal.getTime());<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">return (java.sql.Date.valueOf(mDateTime));<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">}<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><strong><span lang="EN-US" style="FONT-SIZE: 22pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt"><o:p><font size="4">4 当前时间</font></o:p></span></strong></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">Calendar cal = Calendar.getInstance();<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">// SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM- dd HH:mm:ss");</span><span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt"><o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt"><span lang="EN-US"><o:p></o:p></span></span> </p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss G E D F w W a E F");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">String mDateTime=formatter.format(cal.getTime());<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">out.println(mDateTime);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">out.println("&lt;br&gt;");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><strong><span lang="EN-US" style="FONT-SIZE: 22pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt"><o:p><font size="4">5 一年前日期</font></o:p></span></strong></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">java.util.Date myDate=new java.util.Date();<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">long myTime=(myDate.getTime()/1000)-60*60*24*365;<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">myDate.setTime(myTime*1000);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">String mDate=formatter.format(myDate);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">out.println(mDate);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">out.println("&lt;br&gt;");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><strong><span lang="EN-US" style="FONT-SIZE: 22pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt"><o:p><font size="4">6 明天日期</font></o:p></span></strong></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">myDate=new java.util.Date();<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">myTime=(myDate.getTime()/1000)+60*60*24;<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">myDate.setTime(myTime*1000);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">mDate=formatter.format(myDate);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">out.println(mDate);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">out.println("&lt;br&gt;");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt"><strong><font size="4">7 两个时间之间的天数</font></strong><br />SimpleDateFormat myFormatter = new SimpleDateFormat("yyyy-MM- dd");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">java.util.Date date= myFormatter.parse("2003-05-1");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">java.util.Date mydate= myFormatter.parse("1899-12-30");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">long day=(date.getTime()-mydate.getTime())/(24*60*60*1000);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">out.println(day);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">out.println("&lt;br&gt;");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><strong><span lang="EN-US" style="FONT-SIZE: 22pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt"><o:p><font size="4">8 加半小时</font></o:p></span></strong></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">java.util.Date date1 = format.parse("2002-02-28 23:16:00");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">long Time=(date1.getTime()/1000)+60*30;<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">date1.setTime(Time*1000);</span><span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt"><o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span style="FONT-SIZE: 9pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt"><span lang="EN-US"><o:p></o:p></span></span> </p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">String mydate1=formatter.format(date1);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">out.println(mydate1);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">out.println("&lt;br&gt;");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><strong><span lang="EN-US" style="FONT-SIZE: 22pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt"><o:p><font size="4">9 年月周求日期</font></o:p></span></strong></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM F E");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">java.util.Date date2= formatter2.parse("2003-05 5 星期五");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">SimpleDateFormat formatter3 = new SimpleDateFormat("yyyy-MM-dd");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">String mydate2=formatter3.format(date2);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">out.println(mydate2);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">out.println("&lt;br&gt;");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><strong><span lang="EN-US" style="FONT-SIZE: 22pt; COLOR: black; FONT-FAMILY: SimSun; mso-font-kerning: 0pt"><o:p><font size="4">10 求给定日期是星期几</font></o:p></span></strong></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">mydate= myFormatter.parse("2001-1-1");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">SimpleDateFormat formatter4 = new SimpleDateFormat("E");<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">String mydate3=formatter4.format(mydate);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">out.println(mydate3);<o:p></o:p></span></p><p class="MsoNormal" style="MARGIN: 0mm 0mm 0pt; TEXT-ALIGN: left; mso-layout-grid-align: none" align="left"><span lang="EN-US" style="FONT-SIZE: 9pt; COLOR: #333333; FONT-FAMILY: SimSun; mso-font-kerning: 0pt">out.println("&lt;br&gt;");<o:p></o:p></span></p><img src ="http://www.blogjava.net/matthew2006/aggbug/58325.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-07-15 14:52 <a href="http://www.blogjava.net/matthew2006/archive/2006/07/15/58325.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>常见java面试题</title><link>http://www.blogjava.net/matthew2006/archive/2006/06/29/55813.html</link><dc:creator>matthew</dc:creator><author>matthew</author><pubDate>Thu, 29 Jun 2006 12:08:00 GMT</pubDate><guid>http://www.blogjava.net/matthew2006/archive/2006/06/29/55813.html</guid><wfw:comment>http://www.blogjava.net/matthew2006/comments/55813.html</wfw:comment><comments>http://www.blogjava.net/matthew2006/archive/2006/06/29/55813.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/matthew2006/comments/commentRss/55813.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/matthew2006/services/trackbacks/55813.html</trackback:ping><description><![CDATA[
		<p>Java基础方面:</p>
		<p>1,作用域public,protected,private,以及不写时的区别</p>
		<p>          <font color="#0033ff">作用域    </font>                  <font color="#0033ff">当前类               同一package             子孙类            其他package </font></p>
		<p>
				<font color="#0033ff">           </font>
				<font color="#cc3333">public                           √                         √                         √                        √</font>
		</p>
		<p>
				<font color="#cc3333">          </font>
				<font color="#cc3333"> protected                       √                        √                         √                         ×</font>
		</p>
		<p>
				<font color="#cc3333">         </font>
				<font color="#cc3366"> friendly                          √                         √                         ×                         ×</font>
		</p>
		<p>
				<font color="#cc3366">        </font>
				<font color="#993333">  private                            √                         ×                        ×                          ×</font>
		</p>
		<p>
				<font color="#993333">          不写时默认为friendly <br /></font>
		</p>
		<p>2,ArrayList和Vector的区别,HashMap和Hashtable的区别</p>
		<p>
				<font color="#0033ff">答：就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 </font>
		</p>
		<p>3,char型变量能不能定义为一个中文?为什么?</p>
		<p>
				<font color="#0033ff">是能够定义成为一个中文的，因为java中以unicode编码，一个char占16个字节，所以放一个中文是没问题的 <br /></font>
		</p>
		<p>4,多线程有几种表示方法,都是什么?同步有几种实现方法,都是什么?</p>
		<p>
				<font color="#0033ff">多线程有两种实现方法，分别是继承Thread类与实现Runnable接口 <br />同步的实现方面有一种，使用synchronized,wait,notify <br /></font>
		</p>
		<p>5,继承时候类的执行顺序问题,一般都是选择题,问你将会打印出什么?</p>
		<p>6,内部类的实现方式?</p>
		<p>7,垃圾回收机制,如何优化程序?</p>
		<p>8,float型float f=3.4是否正确?</p>
		<p>Jsp方面</p>
		<p>1,jsp有哪些内置对象?作用分别是什么?</p>
		<p>2,jsp有哪些动作?作用分别是什么?</p>
		<p>3,include的两种实现方式的区别?</p>
		<p>4,两种跳转方式分别是什么?有什么区别?</p>
		<p>Servlet方面</p>
		<p>1,说一说Servlet的生命周期?</p>
		<p>2,Servlet版本间(忘了问的是哪两个版本了)的不同?</p>
		<p>Jdbc,Jdo方面</p>
		<p>1,可能会让你写一段Jdbc连Oracle的程序.</p>
		<p>2,Class.forName的作用?为什么要用?</p>
		<p>3,Jdo是什么?</p>
		<p>
				<font color="#0000ff">JDO是Java对象持久化的规范之一，为java data object的简称,是一个用于存取某种数据仓库中的对象的标准化API。JDO提供了透明的对象存储，因此对开发人员来说，存储数据对象完全不需要额外的代码（如JDBC API的使用）。这些繁琐的例行工作已经转移到JDO产品提供商身上，使开发人员解脱出来，从而集中时间和精力在业务逻辑上。另外，JDO很灵活，因为它可以在任何数据底层上运行。JDBC只是面向关系数据库（RDBMS)JDO更通用，提供到任何数据底层的存储功能，比如关系数据库、文件、XML以及对象数据库（ODBMS）等等，使得应用可移植性更强。</font>
		</p>
		<p>Xml方面</p>
		<p>1,xml有哪些解析技术?区别是什么?</p>
		<p>
				<font color="#0000cc">DOM:处理大型文件时其性能下降的非常厉害。这个问题是由DOM的树结构所造成的，这种结构占用的内存较多，而且DOM必须在解析文件之前把整个文档装入内存,适合对XML的随机访问</font>
		</p>
		<p>
				<font color="#0000cc">SAX:不现于DOM,SAX是事件驱动型的XML解析方式。它顺序读取XML文件，不需要一次全部装载整个文件。当遇到像文件开头，文档结束，或者标签开头与标签结束时，它会触发一个事件，用户通过在其回调事件中写入处理代码来处理XML文件，适合对XML的顺序访问 </font>
		</p>
		<p>
				<font color="#0000cc">
						<br />STAX:Streaming API for XML (StAX)</font>
		</p>
		<p>2,你在项目中用到了xml技术的哪些方面?如何实现的?</p>
		<p>
				<font color="#0000ff">用到了数据存贮，信息配置两方面。在做数据交换平台时，将不同数据源的数据组装成XML文件，然后将XML文件压缩打包加密后通过网络传送给接收者，接收解密与解压缩后再同XML文件中还原相关信息进行处理。在做软件配置时，利用XML可以很方便的进行，软件的各种配置参数都存贮在XML文件中。</font>
				<br />
		</p>
		<p>3,用jdom解析xml文件时如何解决中文问题?如何解析?</p>
		<p>EJB方面</p>
		<p>1,EJB2.0有哪些内容?分别用在什么场合? EJB2.0和EJB1.1的区别?</p>
		<p>MVC方面</p>
		<p>1,MVC的各个部分都有那些技术来实现?如何实现?</p>
		<p>设计模式方面:</p>
		<p>1,开发中都用到了那些设计模式?用在什么场合?</p>
		<p>JavaScript方面</p>
		<p>      1,如何校验数字型?</p>
		<p>CORBA</p>
		<p>      1,CORBA是什么?用途是什么?</p>
		<p> </p>
		<p>以上就是我的总结,可能不是全部,因为时间问题,如果能够记起来,我会再加上,有些问题描述的可能不准确,希望大家批评指正,问题都很基础,即使不知道,花上一点时间查找(csdn/java版)就能弄懂,希望对正在找工作的朋友有所帮助,有所提醒.一份正确率很高的笔试卷可能会为你的面试减轻负担,少问不少问题.</p>
		<p>当然我还是要提醒从<br /></p>
		<h2 align="center">
				<a id="viewpost" href="http://blog.csdn.net/doodoofish/archive/2004/07/12/39841.aspx">
						<font style="BACKGROUND-COLOR: #f5f5dc" color="#800080">
								<u>Java陷阱一箩筐----面试题集</u>
						</font>
				</a>
		</h2>
		<p>找工作要面试，有面试就有对付面试的办法。以下一些题目来自我和我朋友痛苦的面试经历，提这些问题的公司包括IBM, E*Trade, Siebel, Motorola, SUN, 以及其它大小公司。<br /><br />面试是没什么道理可讲的，它的题目有的不合情理、脱离实际。有在纸上写的，有当面考你的，也有在电话里问的，给你IDE的估计很少(否则你赶快去买彩票， 说不定中)。所以如果你看完此文后，请不要抱怨说这些问题都能用IDE来解决。你必须在任何情况下准确回答这些问题，在面试中如果出现一两题回答不准确很 有可能你就被拒之门外了。<br /><br />当然这些都是Java的基本题，那些面试的人大多数不会问你Hibernate有多先进，Eclipse的三个组成部分，或command design pattern，他们都是老一辈了，最喜欢问的就是基础知识。别小看了这些基础，我朋友水平一流，结果就栽在一到基础知识的问题下，和高薪无缘。<br /><br />好了废话少说，开始正题。<br /><br />第一，谈谈final, finally, finalize的区别。<br />最常被问到。</p>
		<p>
				<font color="#0033ff">final—修饰符（关键字）如果一个类被声明为final，意味着它不能再派生出新的子类，不能作为父类被继承。因此一个类不能既被声明为 abstract的，又被声明为final的。将变量或方法声明为final，可以保证它们在使用中不被改变。被声明为final的变量必须在声明时给定初值，而在以后的引用中只能读取，不可修改。被声明为final的方法也同样只能使用，不能重载 <br />finally—再异常处理时提供 finally 块来执行任何清除操作。如果抛出一个异常，那么相匹配的 catch 子句就会执行，然后控制就会进入 finally 块（如果有的话）。 <br />finalize—方法名。Java 技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在 Object 类中定义的，因此所有的类都继承了它。子类覆盖 finalize() 方法以整理系统资源或者执行其他清理工作。finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。 <br /><br /></font>
				<br />第二，Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类，是否可以implements(实现)interface(接口)?<br /></p>
		<p>
				<font color="#0033ff">匿名的内部类是没有名字的内部类。不能extends(继承) 其它类，但一个内部类可以作为一个接口，由另一个内部类实现。</font>
		</p>
		<p>
				<br />第三，Static Nested Class 和 Inner Class的不同，说得越多越好(面试题有的很笼统)。</p>
		<p> </p>
		<p>
				<font color="#0033ff">Nested Class （一般是C++的说法），Inner Class (一般是JAVA的说法)。Java内部类与C++嵌套类最大的不同就在于是否有指向外部的引用上。具体可见http: //www.frontfree.net/articles/services/view.asp?id=704&amp;page=1 <br />注： 静态内部类（Inner Class）意味着1创建一个static内部类的对象，不需要一个外部类对象，2不能从一个static内部类的一个对象访问一个外部类对象 <br /><br /></font>
				<br />第四，&amp;和&amp;&amp;的区别。<br />这个问得很少。</p>
		<p>
				<font color="#0033ff">&amp;是位运算符。&amp;&amp;是布尔逻辑运算符。<br /></font>
				<br />第五，HashMap和Hashtable的区别。<br />常问。</p>
		<p>
				<font color="#0033ff">都属于Map接口的类，实现了将惟一键映射到特定的值上。 <br />HashMap 类没有分类或者排序。它允许一个 null 键和多个 null 值。 <br />Hashtable 类似于 HashMap，但是不允许 null 键和 null 值。它也比 HashMap 慢，因为它是同步的。<br /></font>
				<br />第六，Collection 和 Collections的区别。<br />你千万别说一个是单数一个是复数。</p>
		<p>
				<font color="#0033ff">Collections是个java.util下的类，它包含有各种有关集合操作的静态方法。 <br />Collection是个java.util下的接口，它是各种集合结构的父接口。 <br /></font>
				<br />
				<br />第七，什么时候用assert。<br />API级的技术人员有可能会问这个。</p>
		<p>
				<font color="#0033ff">断言是一个包含布尔表达式的语句，在执行这个语句时假定该表达式为 true。如果表达式计算为 false，那么系统会报告一个 AssertionError。它用于调试目的： <br />assert(a &gt; 0); // throws an AssertionError if a &lt;= 0 <br />断言可以有两种形式： <br />assert Expression1 ; <br />assert Expression1 : Expression2 ; <br />Expression1 应该总是产生一个布尔值。 <br />Expression2 可以是得出一个值的任意表达式。这个值用于生成显示更多调试信息的 String 消息。 <br />断言在默认情况下是禁用的。要在编译时启用断言，需要使用 source 1.4 标记： <br />javac -source 1.4 Test.java <br />要在运行时启用断言，可使用 -enableassertions 或者 -ea 标记。 <br />要在运行时选择禁用断言，可使用 -da 或者 -disableassertions 标记。 <br />要系统类中启用断言，可使用 -esa 或者 -dsa 标记。还可以在包的基础上启用或者禁用断言。 <br />可以在预计正常情况下不会到达的任何位置上放置断言。断言可以用于验证传递给私有方法的参数。不过，断言不应该用于验证传递给公有方法的参数，因为不管是否启用了断言，公有方法都必须检查其参数。不过，既可以在公有方法中，也可以在非公有方法中利用断言测试后置条件。另外，断言不应该以任何方式改变程序的状态。 <br /></font>
				<br />
				<br />第八，GC是什么? 为什么要有GC? <br />基础。<br /></p>
		<p>
				<font color="#0033cc">GC是垃圾收集器。Java 程序员不用担心内存管理，因为垃圾收集器会自动进行管理。要请求垃圾收集，可以调用下面的方法之一： <br />System.gc() <br />Runtime.getRuntime().gc() <br /></font>
				<br />第九，String s = new String("xyz");创建了几个String Object?</p>
		<p>
				<font color="#0033ff">问题太bt,偶不回答，考<br /></font>
				<br />第十，Math.round(11.5)等於多少? Math.round(-11.5)等於多少?</p>
		<p>
				<font color="#0033ff">Math.round(11.5)返回（long）12，Math.round(-11.5)返回（long）-11; <br /></font>
				<br />第十一，short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?<br />面试题都是很变态的，要做好受虐的准备。</p>
		<p>
				<font color="#0033ff">short s1 = 1; s1 = s1 + 1;有错，s1是short型，s1+1是int型,不能显式转化为short型。可修改为s1 =(short)(s1 + 1) 。short s1 = 1; s1 += 1正确。？？<br /><br /></font>第十二，sleep() 和 wait() 有什么区别?<br />搞线程的最爱。</p>
		<p>
				<font color="#0033ff">sleep()方法是使线程停止一段时间的方法。在sleep 时间间隔期满后，线程不一定立即恢复执行。这是因为在那个时刻，其它线程可能正在运行而且没有被调度为放弃执行，除非(a)“醒来”的线程具有更高的优先级 <br />(b)正在运行的线程因为其它原因而阻塞。 <br />wait()是线程交互时，如果线程对一个同步对象x 发出一个wait()调用，该线程会暂停执行，被调对象进入等待状态，直到被唤醒或等待时间到。 <br /><br /></font>
				<br />第十三，Java有没有goto?<br />很十三的问题，如果哪个面试的问到这个问题，我劝你还是别进这家公司。</p>
		<p>
				<font color="#0033ff">Goto—java中的保留字，现在没有在java中使用。</font>
				<br />
				<br />第十四，数组有没有length()这个方法? String有没有length()这个方法?</p>
		<p>
				<font color="#0033ff">数组没有length()这个方法，有length的属性。 <br />String有有length()这个方法。 <br /></font>
				<br />
				<br />第十五，Overload和Override的区别。Overloaded的方法是否可以改变返回值的类型?<br />常问。</p>
		<p>
				<font color="#0033ff">方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现，重载Overloading是一个类中多态性的一种表现。如果在子类中定义某方法与其父类有相同的名称和参数，我们说该方法被重写 (Overriding)。子类的对象使用这个方法时，将调用子类中的定义，对它而言，父类中的定义如同被“屏蔽”了。如果在一个类中定义了多个同名的方法，它们或有不同的参数个数或有不同的参数类型，则称为方法的重载(Overloading)。Overloaded的方法是可以改变返回值的类型。 <br /></font>
				<br />
				<br />第十六，Set里的元素是不能重复的，那么用什么方法来区分重复与否呢? 是用==还是equals()? 它们有何区别?</p>
		<p>
				<font color="#0033ff">Set里的元素是不能重复的，那么用iterator()方法来区分重复与否。equals()是判读两个Set是否相等。 <br />equals()和==方法决定引用值是否指向同一对象equals()在类中被覆盖，为的是当两个分离的对象的内容和类型相配的话，返回真值。 （不知所云）<br /><br /></font>
				<br />第十七，给我一个你最常见到的runtime exception。<br />如果你这个答不出来，面试的人会认为你没有实际编程经验。</p>
		<p>
				<font color="#0033ff">ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException, EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException, <br />ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFormatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException <br /></font>
				<br />
				<br />第十八，error和exception有什么区别?</p>
		<p>
				<font color="#0033ff">error 表示恢复不是不可能但很困难的情况下的一种严重问题。比如说内存溢出。不可能指望程序能处理这样的情况。 <br />exception 表示一种设计或实现问题。也就是说，它表示如果程序运行正常，从不会发生的情况</font>。<br /><br />第十九，List, Set, Map是否继承自Collection接口?</p>
		<p>
				<font color="#0033ff">List，Set是 <br /><br />Map不是 <br /></font>
				<br />
				<br />第二十，abstract class和interface有什么区别?<br />常问。</p>
		<p>
				<font color="#0033ff">声明方法的存在而不去实现它的类被叫做抽象类（abstract class），它用于要创建一个体现某些基本行为的类，并为该类声明方法，但不能在该类中实现该类的情况。不能创建abstract 类的实例。然而可以创建一个变量，其类型是一个抽象类，并让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract 类的子类为它们父类中的所有抽象方法提供实现，否则它们也是抽象类为。取而代之，在子类中实现该方法。知道其行为的其它类可以在类中实现这些方法。 <br />接口（interface）是抽象类的变体。在接口中，所有方法都是抽象的。多继承性可通过实现这样的接口而获得。接口中的所有方法都是抽象的，没有一个有程序体。接口只可以定义static final成员变量。接口的实现与子类相似，除了该实现类不能从接口定义中继承行为。当类实现特殊接口时，它定义（即将程序体给予）所有这种接口的方法。然后，它可以在实现了该接口的类的任何对象上调用接口的方法。由于有抽象类，它允许使用接口名作为引用变量的类型。通常的动态联编将生效。引用可以转换到接口类型或从接口类型转换，instanceof 运算符可以用来决定某对象的类是否实现了接口。</font>
				<br />
				<br />
				<br />第二十一，abstract的method是否可同时是static,是否可同时是native，是否可同时是synchronized?</p>
		<p>
				<font color="#0000cc">不能</font>
				<br />
				<br />
				<br />第二十二，接口是否可继承接口? 抽象类是否可实现(implements)接口? 抽象类是否可继承实体类(concrete class)?</p>
		<p>
				<font color="#0000cc">接口可以继承接口。抽象类可以实现(implements)接口，抽象类是否可继承实体类，但前提是实体类必须有明确的构造函数。 <br /></font>
				<br />
				<br />第二十三，启动一个线程是用run()还是start()?</p>
		<p>
				<font color="#0000cc">启动一个线程是调用start()方法，使线程所代表的虚拟处理机处于可运行状态，这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法实执行的内容。</font>
				<br />
				<br />第二十四，构造器Constructor是否可被override?</p>
		<p>
				<font color="#0000cc">构造器Constructor不能被继承，因此不能重写Overriding，但可以被重载Overloading。</font>
				<br />
				<br />第二十五，是否可以继承String类?<br /><br />第二十六，当一个线程进入一个对象的一个synchronized方法后，其它线程是否可进入此对象的其它方法?<br /><br />第二十七，try {}里有一个return语句，那么紧跟在这个try后的finally {}里的code会不会被执行，什么时候被执行，在return前还是后?<br /><br />第二十八，编程题: 用最有效率的方法算出2乘以8等於几?<br />有C背景的程序员特别喜欢问这种问题。<br /><br />第二十九，两个对象值相同(x.equals(y) == true)，但却可有不同的hash code，这句话对不对?<br /><br />第三十，当一个对象被当作参数传递到一个方法后，此方法可改变这个对象的属性，并可返回变化后的结果，那么这里到底是值传递还是引用传递?<br /><br />第三十一，swtich是否能作用在byte上，是否能作用在long上，是否能作用在String上?<br /><br />第三十二，编程题: 写一个Singleton出来。<br /></p>
<img src ="http://www.blogjava.net/matthew2006/aggbug/55813.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/matthew2006/" target="_blank">matthew</a> 2006-06-29 20:08 <a href="http://www.blogjava.net/matthew2006/archive/2006/06/29/55813.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>