﻿<?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/xxxzheng/category/1781.html</link><description>路慢慢其休远兮,吾将上下而求素</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 12:36:05 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 12:36:05 GMT</pubDate><ttl>60</ttl><item><title>一些简单得JAVA小程序</title><link>http://www.blogjava.net/xxxzheng/archive/2005/12/01/22138.html</link><dc:creator>Steve</dc:creator><author>Steve</author><pubDate>Thu, 01 Dec 2005 09:49:00 GMT</pubDate><guid>http://www.blogjava.net/xxxzheng/archive/2005/12/01/22138.html</guid><wfw:comment>http://www.blogjava.net/xxxzheng/comments/22138.html</wfw:comment><comments>http://www.blogjava.net/xxxzheng/archive/2005/12/01/22138.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xxxzheng/comments/commentRss/22138.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xxxzheng/services/trackbacks/22138.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 一个简单的Java应用程序public class Hello{ &nbsp;&nbsp;&nbsp;&nbsp;public static void main (String args[ ])&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println("这是一个简单的应用程序");&nbsp;&...&nbsp;&nbsp;<a href='http://www.blogjava.net/xxxzheng/archive/2005/12/01/22138.html'>阅读全文</a><img src ="http://www.blogjava.net/xxxzheng/aggbug/22138.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xxxzheng/" target="_blank">Steve</a> 2005-12-01 17:49 <a href="http://www.blogjava.net/xxxzheng/archive/2005/12/01/22138.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>连接数据库大全</title><link>http://www.blogjava.net/xxxzheng/archive/2005/12/01/22135.html</link><dc:creator>Steve</dc:creator><author>Steve</author><pubDate>Thu, 01 Dec 2005 09:46:00 GMT</pubDate><guid>http://www.blogjava.net/xxxzheng/archive/2005/12/01/22135.html</guid><wfw:comment>http://www.blogjava.net/xxxzheng/comments/22135.html</wfw:comment><comments>http://www.blogjava.net/xxxzheng/archive/2005/12/01/22135.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xxxzheng/comments/commentRss/22135.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xxxzheng/services/trackbacks/22135.html</trackback:ping><description><![CDATA[Java数据库连接（JDBC）由一组用 Java 编程语言编写的类和接口组成。JDBC 为工具/数据库开发人员提供了一个标准的 API，使他们能够用纯Java API 来编写数据库应用程序。然而各个开发商的接口并不完全相同，所以开发环境的变化会带来一定的配置变化。本文主要集合了不同数据库的连接方式。<BR><BR>　　一、连接各种数据库方式速查表<BR><BR>　　下面罗列了各种数据库使用JDBC连接的方式，可以作为一个手册使用。<BR><BR>　　1、Oracle8/8i/9i数据库（thin模式）<BR><BR>Class.forName(“oracle.jdbc.driver.OracleDriver“).newInstance();<BR>String url=“jdbc:oracle:thin:@localhost:1521:orcl“; //orcl为数据库的SID<BR>String user=“test“;<BR>String password=“test“;<BR>Connection conn= DriverManager.getConnection(url,user,password);<BR><BR>　　2、DB2数据库<BR>Class.forName(“com.ibm.db2.jdbc.app.DB2Driver “).newInstance();<BR>String url=“jdbc:db2://localhost:5000/sample“; //sample为你的数据库名<BR>String user=“admin“;<BR>String password=““;<BR>Connection conn= DriverManager.getConnection(url,user,password);<BR><BR>　　3、Sql Server7.0/2000数据库<BR>Class.forName(“com.microsoft.jdbc.sqlserver.SQLServerDriver“).newInstance();<BR>String url=“jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb“;<BR>//mydb为数据库<BR>String user=“sa“;<BR>String password=““;<BR>Connection conn= DriverManager.getConnection(url,user,password);<BR><BR>　　4、Sybase数据库<BR>Class.forName(“com.sybase.jdbc.SybDriver“).newInstance();<BR>String url =“ jdbc:sybase:Tds:localhost:5007/myDB“;//myDB为你的数据库名<BR>Properties sysProps = System.getProperties();<BR>SysProps.put(“user“,“userid“);<BR>SysProps.put(“password“,“user_password“);<BR>Connection conn= DriverManager.getConnection(url, SysProps);<BR>　5、Informix数据库<BR>Class.forName(“com.informix.jdbc.IfxDriver“).newInstance();<BR>String url = “jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver;<BR>user=testuser;password=testpassword“; //myDB为数据库名<BR>Connection conn= DriverManager.getConnection(url);<BR><BR>　　6、MySQL数据库<BR>Class.forName(“org.gjt.mm.mysql.Driver“).newInstance();<BR>String url =“jdbc:mysql://localhost/myDB?user=soft&amp;password=soft1234&amp;useUnicode=true&amp;characterEncoding=8859_1“<BR>//myDB为数据库名<BR>Connection conn= DriverManager.getConnection(url);<BR><BR>　　7、PostgreSQL数据库<BR>Class.forName(“org.postgresql.Driver“).newInstance();<BR>String url =“jdbc:postgresql://localhost/myDB“ //myDB为数据库名<BR>String user=“myuser“;<BR>String password=“mypassword“;<BR>Connection conn= DriverManager.getConnection(url,user,password);<BR><BR>　　8、access数据库直连用ODBC的<BR>Class.forName(“sun.jdbc.odbc.JdbcOdbcDriver“) ;<BR>String url=“jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ=“+application.getRealPath(“/Data/ReportDemo.mdb“);<BR>Connection conn = DriverManager.getConnection(url,““,“”);<BR>Statement stmtNew=conn.createStatement() ;<BR><BR>　　二、JDBC连接MySql方式<BR><BR>　　下面是使用JDBC连接MySql的一个小的教程<BR><BR>　　1、查找驱动程序<BR><BR>　　MySQL目前提供的java驱动程序为Connection/J，可以从MySQL官方网站下载，并找到mysql-connector-java-3.0.15-ga-bin.jar文件，此驱动程序为纯java驱动程序，不需做其他配置。<BR>2、动态指定classpath<BR><BR>　　如果需要执行时动态指定classpath，就在执行时采用－cp方式。否则将上面的.jar文件加入到classpath环境变量中。<BR><BR>　　3、加载驱动程序<BR>try{<BR>　Class.forName(com.mysql.jdbc.Driver);<BR>　System.out.println(Success loading Mysql Driver!);<BR>}catch(Exception e)<BR>{<BR><BR>　System.out.println(Error loading Mysql Driver!);<BR>　e.printStackTrace();<BR>}<BR><BR>　　4、设置连接的url<BR><BR>jdbc：mysql：//localhost/databasename[?pa=va][＆pa=va]<BR><BR>　　三、以下列出了在使用JDBC来连接Oracle数据库时可以使用的一些技巧<BR><BR>　　1、在客户端软件开发中使用Thin驱动程序<BR><BR>　　在开发Java软件方面，Oracle的数据库提供了四种类型的驱动程序，二种用于应用软件、applets、servlets等客户端软件，另外二种用于数据库中的Java存储过程等服务器端软件。在客户机端软件的开发中，我们可以选择OCI驱动程序或Thin驱动程序。OCI驱动程序利用Java本地化接口（JNI），通过Oracle客户端软件与数据库进行通讯。Thin驱动程序是纯Java驱动程序，它直接与数据库进行通讯。为了获得最高的性能，Oracle建议在客户端软件的开发中使用OCI驱动程序，这似乎是正确的。但我建议使用Thin驱动程序，因为通过多次测试发现，在通常情况下，Thin驱动程序的性能都超过了OCI驱动程序。<BR><BR>　　2、关闭自动提交功能，提高系统性能<BR><BR>　　在第一次建立与数据库的连接时，在缺省情况下，连接是在自动提交模式下的。为了获得更好的性能，可以通过调用带布尔值false参数的Connection类的setAutoCommit()方法关闭自动提交功能，如下所示：<BR>　　conn.setAutoCommit(false);<BR><BR>　　值得注意的是，一旦关闭了自动提交功能，我们就需要通过调用Connection类的commit()和rollback()方法来人工的方式对事务进行管理。<BR>3、在动态SQL或有时间限制的命令中使用Statement对象<BR><BR>　　在执行SQL命令时，我们有二种选择：可以使用PreparedStatement对象，也可以使用Statement对象。无论多少次地使用同一个SQL命令，PreparedStatement都只对它解析和编译一次。当使用Statement对象时，每次执行一个SQL命令时，都会对它进行解析和编译。这可能会使你认为，使用PreparedStatement对象比使用Statement对象的速度更快。然而，我进行的测试表明，在客户端软件中，情况并非如此。因此，在有时间限制的SQL操作中，除非成批地处理SQL命令，我们应当考虑使用Statement对象。<BR><BR>　　此外，使用Statement对象也使得编写动态SQL命令更加简单，因为我们可以将字符串连接在一起，建立一个有效的SQL命令。因此，我认为，Statement对象可以使动态SQL命令的创建和执行变得更加简单。<BR><BR>　　4、利用helper函数对动态SQL命令进行格式化<BR><BR>　　在创建使用Statement对象执行的动态SQL命令时，我们需要处理一些格式化方面的问题。例如，如果我们想创建一个将名字O‘Reilly插入表中的SQL命令，则必须使用二个相连的“‘‘”号替换O‘Reilly中的“‘”号。完成这些工作的最好的方法是创建一个完成替换操作的helper方法，然后在连接字符串心服用公式表达一个SQL命令时，使用创建的helper方法。与此类似的是，我们可以让helper方法接受一个Date型的值，然后让它输出基于Oracle的to_date()函数的字符串表达式。<BR><BR>　　5、利用PreparedStatement对象提高数据库的总体效率<BR><BR>　　在使用PreparedStatement对象执行SQL命令时，命令被数据库进行解析和编译，然后被放到命令缓冲区。然后，每当执行同一个PreparedStatement对象时，它就会被再解析一次，但不会被再次编译。在缓冲区中可以发现预编译的命令，并且可以重新使用。在有大量用户的企业级应用软件中，经常会重复执行相同的SQL命令，使用PreparedStatement对象带来的编译次数的减少能够提高数据库的总体性能。如果不是在客户端创建、预备、执行PreparedStatement任务需要的时间长于Statement任务，我会建议在除动态SQL命令之外的所有情况下使用PreparedStatement对象。<BR><BR>　　6、在成批处理重复的插入或更新操作中使用PreparedStatement对象<BR><BR>　　如果成批地处理插入和更新操作，就能够显著地减少它们所需要的时间。Oracle提供的Statement和 CallableStatement并不真正地支持批处理，只有PreparedStatement对象才真正地支持批处理。我们可以使用addBatch()和executeBatch()方法选择标准的JDBC批处理，或者通过利用PreparedStatement对象的setExecuteBatch()方法和标准的executeUpdate()方法选择速度更快的Oracle专有的方法。要使用Oracle专有的批处理机制，可以以如下所示的方式调用setExecuteBatch()：<BR>PreparedStatement pstmt3D null;<BR>try {<BR>　((OraclePreparedStatement)pstmt).setExecuteBatch(30);<BR>　...<BR>　pstmt.executeUpdate();<BR>}<BR><BR>　　调用setExecuteBatch()时指定的值是一个上限，当达到该值时，就会自动地引发SQL命令执行，标准的executeUpdate()方法就会被作为批处理送到数据库中。我们可以通过调用PreparedStatement类的sendBatch()方法随时传输批处理任务。<BR>7、使用Oracle locator方法插入、更新大对象（LOB）<BR><BR>　　Oracle的PreparedStatement类不完全支持BLOB和CLOB等大对象的处理，尤其是Thin驱动程序不支持利用PreparedStatement对象的setObject()和setBinaryStream()方法设置BLOB的值，也不支持利用setCharacterStream()方法设置CLOB的值。只有locator本身中的方法才能够从数据库中获取LOB类型的值。可以使用PreparedStatement对象插入或更新LOB，但需要使用locator才能获取LOB的值。由于存在这二个问题，因此，我建议使用locator的方法来插入、更新或获取LOB的值。<BR><BR>　　8、使用SQL92语法调用存储过程<BR><BR>　　在调用存储过程时，我们可以使用SQL92或Oracle PL/SQL，由于使用Oracle PL/SQL并没有什么实际的好处，而且会给以后维护你的应用程序的开发人员带来麻烦，因此，我建议在调用存储过程时使用SQL92。<BR><BR>　　9、使用Object SQL将对象模式转移到数据库中<BR><BR>　　既然可以将Oracle的数据库作为一种面向对象的数据库来使用，就可以考虑将应用程序中的面向对象模式转到数据库中。目前的方法是创建Java bean作为伪装的数据库对象，将它们的属性映射到关系表中，然后在这些bean中添加方法。尽管这样作在Java中没有什么问题，但由于操作都是在数据库之外进行的，因此其他访问数据库的应用软件无法利用对象模式。如果利用Oracle的面向对象的技术，可以通过创建一个新的数据库对象类型在数据库中模仿其数据和操作，然后使用JPublisher等工具生成自己的Java bean类。如果使用这种方式，不但Java应用程序可以使用应用软件的对象模式，其他需要共享你的应用中的数据和操作的应用软件也可以使用应用软件中的对象模式。<BR><BR>　　10、利用SQL完成数据库内的操作<BR><BR>　　我要向大家介绍的最重要的经验是充分利用SQL的面向集合的方法来解决数据库处理需求，而不是使用Java等过程化的编程语言。<BR><BR>　　如果编程人员要在一个表中查找许多行，结果中的每个行都会查找其他表中的数据，最后，编程人员创建了独立的UPDATE命令来成批地更新第一个表中的数据。与此类似的任务可以通过在set子句中使用多列子查询而在一个UPDATE命令中完成。当能够在单一的SQL命令中完成任务，何必要让数据在网上流来流去的？我建议用户认真学习如何最大限度地发挥SQL的功能<BR><img src ="http://www.blogjava.net/xxxzheng/aggbug/22135.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xxxzheng/" target="_blank">Steve</a> 2005-12-01 17:46 <a href="http://www.blogjava.net/xxxzheng/archive/2005/12/01/22135.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>非常不错的SCJP真题回忆</title><link>http://www.blogjava.net/xxxzheng/archive/2005/11/30/22007.html</link><dc:creator>Steve</dc:creator><author>Steve</author><pubDate>Wed, 30 Nov 2005 09:08:00 GMT</pubDate><guid>http://www.blogjava.net/xxxzheng/archive/2005/11/30/22007.html</guid><wfw:comment>http://www.blogjava.net/xxxzheng/comments/22007.html</wfw:comment><comments>http://www.blogjava.net/xxxzheng/archive/2005/11/30/22007.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xxxzheng/comments/commentRss/22007.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xxxzheng/services/trackbacks/22007.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: PART 11.public static void main(String args[]) { Boolean a[]=new Boolean[4]; int I= 1; System.out.println(a[I]); } What will be printed? Compilation Error in Line 2 Compilation Error in line 4 Excepti...&nbsp;&nbsp;<a href='http://www.blogjava.net/xxxzheng/archive/2005/11/30/22007.html'>阅读全文</a><img src ="http://www.blogjava.net/xxxzheng/aggbug/22007.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xxxzheng/" target="_blank">Steve</a> 2005-11-30 17:08 <a href="http://www.blogjava.net/xxxzheng/archive/2005/11/30/22007.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>问题集锦：Servlets/JSP开发技术问答</title><link>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21997.html</link><dc:creator>Steve</dc:creator><author>Steve</author><pubDate>Wed, 30 Nov 2005 08:56:00 GMT</pubDate><guid>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21997.html</guid><wfw:comment>http://www.blogjava.net/xxxzheng/comments/21997.html</wfw:comment><comments>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21997.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xxxzheng/comments/commentRss/21997.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xxxzheng/services/trackbacks/21997.html</trackback:ping><description><![CDATA[　<B>为什么GenericServlet在init(ServletConfig config)基础上增加了一个init()方法？</B><BR>　　<BR>　　init()方法被GenericServlet.init(ServletConfig config)方法调用。<BR>　　<BR>　　init()方法方便了开发人员定制Servlet的初始化，而无须去维护ServletConfig对象的存储工作。<BR>　　<BR>　　重写GenericServlet.init(ServletConfig config)必须要显示的调用super.init(config)方法。<BR>　　<BR>　　<B>ServletContext.getContect(java.lang.String uripath)的作用是什么？</B><BR>　　<BR>　　返回同一Server中指定的path对应的ServletContext对象,通过该对象可以实现与Server中的其他Context打交道。<BR>　　<BR>　　uripath必须是以"/"开始（该路径的含义是相对于整个Servlet文档的根路径，而不是当前ServletContext的根路径）。<BR>　　<BR>　　<B>Servlet生命周期是什么？</B><BR>　　<BR>　　一般的Servlet(GenericServlet,即与协议无关的Servlet)的生命周期：init() --&gt; GenericServlet.service(ServletRequest req, ServletResponse res) --&gt; destroy.<BR>　　<BR>　　HttpServlet的生命周期: init() --&gt; GenericServlet.service(ServletRequest req, ServletResponse res)---&gt; service(HttpServletRequest req, HttpServletResponse resp) --&gt; doXXXX()--&gt;destroy.<BR>　　<BR>　　<B>有没有必要重写GenericServlet.service()方法？</B><BR>　　<BR>　　对于HttpServlet来说没有必要。只需要重写它的doXXXX()方法就可以了。HttpServlet中service()方法会自动的根据用户请求类型把请求转发给相应的doXXXX()方法（例如doGet()方法）。<BR>　　<BR>　　ServletRequest.getReader()和ServletRequest.getInputStream()如何使用？<BR>　　<BR>　　注意两个方法不能同时使用。<BR>　　<BR>　　ServletRequest.getRealPath(String path)方法已经不推荐使用。<BR>　　<BR>　　请使用ServletContext.getRealPath(String path)方法。<BR>　　<BR>　　<B>ServletResponse缺省的字符集(charset)是什么?</B><BR>　　<BR>　　ServletResponse缺省的字符集(charset)是ISO-8859-1,可以通过setContentType(java.lang.String)方法改变新的字符集。<BR>　　<BR>　　例如：setContentType("text/html; charset=Shift_JIS").<BR>　　<BR>　　关于字符集信息，可以浏览<A href="http://info.internet.isi.edu/in-notes/rfc/files/rfc2045.txt" target=_blank><FONT color=blue><SPAN class=zhi14>RFC 2045</SPAN></FONT></A><BR>　　<BR>　　<B>HttpServletRequest.getRequestURI()和HttpServletRequest.getRequestURL()区别是什么?<BR>　　</B><BR>　　request.getRequestURI() 返回值类似：/xuejava/requestdemo.jsp<BR>　　<BR>　　request.getRequestURL() 返回值类似：http://localhost:8080/xuejava/requestdemo.jsp<BR>　　<BR>　　HttpServletRequest.encodeURL()和HttpServletRequest.encodeRedirectURL(()区别是什么?为什么要有两个不同的方法呢？<BR>　　<BR>　　当用URL-rewriting方式来管理Session的时候，需要用到以上的两个方法。<BR>　　<BR>　　两个方法的不同点是：两个方法确定是否需要包含session ID的逻辑不同。<BR>　　<BR>　　在调用HttpServletResponse.sendRedirect前，应该先调用encodeRedirectURL()方法，否则可能会丢失Sesssion信息。 ...<BR>　　<BR>　　<B>如何使你的Servlet或者JSP实现Single Thread Model?</B><BR>　　<BR>　　对于Servlet实现javax.single.SingleThreadModel接口。<BR>　　<BR>　　对于JSP,在Page Directive中写如下的语句&lt;%@ page isThreadSafe="false" %&gt;<BR>　　<BR>　　JSP Tag 和 JSP XML-based Tag<BR>　　<BR>　　...<BR>　　<BR>　　<B>如何把某一个JSP Page定义成为Error Page?为什么要这样做？</B><BR>　　<BR>　　实现方法： &lt;%@ page isErrorPage="true" %&gt;<BR>　　<BR>　　为什么？ 因为需要获取Exception 对象（缺省情况下，在JSP Page中是不能直接使用“隐含对象” exception的）。<BR>　　<BR>　　<B>JSP Page的执行顺序是如何的？</B><BR>　　<BR>　　JSP Page的执行顺序如下：<BR>　　<BR>　　JSP Page Translation. JSP Page --&gt; Servlet source code.<BR>　　JSP Page Compilation. Servlet source code --&gt; Servlet class.<BR>　　Load Class(First time or the server restarted)<BR>　　<BR>　　Create instance(可能会很多次，如果JSP Page中声明了&lt;%@ page isThreadSafe="false" %&gt;)<BR>　　<BR>　　Call jspInit method（一般的JSP Page都没有重写这个方法，重写需要在声明语句段中）。<BR>　　<BR>　　Call _jspService method（类似与一般HttpServlet的doGet和doPost方法，但是可以同时用来处理Post和Getq请求）。<BR>　　<BR>　　Call jspDestroy method（Server在卸载Servet的时候，例如当Servlet很久没有使用的情况）。<BR>　　<BR>　　<B>JSP Page中有哪些隐含对象(Implicity Object)?各自的类型和作用是什么？</B><BR>　　<BR>　　request --<BR>　　reponse --<BR>　　session --<BR>　　application --<BR>　　out --<BR>　　page --<BR>　　pagecontext --<BR>　　exception -- 只有在当前JSP Page为Error Page的时候才有效。<BR>　　config --<BR>　　<BR>　　<B>&lt;jsp:include page="/foo/foo.jsp" %&gt; 和 &lt;@ include file="/foo/foo.jsp" %&gt;的区别是什么？<BR>　　</B><BR>　　&lt;jsp:include ... -- request time.<BR>　　&lt;@ include ... -- Page translation time.<BR>　　<BR>　　<B>Servlets/JSP Container(Engine)有几种运行方式？</B><BR>　　<BR>　　Standalone<BR>　　Tomcat standalone mode<BR>　　In-process<BR>　　Tomcat running inside Apache Web Server.<BR>　　Out-of-process<BR>　　Apache + mod_jk + Tomcat<BR>　　<BR>　　Servlet,Servlet开发人员，Servlet API, Servlet Container的关系是什么？<BR>　　<BR>　　Servlet,Servlet开发人员 ---&gt;Servlet API --&gt; Servlet Container<BR>　　The parts of an HTTP message<BR>　　<BR>　　Message part Description<BR>　　The initial line： Specifies the purpose of the request or response message<BR>　　例子：GET /reports/sales/index.html HTTP/1.0<BR>　　The header section:Specifies the meta-information, such as size, type, and encoding,<BR>　　about the content of the message<BR>　　A blank line:<BR>　　An optional message body: The main content of the request or response message<BR>　　<BR>　　下面是一个Response的例子：<BR>　　<BR>　　HTTP/1.0 200 OK<BR>　　Date: Tue, 01 Dec 2001 23:59:59 GMT<BR>　　Content-Type: text/html<BR>　　Content-Length: 52<BR>　　<BR>　　&lt;html&gt;<BR>　　&lt;body&gt;<BR>　　&lt;h1&gt;Hello, John!&lt;/h1&gt;<BR>　　&lt;/body&gt;<BR>　　&lt;/html&gt;<BR>　　<BR>　　<B>HTTP规范中定义了哪些方法？各自有什么用途？</B><BR>　　<BR>　　GET<BR>　　HEAD<BR>　　POST<BR>　　从 Http 1.1规范开始，增加了以下的方法:<BR>　　<BR>　　PUT<BR>　　OPTIONS<BR>　　TRACE<BR>　　DELETE<BR>　　CONNECT<BR>　　<BR>　　ServetRequest中为什么要定义:getContentType(),getContentLength()方法。<BR>　　<BR>　　根据HTTP协议规范，Request 和 Response一样也有这些必不可少的内容！<BR>　　<BR>　　所以需要首先了解 HTTP Message的概念和其内容的格式，这些东西对于Request和Reponse是一样的。<BR>　　<BR>　　对于GET方式发送的请求，其内容类型为：null<BR>　　<BR>　　对于POST方式发送的请求，其内容类型为：application/x-www-form-urlencoded<BR>　　<BR>　　POST方式发送请求的内容类似于：username=xuejava.<BR>　　<BR>　　RequestDispatcher.forward()和HttpServletResponse.sendRedirect()的区别是什么？<BR>　　<BR>　　RequestDispatcher.forward()是在服务器端运行；HttpServletResponse.sendRedirect()是通过向客户浏览器发送命令来完成。<BR>　　<BR>　　所以RequestDispatcher.forward()对于浏览器来说是“透明的”；而HttpServletResponse.sendRedirect()则不是。<BR>　　<BR>　　另外，还要注意RequestDispatcher.forward()在调用的时候Response不能已经Commit了（Response.isCommitted()）。<BR>　　<BR>　　ServletContext.getRequestDispatcher(String url)和ServletRequest.getRequestDispatcher(String url)的区别是什么？为什么？<BR>　　<BR>　　ServletContext.getRequestDispatcher(String url)中的url只能使用绝对路径；而ServletRequest.getRequestDispatcher(String url)中的url可以使用相对路径。<BR>　　<BR>　　因为ServletRequest具有相对路径的概念；而ServletContext对象无次概念。<BR>　　<BR>　　<B>如何把请求转移到另外一个Web App中的某个地址？</B><BR>　　<BR>　　ServletContext.getRequestDispatcher(String url)和ServletRequest.getRequestDispatcher(String url)只能把请求转移到同一个Web App中的地址。<BR>　　<BR>　　如果需要把请求转移到另外一个Web App中的某个地址，可以按下面的做法：<BR>　　<BR>　　1. 获得另外一个Web App的ServletConext对象(currentServletContext.getContext(uripath)).<BR>　　<BR>　　2. 调用ServletContext.getRequestDispatcher(String url)方法。<BR>　　<BR>　　未完待续<img src ="http://www.blogjava.net/xxxzheng/aggbug/21997.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xxxzheng/" target="_blank">Steve</a> 2005-11-30 16:56 <a href="http://www.blogjava.net/xxxzheng/archive/2005/11/30/21997.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>问题集锦：Servlets/JSP开发技术问答</title><link>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21998.html</link><dc:creator>Steve</dc:creator><author>Steve</author><pubDate>Wed, 30 Nov 2005 08:56:00 GMT</pubDate><guid>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21998.html</guid><wfw:comment>http://www.blogjava.net/xxxzheng/comments/21998.html</wfw:comment><comments>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21998.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xxxzheng/comments/commentRss/21998.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xxxzheng/services/trackbacks/21998.html</trackback:ping><description><![CDATA[　<B>为什么GenericServlet在init(ServletConfig config)基础上增加了一个init()方法？</B><BR>　　<BR>　　init()方法被GenericServlet.init(ServletConfig config)方法调用。<BR>　　<BR>　　init()方法方便了开发人员定制Servlet的初始化，而无须去维护ServletConfig对象的存储工作。<BR>　　<BR>　　重写GenericServlet.init(ServletConfig config)必须要显示的调用super.init(config)方法。<BR>　　<BR>　　<B>ServletContext.getContect(java.lang.String uripath)的作用是什么？</B><BR>　　<BR>　　返回同一Server中指定的path对应的ServletContext对象,通过该对象可以实现与Server中的其他Context打交道。<BR>　　<BR>　　uripath必须是以"/"开始（该路径的含义是相对于整个Servlet文档的根路径，而不是当前ServletContext的根路径）。<BR>　　<BR>　　<B>Servlet生命周期是什么？</B><BR>　　<BR>　　一般的Servlet(GenericServlet,即与协议无关的Servlet)的生命周期：init() --&gt; GenericServlet.service(ServletRequest req, ServletResponse res) --&gt; destroy.<BR>　　<BR>　　HttpServlet的生命周期: init() --&gt; GenericServlet.service(ServletRequest req, ServletResponse res)---&gt; service(HttpServletRequest req, HttpServletResponse resp) --&gt; doXXXX()--&gt;destroy.<BR>　　<BR>　　<B>有没有必要重写GenericServlet.service()方法？</B><BR>　　<BR>　　对于HttpServlet来说没有必要。只需要重写它的doXXXX()方法就可以了。HttpServlet中service()方法会自动的根据用户请求类型把请求转发给相应的doXXXX()方法（例如doGet()方法）。<BR>　　<BR>　　ServletRequest.getReader()和ServletRequest.getInputStream()如何使用？<BR>　　<BR>　　注意两个方法不能同时使用。<BR>　　<BR>　　ServletRequest.getRealPath(String path)方法已经不推荐使用。<BR>　　<BR>　　请使用ServletContext.getRealPath(String path)方法。<BR>　　<BR>　　<B>ServletResponse缺省的字符集(charset)是什么?</B><BR>　　<BR>　　ServletResponse缺省的字符集(charset)是ISO-8859-1,可以通过setContentType(java.lang.String)方法改变新的字符集。<BR>　　<BR>　　例如：setContentType("text/html; charset=Shift_JIS").<BR>　　<BR>　　关于字符集信息，可以浏览<A href="http://info.internet.isi.edu/in-notes/rfc/files/rfc2045.txt" target=_blank><FONT color=blue><SPAN class=zhi14>RFC 2045</SPAN></FONT></A><BR>　　<BR>　　<B>HttpServletRequest.getRequestURI()和HttpServletRequest.getRequestURL()区别是什么?<BR>　　</B><BR>　　request.getRequestURI() 返回值类似：/xuejava/requestdemo.jsp<BR>　　<BR>　　request.getRequestURL() 返回值类似：http://localhost:8080/xuejava/requestdemo.jsp<BR>　　<BR>　　HttpServletRequest.encodeURL()和HttpServletRequest.encodeRedirectURL(()区别是什么?为什么要有两个不同的方法呢？<BR>　　<BR>　　当用URL-rewriting方式来管理Session的时候，需要用到以上的两个方法。<BR>　　<BR>　　两个方法的不同点是：两个方法确定是否需要包含session ID的逻辑不同。<BR>　　<BR>　　在调用HttpServletResponse.sendRedirect前，应该先调用encodeRedirectURL()方法，否则可能会丢失Sesssion信息。 ...<BR>　　<BR>　　<B>如何使你的Servlet或者JSP实现Single Thread Model?</B><BR>　　<BR>　　对于Servlet实现javax.single.SingleThreadModel接口。<BR>　　<BR>　　对于JSP,在Page Directive中写如下的语句&lt;%@ page isThreadSafe="false" %&gt;<BR>　　<BR>　　JSP Tag 和 JSP XML-based Tag<BR>　　<BR>　　...<BR>　　<BR>　　<B>如何把某一个JSP Page定义成为Error Page?为什么要这样做？</B><BR>　　<BR>　　实现方法： &lt;%@ page isErrorPage="true" %&gt;<BR>　　<BR>　　为什么？ 因为需要获取Exception 对象（缺省情况下，在JSP Page中是不能直接使用“隐含对象” exception的）。<BR>　　<BR>　　<B>JSP Page的执行顺序是如何的？</B><BR>　　<BR>　　JSP Page的执行顺序如下：<BR>　　<BR>　　JSP Page Translation. JSP Page --&gt; Servlet source code.<BR>　　JSP Page Compilation. Servlet source code --&gt; Servlet class.<BR>　　Load Class(First time or the server restarted)<BR>　　<BR>　　Create instance(可能会很多次，如果JSP Page中声明了&lt;%@ page isThreadSafe="false" %&gt;)<BR>　　<BR>　　Call jspInit method（一般的JSP Page都没有重写这个方法，重写需要在声明语句段中）。<BR>　　<BR>　　Call _jspService method（类似与一般HttpServlet的doGet和doPost方法，但是可以同时用来处理Post和Getq请求）。<BR>　　<BR>　　Call jspDestroy method（Server在卸载Servet的时候，例如当Servlet很久没有使用的情况）。<BR>　　<BR>　　<B>JSP Page中有哪些隐含对象(Implicity Object)?各自的类型和作用是什么？</B><BR>　　<BR>　　request --<BR>　　reponse --<BR>　　session --<BR>　　application --<BR>　　out --<BR>　　page --<BR>　　pagecontext --<BR>　　exception -- 只有在当前JSP Page为Error Page的时候才有效。<BR>　　config --<BR>　　<BR>　　<B>&lt;jsp:include page="/foo/foo.jsp" %&gt; 和 &lt;@ include file="/foo/foo.jsp" %&gt;的区别是什么？<BR>　　</B><BR>　　&lt;jsp:include ... -- request time.<BR>　　&lt;@ include ... -- Page translation time.<BR>　　<BR>　　<B>Servlets/JSP Container(Engine)有几种运行方式？</B><BR>　　<BR>　　Standalone<BR>　　Tomcat standalone mode<BR>　　In-process<BR>　　Tomcat running inside Apache Web Server.<BR>　　Out-of-process<BR>　　Apache + mod_jk + Tomcat<BR>　　<BR>　　Servlet,Servlet开发人员，Servlet API, Servlet Container的关系是什么？<BR>　　<BR>　　Servlet,Servlet开发人员 ---&gt;Servlet API --&gt; Servlet Container<BR>　　The parts of an HTTP message<BR>　　<BR>　　Message part Description<BR>　　The initial line： Specifies the purpose of the request or response message<BR>　　例子：GET /reports/sales/index.html HTTP/1.0<BR>　　The header section:Specifies the meta-information, such as size, type, and encoding,<BR>　　about the content of the message<BR>　　A blank line:<BR>　　An optional message body: The main content of the request or response message<BR>　　<BR>　　下面是一个Response的例子：<BR>　　<BR>　　HTTP/1.0 200 OK<BR>　　Date: Tue, 01 Dec 2001 23:59:59 GMT<BR>　　Content-Type: text/html<BR>　　Content-Length: 52<BR>　　<BR>　　&lt;html&gt;<BR>　　&lt;body&gt;<BR>　　&lt;h1&gt;Hello, John!&lt;/h1&gt;<BR>　　&lt;/body&gt;<BR>　　&lt;/html&gt;<BR>　　<BR>　　<B>HTTP规范中定义了哪些方法？各自有什么用途？</B><BR>　　<BR>　　GET<BR>　　HEAD<BR>　　POST<BR>　　从 Http 1.1规范开始，增加了以下的方法:<BR>　　<BR>　　PUT<BR>　　OPTIONS<BR>　　TRACE<BR>　　DELETE<BR>　　CONNECT<BR>　　<BR>　　ServetRequest中为什么要定义:getContentType(),getContentLength()方法。<BR>　　<BR>　　根据HTTP协议规范，Request 和 Response一样也有这些必不可少的内容！<BR>　　<BR>　　所以需要首先了解 HTTP Message的概念和其内容的格式，这些东西对于Request和Reponse是一样的。<BR>　　<BR>　　对于GET方式发送的请求，其内容类型为：null<BR>　　<BR>　　对于POST方式发送的请求，其内容类型为：application/x-www-form-urlencoded<BR>　　<BR>　　POST方式发送请求的内容类似于：username=xuejava.<BR>　　<BR>　　RequestDispatcher.forward()和HttpServletResponse.sendRedirect()的区别是什么？<BR>　　<BR>　　RequestDispatcher.forward()是在服务器端运行；HttpServletResponse.sendRedirect()是通过向客户浏览器发送命令来完成。<BR>　　<BR>　　所以RequestDispatcher.forward()对于浏览器来说是“透明的”；而HttpServletResponse.sendRedirect()则不是。<BR>　　<BR>　　另外，还要注意RequestDispatcher.forward()在调用的时候Response不能已经Commit了（Response.isCommitted()）。<BR>　　<BR>　　ServletContext.getRequestDispatcher(String url)和ServletRequest.getRequestDispatcher(String url)的区别是什么？为什么？<BR>　　<BR>　　ServletContext.getRequestDispatcher(String url)中的url只能使用绝对路径；而ServletRequest.getRequestDispatcher(String url)中的url可以使用相对路径。<BR>　　<BR>　　因为ServletRequest具有相对路径的概念；而ServletContext对象无次概念。<BR>　　<BR>　　<B>如何把请求转移到另外一个Web App中的某个地址？</B><BR>　　<BR>　　ServletContext.getRequestDispatcher(String url)和ServletRequest.getRequestDispatcher(String url)只能把请求转移到同一个Web App中的地址。<BR>　　<BR>　　如果需要把请求转移到另外一个Web App中的某个地址，可以按下面的做法：<BR>　　<BR>　　1. 获得另外一个Web App的ServletConext对象(currentServletContext.getContext(uripath)).<BR>　　<BR>　　2. 调用ServletContext.getRequestDispatcher(String url)方法。<BR>　　<BR>　　未完待续<img src ="http://www.blogjava.net/xxxzheng/aggbug/21998.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xxxzheng/" target="_blank">Steve</a> 2005-11-30 16:56 <a href="http://www.blogjava.net/xxxzheng/archive/2005/11/30/21998.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java基础知识——java入门与加深一</title><link>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21994.html</link><dc:creator>Steve</dc:creator><author>Steve</author><pubDate>Wed, 30 Nov 2005 08:53:00 GMT</pubDate><guid>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21994.html</guid><wfw:comment>http://www.blogjava.net/xxxzheng/comments/21994.html</wfw:comment><comments>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21994.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xxxzheng/comments/commentRss/21994.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xxxzheng/services/trackbacks/21994.html</trackback:ping><description><![CDATA[1 什么是Java、Java2、JDK？JDK后面的1.3、1.4.2版本号又是怎么回事？<BR>　　<BR>　　答：Java是一种通用的，并发的，强类型的，面向对象的编程语言（摘自Java规范第二版) JDK是Sun公司分发的免费Java开发工具，正式名称为J2SDK(Java2 Software Develop Kit)。<BR>　　<BR>　　2 什么是JRE/J2RE？<BR>　　<BR>　　答：J2RE是Java2 Runtime Environment，即Java运行环境，有时简称JRE。<BR>　　<BR>　　如果你只需要运行Java程序或Applet，下载并安装它即可。<BR>　　<BR>　　如果你要自行开发Java软件，请下载JDK。在JDK中附带有J2RE。<BR>　　<BR>　　注意由于Microsoft对Java的支持不完全，请不要使用IE自带的虚拟机来运行Applet，务必安装一个J2RE或JDK。<BR>　　<BR>　　3 学习Java用什么工具比较好？<BR>　　<BR>　　答：作者建议首先使用JDK+文本编辑器，这有助你理解下列几个基础概念：path，classpath，package并熟悉基本命令：javac和java。并且下载和你的JDK版本一致的API帮助。<BR>　　<BR>　　如果你不确定类或函数的用法，请先查阅API而不是发贴求助。<BR>　　<BR>　　当你熟悉Java之后，你可以考虑换一个IDE。很多人推荐JCreator，实际上JCreator的功能还 是很弱的。<BR>　　<BR>　　作者推荐eclipse，下载网址http://www.eclipse.org 。因eclispe是免费的.<BR>　　<BR>　　4 学习Java有哪些好的参考书？<BR>　　<BR>　　答：作者首先推荐Thinking in Java，中文名《Java编程思想》，有中文版。<BR>　　<BR>　　该书第一章介绍了很多面向对象的编程思想，作为新手应当认真阅读。<BR>　　<BR>　　除此以外，O′relly出版社和Wrox出版社的书也不错。作者本人不喜欢大陆作者的书。<BR>　　<BR>　　也许你觉得英文太难，但是网上大多数资料都是英文的。另外，你需要经常查阅API，而那也是英文的。<BR>　　<BR>　　5 Java和C++哪个更好？<BR>　　<BR>　　答：这个问题是一个很不恰当的问题。你应该问：Java和C++哪个更适用于我的项目？<BR>　　<BR>　　如果你不需要跨平台，不需要分布式，要强调程序的运行速度，C++更为适用。反之?你应当考虑Java。<BR>　　<BR>　　6 什么是J2SE/J2EE/J2ME？<BR>　　<BR>　　答：J2SE就是一般的Java。<BR>　　<BR>　　J2ME是针对嵌入式设备的，比如Java手机，它有自己的SDK。而J2EE使用J2SE的SDK。<BR>　　<BR>　　J2EE规范更多的是对J2EE服务器的要求和开发人员的约束。详情见后继《J2EE FAQ》。<BR>　　<BR>　　<B>二、命令篇</B><BR>　　<BR>　　7 我写了第一个Java程序，应该如何编译/运行？<BR>　　<BR>　　答：首先请将程序保存为xxx.java文件，然后在dos窗口下使用javac xxx.java命令，你会发现该目录下多了一个xxx.class文件，再使用java xxx命令，你的java程序就开始运行了。<BR>　　<BR>　　8 我照你说的做了，但是出现什么"′javac′ 不是内部或外部命令，也不是可运行的程序或批处理文件。"。<BR>　　<BR>　　答：你遇到了path问题。操作系统在一定的范围(path)内搜索javac.exe，但是没能找到。请编辑你的操作系统环境变量，新增一个JAVA_HOME变量，设为你JDK的安装目录，再编辑Path变量，加上一项 %JAVA_HOME%\bin。然后关掉并新开一个dos窗口，你就可以使用javac和java命令了。<BR>　　<BR>　　9 环境变量怎么设置？<BR>　　<BR>　　答：请向身边会设的人咨询。<BR>　　<BR>　　10 javac xxx.java顺利通过了，但是java xxx的时候显示什么"NoClassDefFoundError"?br&gt;<BR>　　<BR>　　答：你遇到了classpath问题。java命令在一定的范围(classpath)内搜索你要用的class文件，但是未能找到。<BR>　　<BR>　　首先请确认你没有错敲成java xxx.class，其次，检查你的CLASSPATH环境变量，如果你设置了该变量又没有包含.（代表当前目录）的?br&gt; 睿?br&gt; 你就会遇到这个问题。请在你的CLASSPATH环境变量中加入一项 。另外参见15。<BR>　　<BR>　　11 我在java xxx的时候显示"Exception in thread "main" java.lang.NoSuchMethodError: main"。<BR>　　<BR>　　答：首先，在你的程序中每个java文件有且只能有一个public类，这个类的类名必须和文件名的大小写完全一样。其次，在你要运行的类中有且只能有一个public static void main(String[] args)方法，这个方法就是你的主程序。<BR>　　<BR>　　12 package是什么意思？怎么用？<BR>　　<BR>　　答：为了唯一标识每个类并分组，java使用了package的概念。<BR>　　<BR>　　每个类都有一个全名，例如String的全名是java.lang.String，其中java.lang是包名，String是短名。<BR>　　<BR>　　这样，如果你也定义了String，你可以把它放在mypackage中，通过使用全名mypackage.String和java.lang.String来区分这两个类。同时，将逻辑上相关的类放在同一个包中，可以使程序结构更为清楚。你要做的就是在java文件开头加一行"package mypackage;"。<BR>　　<BR>　　注意包没有嵌套或包含关系，A包和A.B包对java命令来说是并列的两个包。<BR>　　<BR>　　13 我没有声明任何package会怎么样？<BR>　　<BR>　　答：你的类被认为放在默认包中。这时全名和短名是一致的。<BR>　　<BR>　　14 在一个类中怎么使用其他类？<BR>　　<BR>　　答：如果你使用java.lang包中的类，不用做任何事。<BR>　　<BR>　　如果你使用其他包中的类，使用import package1.class1; 或 import package2.*;这里.*表示引入这个包中的所有类。然后在程序中你可以使用其他类的短名。如果短名有冲突，使用全名来区分。<BR>　　<BR>　　15 我用了package的时候显示"NoClassDefFoundError"，但是我把所有package去掉的时候能正常运行。<BR>　　<BR>　　答：将你的java文件按包名存放。<BR>　　<BR>　　比如你的工作目录是/work，你的类是package1.class1，那么将它存放为/work/package1/class1.java。如果没有声明包，那么直接放在/work下。<BR>　　<BR>　　在/work下执行javac package1/class1.java，再执行java package1.class1，你会发现一切正常。另外，你可以考虑开始使用IDE。<BR>　　<BR>　　16 我想把java编译成exe文件，该怎么做？<BR>　　<BR>　　答：JDK只能将java源文件编译为class文件。<BR>　　<BR>　　class文件是一种跨平台的字节码，必须依赖平台相关的JRE来运行。Java以此来实现跨平台.有些开发工具可以将java文件编译为exe文件。作者反对这种做法，因为这样就取消了跨平台性。如果你确信你的软件只在Windows平台上运行，你可以考虑使用C++/C#来编程。<BR>　　<BR>　　17 我在编译的时候遇到什么"deprecated API"，是什么意思？<BR>　　<BR>　　答：所谓deprecated是指已经?时，但是为了向前兼容起见仍然保留的方法??br&gt; 这些方法可能会在以后取消支持。你应当改用较新的方法。一般在API里面会说明你应当用什么方法来代替之。<BR>　　<BR>　　<B>三、I/O篇</B><BR>　　<BR>　　18 我怎么给java程序加启动参数，就像dir /p/w那样？<BR>　　<BR>　　答：还记得public static void main(String[] args)吗？这里的args就是你的启动参数。在运行时你输入java package1.class1 -arg1 -arg2，args中就会有两个String，一个是arg1，另一个是arg2。<BR>　　<BR>　　19 我怎么从键盘输入一个int/double/字符串？<BR>　　<BR>　　答：java的I/O操作比C++要复杂一点。如果要从键盘输入，样例代码如下：BufferedReader cin = new BufferedReader( new InputStreamReader( System.in ) );String s = cin.readLine();<BR>　　<BR>　　这样你就获得了一个字符串，如果你需要数字的话再加上：int n = Integer.parseInt( s ); 或者 double d = Double.parseDouble( s );<BR>　　<BR>　　20 我怎么输出一个int/double/字符串？<BR>　　<BR>　　答：在程序开始写：<BR>　　<BR>　　PrintWriter cout = new PrintWriter( System.out );<BR>　　<BR>　　需要时写：<BR>　　<BR>　　cout.print(n); 或者cout.println("hello")等等。<BR>　　<BR>　　21 我发现有些书上直接用System.in和System.out输入输出，比你要简单得多。<BR>　　<BR>　　答：java使用unicode，是双字节。而System.in和System.out是单字节的stream。<BR>　　<BR>　　如果你要输入输出双字节文字比如中文，请使用作者的做法。<BR>　　<BR>　　22 我怎么从文件输入一个int/double/字符串？<BR>　　<BR>　　答：类似于从键盘输入，只不过换成BufferedReader fin = new BufferedReader( new FileReader(" myFileName " ) );<BR>　　PrintWriter fout = new PrintWriter( new FileWriter(" myFileName " ) );<BR>　　<BR>　　另外如果你还没下载API，请开始下载并阅读java.io包中的内容。<BR>　　<BR>　　23 我想读写文件的指定位置，该怎么办？<BR>　　<BR>　　答：你肯定没有认真看API。java.io.RandomAccessFile可以满足你的需要。<BR>　　<BR>　　24 怎么判断要读的文件已经到了尽头？<BR>　　<BR>　　答：你肯定没有认真看API。在Reaer的read方法中明确说明返回-1表示流的结尾。<BR>　　<BR>　　<B>四、 关键字篇</B><BR>　　<BR>　　25 java里面怎么定义宏？<BR>　　<BR>　　答：java不支持宏，因为宏代换不能保证类型安全。<BR>　　<BR>　　如果你需要定义常量，可以将它定义为某个类的static final成员。参见26和30。<BR>　　<BR>　　26 java里面没法用const。<BR>　　<BR>　　答：你可以用final关键字。例如 final int m = 9。被声明为final的变量不能被再次赋值.final也可以用于声明方法或类，被声明为final的方法或类不能被继承。注意const是java的保留字以备扩充。<BR>　　<BR>　　27 java里面也不能用goto。<BR>　　<BR>　　答：甚至在面向过程的语言中你也可以完全不用goto。请检查你的程序流程是否合理。<BR>　　<BR>　　如果你需要从多层循环中迅速跳出，java增强了（和C++相比）break和continue的功能。<img src ="http://www.blogjava.net/xxxzheng/aggbug/21994.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xxxzheng/" target="_blank">Steve</a> 2005-11-30 16:53 <a href="http://www.blogjava.net/xxxzheng/archive/2005/11/30/21994.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java基础知识——java入门与加深2</title><link>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21995.html</link><dc:creator>Steve</dc:creator><author>Steve</author><pubDate>Wed, 30 Nov 2005 08:53:00 GMT</pubDate><guid>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21995.html</guid><wfw:comment>http://www.blogjava.net/xxxzheng/comments/21995.html</wfw:comment><comments>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21995.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xxxzheng/comments/commentRss/21995.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xxxzheng/services/trackbacks/21995.html</trackback:ping><description><![CDATA[31 throw和throws有什么不同？<BR>　　<BR>　　答：throws用于声明一个方法会抛出哪些异常。而throw是在方法体中实际执行抛出异常的动作。<BR>　　<BR>　　如果你在方法中throw一个异常，却没有在方法声明中声明之，编译器会报错。<BR>　　<BR>　　注意Error和RuntimeException的子类是例外，无需特别声明。<BR>　　<BR>　　32 什么是异常？<BR>　　<BR>　　答：异常最早在Ada语言中引入，用于在程序中动态处理错误并恢复。<BR>　　<BR>　　你可以在方法中拦截底层异常并处理之，也可以抛给更高层的模块去处理。<BR>　　<BR>　　你也可以抛出自己的异常指示发生了某些不正常情况。常见的拦截处理代码如下：<BR>　　try<BR>　　{<BR>　　...... //以下是可能发生异常的代码<BR>　　...... //异常被抛出，执行流程中断并转向拦截代码。<BR>　　......<BR>　　}<BR>　　<BR>　　catch(Exception1 e) //如果Exception1是Exception2的子类并要做特别处理，应排在前面<BR>　　{<BR>　　//发生Exception1时被该段拦截<BR>　　}<BR>　　catch(Exception2 e)<BR>　　{<BR>　　//发生Exception2时被该段拦截<BR>　　}<BR>　　finally //这是可选的<BR>　　{<BR>　　//无论异常是否发生，均执行此段代码<BR>　　}<BR>　　<BR>　　33 final和finally有什么不同？<BR>　　<BR>　　答：final请见26。finally用于异常机制，参见32。<BR>　　<BR>　　<B>五、 面向对象篇</B><BR>　　<BR>　　34 extends和implements有什么不同？<BR>　　<BR>　　答：extends用于（单）继承一个类（class），而implements用于实现一个接口（interface）。<BR>　　<BR>　　interface的引入是为了部分地提供多继承的功能。<BR>　　<BR>　　在interface中只需声明方法头，而将方法体留给实现的class来做。<BR>　　<BR>　　这些实现的class的实例完全可以当作interface的实例来对待。<BR>　　<BR>　　有趣的是在interface之间也可以声明为extends（单继承）的关系。<BR>　　<BR>　　35 java怎么实现多继承？<BR>　　<BR>　　答：java不支持显式的多继承。<BR>　　<BR>　　因为在显式多继承的语言例如c++中，会出现子类被迫声明祖先虚基类构造函数的问题，而这是违反面向对象的封装性原则的。<BR>　　<BR>　　java提供了interface和implements关键字来部分地实现多继承。参见34。<BR>　　<BR>　　36 abstract是什么？<BR>　　<BR>　　答：被声明为abstract的方法无需给出方法体，留给子类来实现。<BR>　　<BR>　　而如果一个类中有abstract方法，那么这个类也必须声明为abstract。<BR>　　<BR>　　被声明为abstract的类无法实例化，尽管它可以定义构造方法供子类使用。<BR>　　<BR>　　37 public,protected,private有什么不同？<BR>　　<BR>　　答：这些关键字用于声明类和成员的可见性。public成员可以被任何类访问，protected成员限于自己和子类访问，private成员限于自己访问。<BR>　　<BR>　　Java还提供了第四种的默认可见性，当没有任何public,protected,private修饰时.<BR>　　<BR>　　类可以用public或默认来修饰。<BR>　　<BR>　　38 Override和Overload有什么不同？<BR>　　<BR>　　答：Override是指父类和子类之间方法的继承关系，这些方法有着相同的名称和参数类型。<BR>　　<BR>　　Overload是指同一个类中不同方法（可以在子类也可以在父类中定义）间的关系，这些方法有着相同的名称和不同的参数类型。<BR>　　<BR>　　39 我继承了一个方法，但现在我想调用在父类中定义的方法。<BR>　　<BR>　　答：用super.xxx()可以在子类中调用父类方法。<BR>　　<BR>　　40 我想在子类的构造方法中调用父类的构造方法，该怎么办？<BR>　　<BR>　　答：在子类构造方法的第一行调用super(...)即可。<BR>　　<BR>　　41 我在同一个类中定义了好几个构造方法并且想在一个构造方法中调用另一个。<BR>　　<BR>　　答：在构造方法第一行调用this(...)。<BR>　　<BR>　　42 我没有定义构造方法会怎么样？<BR>　　<BR>　　答：自动获得一个无参数的构造方法。<BR>　　<BR>　　43 我调用无参数的构造方法失败了。<BR>　　<BR>　　答：如果你至少定义了一个构造方法，就不再有自动提供的无参数的构造方法了。<BR>　　<BR>　　你需要显式定义一个无参数的构造方法。<BR>　　<BR>　　44 我该怎么定义类似于C++中的析构方法（destructor）？<BR>　　<BR>　　答：提供一个void finalize()方法。在Garbarge Collector回收该对象时会调用该方法。<BR>　　<BR>　　注意实际上你很难判断一个对象会在什么时候被回收。作者从未感到需要提供该方法。<BR>　　<BR>　　45 我想将一个父类对象转换成一个子类对象该怎么做？<BR>　　<BR>　　答：强制类型转换。如<BR>　　public void meth(A a)<BR>　　{<BR>　　B b = (B)a;<BR>　　}<BR>　　如果a实际上并不是B的实例，会抛出ClassCastException。所以请确保a确实是B的实例。<BR>　　<BR>　　46 其实我不确定a是不是B的实例，能不能分情况处理？<BR>　　<BR>　　答：可以使用instanceof操作符。例如<BR>　　<BR>　　if( a instanceof B )<BR>　　{<BR>　　B b = (B)a;<BR>　　}<BR>　　else<BR>　　{<BR>　　...<BR>　　<BR>　　<BR>　　}<BR>　　<BR>　　47 我在方法里修改了一个对象的值，但是退出方法后我发现这个对象的值没变！<BR>　　<BR>　　答：很可能你把传入参数重赋了一个新对象，例如下列代码就会造成这种错误：<BR>　　<BR>　　public void fun1(A a) //a是局部参数，指向了一个外在对象。<BR>　　{<BR>　　a = new A(); //a指向了一个新对象，和外在对象脱钩了。如果你要让a作为传出变量，不要写这一句。<BR>　　<BR>　　a.setAttr(attr);//修改了新对象的值，外在对象没有被修改。<BR>　　}<BR>　　<BR>　　基本类型也会出现这种情况。例如：<BR>　　<BR>　　public void fun2(int a)<BR>　　{<BR>　　a = 10;//只作用于本方法，外面的变量不会变化。<BR>　　}<BR>　　<BR>　　<B>六、java.util篇</B><BR>　　<BR>　　48 java能动态分配数组吗？<BR>　　<BR>　　答：可以。例如int n = 3; Language[] myLanguages = new Language[n];<BR>　　<BR>　　49 我怎么知道数组的长度？<BR>　　<BR>　　答：用length属性。如上例中的 myLanguages.length 就为 3。<BR>　　<BR>　　50 我还想让数组的长度能自动改变，能够增加/删除元素。<BR>　　<BR>　　答：用顺序表--java.util.List接口。<BR>　　<BR>　　你可以选择用ArrayList或是LinkedList，前者是数组实现，后者是链表实现。<BR>　　<BR>　　例如： List list = new ArrayList(); 或是 List list = new LinkedList(); 。<BR>　　<BR>　　51 什么是链表？为什么要有两种实现？<BR>　　<BR>　　答：请补习数据结构。<BR>　　<BR>　　52 我想用队列/栈。<BR>　　<BR>　　答：用java.util.LinkedList。<BR>　　<BR>　　53 我希望不要有重复的元素。<BR>　　<BR>　　答：用集合--java.util.Set接口。例如：Set set = new HashSet()。<BR>　　<BR>　　54 我想遍历集合/Map。<BR>　　<BR>　　答：用java.util.Iterator。参见API。<BR>　　<BR>　　55 我还要能够排序。<BR>　　<BR>　　答：用java.util.TreeSet。例如：Set set = new TreeSet()。放进去的元素会自动排序。<BR>　　<BR>　　你需要为元素实现Comparable接口，还可能需要提供equals()方法，compareTo()方法，hash Code()方法。<BR>　　<BR>　　56 但是我想给数组排序。<BR>　　<BR>　　答：java.util.Arrays类包含了sort等实用方法。<BR>　　<BR>　　57 我想按不同方法排序。<BR>　　<BR>　　答：为每种方法定义一个实现了接口Comparator的类并和Arrays综合运用。<BR>　　<BR>　　58 Map有什么用？<BR>　　<BR>　　答：存储key-value的关键字-值对，你可以通过关键字来快速存取相应的值。<BR>　　<BR>　　59 set方法没问题，但是get方法返回的是Object。<BR>　　<BR>　　答：强制类型转换成你需要的类型。参见45。<BR>　　<BR>　　60 我要获得一个随机数。<BR>　　<BR>　　答：使用java.util.Random类。<BR>　　<BR>　　61 我比较两个String总是false，但是它们明明都是"abc" ！<BR>　　<BR>　　答：比较String一定要使用equals或equalsIgnoreCase方法，不要使用 == ！<BR>　　<BR>　　==比较的是两个引用（变量）是否指向了同一个对象，而不是比较其内容。<img src ="http://www.blogjava.net/xxxzheng/aggbug/21995.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xxxzheng/" target="_blank">Steve</a> 2005-11-30 16:53 <a href="http://www.blogjava.net/xxxzheng/archive/2005/11/30/21995.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>开发Java系统程序员要注意的基本知识二</title><link>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21992.html</link><dc:creator>Steve</dc:creator><author>Steve</author><pubDate>Wed, 30 Nov 2005 08:48:00 GMT</pubDate><guid>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21992.html</guid><wfw:comment>http://www.blogjava.net/xxxzheng/comments/21992.html</wfw:comment><comments>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21992.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xxxzheng/comments/commentRss/21992.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xxxzheng/services/trackbacks/21992.html</trackback:ping><description><![CDATA[<STRONG>问题四：final关键字到底修饰了什么？<BR></STRONG>　　<BR>　　final使得被修饰的变量"不变"，但是由于对象型变量的本质是“引用”，使得“不变”也有了两种含义：引用本身的不变，和引用指向的对象不变。<BR>　　<BR>　　引用本身的不变：<BR>　　final StringBuffer a=new StringBuffer("immutable");<BR>　　final StringBuffer b=new StringBuffer("not immutable");<BR>　　a=b;//编译期错误<BR>　　<BR>　　引用指向的对象不变：<BR>　　final StringBuffer a=new StringBuffer("immutable");<BR>　　a.append(" broken!"); //编译通过<BR>　　<BR>　　可见，final只对引用的“值”(也即它所指向的那个对象的内存地址)有效，它迫使引用只能指向初始指向的那个对象，改变它的指向会导致编译期错误。至于它所指向的对象的变化，final是不负责的。这很类似==操作符：==操作符只负责引用的“值”相等，至于这个地址所指向的对象内容是否相等，==操作符是不管的。<BR>　　<BR>　　理解final问题有很重要的含义。许多程序漏洞都基于此----final只能保证引用永远指向固定对象，不能保证那个对象的状态不变。在多线程的操作中,一个对象会被多个线程共享或修改，一个线程对对象无意识的修改可能会导致另一个使用此对象的线程崩溃。一个错误的解决方法就是在此对象新建的时候把它声明为final，意图使得它“永远不变”。其实那是徒劳的。<BR>　　<BR>　　<B>问题五：到底要怎么样初始化！</B><BR>　　<BR>　　本问题讨论变量的初始化，所以先来看一下Java中有哪些种类的变量。<BR>　　<BR>　　1. 类的属性，或者叫值域<BR>　　<BR>　　2. 方法里的局部变量<BR>　　<BR>　　3. 方法的参数<BR>　　<BR>　　对于第一种变量，Java虚拟机会自动进行初始化。如果给出了初始值，则初始化为该初始值。如果没有给出，则把它初始化为该类型变量的默认初始值。<BR>　　<BR>　　int类型变量默认初始值为0<BR>　　<BR>　　float类型变量默认初始值为0.0f<BR>　　<BR>　　double类型变量默认初始值为0.0<BR>　　<BR>　　boolean类型变量默认初始值为false<BR>　　<BR>　　char类型变量默认初始值为0(ASCII码)<BR>　　<BR>　　long类型变量默认初始值为0<BR>　　<BR>　　所有对象引用类型变量默认初始值为null，即不指向任何对象。注意数组本身也是对象，所以没有初始化的数组引用在自动初始化后其值也是null。<BR>　　<BR>　　对于两种不同的类属性，static属性与instance属性，初始化的时机是不同的。instance属性在创建实例的时候初始化，static属性在类加载，也就是第一次用到这个类的时候初始化，对于后来的实例的创建，不再次进行初始化。这个问题会在以后的系列中进行详细讨论。<BR>　　<BR>　　对于第二种变量，必须明确地进行初始化。如果再没有初始化之前就试图使用它，编译器会抗议。如果初始化的语句在try块中或if块中，也必须要让它在第一次使用前一定能够得到赋值。也就是说，把初始化语句放在只有if块的条件判断语句中编译器也会抗议，因为执行的时候可能不符合if后面的判断条件，如此一来初始化语句就不会被执行了，这就违反了局部变量使用前必须初始化的规定。但如果在else块中也有初始化语句，就可以通过编译，因为无论如何，总有至少一条初始化语句会被执行，不会发生使用前未被初始化的事情。对于try-catch也是一样，如果只有在try块里才有初始化语句，编译部通过。如果在 catch或finally里也有，则可以通过编译。总之，要保证局部变量在使用之前一定被初始化了。所以，一个好的做法是在声明他们的时候就初始化他们，如果不知道要出事化成什么值好，就用上面的默认值吧！<BR>　　<BR>　　其实第三种变量和第二种本质上是一样的，都是方法中的局部变量。只不过作为参数，肯定是被初始化过的，传入的值就是初始值，所以不需要初始化。<BR>　　<BR>　　<B>问题六：instanceof是什么东东？</B><BR>　　<BR>　　instanceof是Java的一个二元操作符，和==，&gt;，&lt;是同一类东东。由于它是由字母组成的，所以也是Java的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例，返回boolean类型的数据。举个例子：<BR>　　<BR>　　String s = "I AM an Object!";<BR>　　boolean isObject = s instanceof Object;<BR>　　<BR>　　我们声明了一个String对象引用，指向一个String对象，然后用instancof来测试它所指向的对象是否是Object类的一个实例，显然，这是真的，所以返回true，也就是isObject的值为True。<BR>　　instanceof有一些用处。比如我们写了一个处理账单的系统，其中有这样三个类：<BR>　　<BR>　　public class Bill {//省略细节}<BR>　　public class PhoneBill extends Bill {//省略细节}<BR>　　public class GasBill extends Bill {//省略细节}<BR>　　<BR>　　在处理程序里有一个方法，接受一个Bill类型的对象，计算金额。假设两种账单计算方法不同，而传入的Bill对象可能是两种中的任何一种，所以要用instanceof来判断：<BR>　　<BR>　　public double calculate(Bill bill) {<BR>　　if (bill instanceof PhoneBill) {<BR>　　//计算电话账单<BR>　　}<BR>　　if (bill instanceof GasBill) {<BR>　　//计算燃气账单<BR>　　}<BR>　　...<BR>　　}<BR>　　这样就可以用一个方法处理两种子类。<BR>　　<BR>　　然而，这种做法通常被认为是没有好好利用面向对象中的多态性。其实上面的功能要求用方法重载完全可以实现，这是面向对象变成应有的做法，避免回到结构化编程模式。只要提供两个名字和返回值都相同，接受参数类型不同的方法就可以了：<BR>　　<BR>　　public double calculate(PhoneBill bill) {<BR>　　//计算电话账单<BR>　　}<BR>　　<BR>　　public double calculate(GasBill bill) {<BR>　　//计算燃气账单<BR>　　}<BR>　　<BR>　　所以，使用instanceof在绝大多数情况下并不是推荐的做法，应当好好利用多态。<img src ="http://www.blogjava.net/xxxzheng/aggbug/21992.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xxxzheng/" target="_blank">Steve</a> 2005-11-30 16:48 <a href="http://www.blogjava.net/xxxzheng/archive/2005/11/30/21992.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java 程序員注意几項</title><link>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21903.html</link><dc:creator>Steve</dc:creator><author>Steve</author><pubDate>Wed, 30 Nov 2005 01:40:00 GMT</pubDate><guid>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21903.html</guid><wfw:comment>http://www.blogjava.net/xxxzheng/comments/21903.html</wfw:comment><comments>http://www.blogjava.net/xxxzheng/archive/2005/11/30/21903.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/xxxzheng/comments/commentRss/21903.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/xxxzheng/services/trackbacks/21903.html</trackback:ping><description><![CDATA[　<B>问题一：我声明了什么！</B><BR>　　<BR>　　String s = "Hello world!";<BR>　　<BR>　　许多人都做过这样的事情，但是，我们到底声明了什么？回答通常是：一个String，内容是“Hello world!”。这样模糊的回答通常是概念不清的根源。如果要准确的回答，一半的人大概会回答错误。<BR>　　<BR>　　这个语句声明的是一个指向对象的引用，名为“s”，可以指向类型为String的任何对象，目前指向"Hello world!"这个String类型的对象。这就是真正发生的事情。我们并没有声明一个String对象，我们只是声明了一个只能指向String对象的引用变量。所以，如果在刚才那句语句后面，如果再运行一句：<BR>　　<BR>　　String string = s;<BR>　　<BR>　　我们是声明了另外一个只能指向String对象的引用，名为string，并没有第二个对象产生，string还是指向原来那个对象，也就是，和s指向同一个对象。<BR>　　<BR>　　<B>问题二："=="和equals方法究竟有什么区别？</B><BR>　　<BR>　　==操作符专门用来比较变量的值是否相等。比较好理解的一点是：<BR>　　int a=10;<BR>　　int b=10;<BR>　　则a==b将是true。<BR>　　但不好理解的地方是：<BR>　　String a=new String("foo");<BR>　　String b=new String("foo");<BR>　　则a==b将返回false。<BR>　　<BR>　　根据前一帖说过，对象变量其实是一个引用，它们的值是指向对象所在的内存地址，而不是对象本身。a和b都使用了new操作符，意味着将在内存中产生两个内容为"foo"的字符串，既然是“两个”，它们自然位于不同的内存地址。a和b的值其实是两个不同的内存地址的值，所以使用"=="操作符，结果会是 false。诚然，a和b所指的对象，它们的内容都是"foo"，应该是“相等”，但是==操作符并不涉及到对象内容的比较。<BR>　　<BR>　　对象内容的比较，正是equals方法做的事。<BR>　　<BR>　　看一下Object对象的equals方法是如何实现的：<BR>　　boolean equals(Object o){<BR>　　<BR>　　return this==o;<BR>　　<BR>　　}<BR>　　Object 对象默认使用了==操作符。所以如果你自创的类没有覆盖equals方法，那你的类使用equals和使用==会得到同样的结果。同样也可以看出， Object的equals方法没有达到equals方法应该达到的目标：比较两个对象内容是否相等。因为答案应该由类的创建者决定，所以Object把这个任务留给了类的创建者。<BR>　　<BR>　　看一下一个极端的类：<BR>　　Class Monster{<BR>　　private String content;<BR>　　...<BR>　　boolean equals(Object another){ return true;}<BR>　　<BR>　　}<BR>　　我覆盖了equals方法。这个实现会导致无论Monster实例内容如何，它们之间的比较永远返回true。<BR>　　<BR>　　所以当你是用equals方法判断对象的内容是否相等，请不要想当然。因为可能你认为相等，而这个类的作者不这样认为，而类的equals方法的实现是由他掌握的。如果你需要使用equals方法，或者使用任何基于散列码的集合（HashSet,HashMap,HashTable），请察看一下java doc以确认这个类的equals逻辑是如何实现的。<BR>　　<BR>　　<B>问题三：String到底变了没有？</B><BR>　　<BR>　　没有。因为String被设计成不可变(immutable)类，所以它的所有对象都是不可变对象。请看下列代码：<BR>　　<BR>　　String s = "Hello";<BR>　　s = s + " world!";<BR>　　<BR>　　s 所指向的对象是否改变了呢？从本系列第一篇的结论很容易导出这个结论。我们来看看发生了什么事情。在这段代码中，s原先指向一个String对象，内容是 "Hello"，然后我们对s进行了+操作，那么s所指向的那个对象是否发生了改变呢？答案是没有。这时，s不指向原来那个对象了，而指向了另一个 String对象，内容为"Hello world!"，原来那个对象还存在于内存之中，只是s这个引用变量不再指向它了。<BR>　　<BR>　　通过上面的说明，我们很容易导出另一个结论，如果经常对字符串进行各种各样的修改，或者说，不可预见的修改，那么使用String来代表字符串的话会引起很大的内存开销。因为 String对象建立之后不能再改变，所以对于每一个不同的字符串，都需要一个String对象来表示。这时，应该考虑使用StringBuffer类，它允许修改，而不是每个不同的字符串都要生成一个新的对象。并且，这两种类的对象转换十分容易。<BR>　　<BR>　　同时，我们还可以知道，如果要使用内容相同的字符串，不必每次都new一个String。例如我们要在构造器中对一个名叫s的String引用变量进行初始化，把它设置为初始值，应当这样做：<BR>　　public class Demo {<BR>　　private String s;<BR>　　...<BR>　　public Demo {<BR>　　s = "Initial Value";<BR>　　}<BR>　　...<BR>　　}<BR>　　而非<BR>　　s = new String("Initial Value");<BR>　　后者每次都会调用构造器，生成新对象，性能低下且内存开销大，并且没有意义，因为String对象不可改变，所以对于内容相同的字符串，只要一个String对象来表示就可以了。也就说，多次调用上面的构造器创建多个对象，他们的String类型属性s都指向同一个对象。<BR>　　<BR>　　上面的结论还基于这样一个事实：对于字符串常量，如果内容相同，Java认为它们代表同一个String对象。而用关键字new调用构造器，总是会创建一个新的对象，无论内容是否相同。<BR>　　<BR>　　至于为什么要把String类设计成不可变类，是它的用途决定的。其实不只String，很多Java标准类库中的类都是不可变的。在开发一个系统的时候，我们有时候也需要设计不可变类，来传递一组相关的值，这也是面向对象思想的体现。不可变类有一些优点，比如因为它的对象是只读的，所以多线程并发访问也不会有任何问题。当然也有一些缺点，比如每个不同的状态都要一个对象来代表，可能会造成性能上的问题。所以Java标准类库还提供了一个可变版本，即 StringBuffer。<img src ="http://www.blogjava.net/xxxzheng/aggbug/21903.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/xxxzheng/" target="_blank">Steve</a> 2005-11-30 09:40 <a href="http://www.blogjava.net/xxxzheng/archive/2005/11/30/21903.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>