??xml version="1.0" encoding="utf-8" standalone="yes"?> 模板定义如下Q?/span> y q号Q如1996 M 月䆾Q如July 或?7 d 月中W几天,?2 H 时(24 ?/span>)Q如0?/span>17 m 分钟,?2 s 钞钟Q如55 S 微钞Q如978 E 星期几,如Tuesday D 一q中的第几天Q如189 w week in year (Number) 27 W week in month (Number) 2 a am/pm marker (Text) PM k hour in day (1~24) (Number) 24 K hour in am/pm (0~11) (Number) 0 z time zone (Text) Pacific Standard Time ' escape for text (Delimiter) '' single quote (Literal) ' 使用SimpleDateFormat cL式化日期Q如果日期格式不对,?x)生异常?o:p> import java.text.*; import java.util.*; public class TestDate { public static void main(String[] args) { String dStr = "2001.12.12-08.23.21"; Date d = null; SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd- HH.mm.ss"); try { http://www.54he.com 何vq?span lang="EN-US">hp54@163.com d = sdf.parse(dStr); } catch (ParseException pe) { System.out.println(pe.getMessage()); } System.out.println(d); System.out.println(d.getTime()); } } ?span lang="EN-US">java.text 包中扑ֈ那个SimpleDateFormat c,l它一个模板,可以parse 成一个DateQ然后用Date cȝgetItme() Ҏ(gu)Q可以得C个Long 数据?o:p> 3 取得当前日期 { Calendar cal = Calendar.getInstance(); SimpleDateFormat formatter = new SimpleDateFormat("yyyy- MM-dd HH:mm:ss"); String mDateTime=formatter.format(cal.getTime()); return (mDateTime); } public java.sql.Date GetDate() { java.sql.Date mDate; Calendar cal = Calendar.getInstance(); SimpleDateFormat formatter = new SimpleDateFormat("yyyy- MM-dd HH:mm:ss"); String mDateTime=formatter.format(cal.getTime()); return (java.sql.Date.valueOf(mDateTime)); } Calendar cal = Calendar.getInstance(); // SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM- dd HH:mm:ss"); SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss G E D F w W a E F"); String mDateTime=formatter.format(cal.getTime()); out.println(mDateTime); out.println("<br>"); java.util.Date myDate=new java.util.Date(); long myTime=(myDate.getTime()/1000)-60*60*24*365; myDate.setTime(myTime*1000); String mDate=formatter.format(myDate); out.println(mDate); out.println("<br>"); myDate=new java.util.Date(); myTime=(myDate.getTime()/1000)+60*60*24; myDate.setTime(myTime*1000); mDate=formatter.format(myDate); out.println(mDate); out.println("<br>"); 7 两个旉之间的天?/font> java.util.Date date= myFormatter.parse("2003-05-1"); java.util.Date mydate= myFormatter.parse("1899-12-30"); long day=(date.getTime()-mydate.getTime())/(24*60*60*1000); out.println(day); out.println("<br>"); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); java.util.Date date1 = format.parse("2002-02-28 23:16:00"); long Time=(date1.getTime()/1000)+60*30; date1.setTime(Time*1000); String mydate1=formatter.format(date1); out.println(mydate1); out.println("<br>"); SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM F E"); java.util.Date date2= formatter2.parse("2003-05 5 星期?); SimpleDateFormat formatter3 = new SimpleDateFormat("yyyy-MM-dd"); String mydate2=formatter3.format(date2); out.println(mydate2); out.println("<br>"); mydate= myFormatter.parse("2001-1-1"); SimpleDateFormat formatter4 = new SimpleDateFormat("E"); String mydate3=formatter4.format(mydate); out.println(mydate3); out.println("<br>");
什么是Java中的内存泄露
下面Q我们就可以描述什么是内存泄漏。在Java中,内存泄漏是存在一些被分配的对象,q些对象有下面两个特点,首先Q这些对象是可达的,卛_有向图中Q存在通\可以与其相连Q其ơ,q些对象是无用的Q即E序以后不会(x)再用这些对象。如果对象满两个条gQ这些对象就可以判定为Java中的内存泄漏Q这些对象不?x)被GC所回收Q然而它却占用内存?在C++中,内存泄漏的范围更大一些。有些对象被分配?jin)内存空_(d)然后却不可达Q由于C++中没有GCQ这些内存将永远收不回来。在Java中,q些不可辄对象都由GC负责回收Q因此程序员?sh)需要考虑q部分的内存泄露?通过分析Q我们得知,对于C++Q程序员需要自q理边和顶点,而对于JavaE序员只需要管理边可以了(jin)(不需要管理顶点的释放)。通过q种方式QJava提高?sh)(jin)编E的效率?因此Q通过以上分析Q我们知道在Java中也有内存泄漏,但范围比C++要小一些。因为Java从语a上保证,M对象都是可达的,所有的不可辑֯象都由GC理?对于E序员来_(d)GC基本是透明的,不可见的。虽?dng)我们只有几个函数可以讉KGCQ例如运行GC的函数System.gc()Q但是根据Java语言规范定义Q?该函C保证JVM的垃圾收集器一定会(x)执行。因为,不同的JVM实现者可能用不同的法理GC。通常QGC的线E的优先U别较低。JVM调用GC的策略也有很多种Q有的是内存?sh)用到达一定程度时QGC才开始工作,也有定时执行的,有的是^~执行GCQ有的是中断式执行GC。但通常来说Q我们不需要关?j)这些。除非在一些特定的场合QGC的执行媄(jing)响应用程序的性能Q例如对于基于Web的实时系l,如网l游戏等Q用户不希望GCH然中断应用E序执行而进行垃圑֛Ӟ那么我们需要调整GC的参敎ͼ让GC能够通过q缓的方式释攑ֆ存,例如垃圑֛收分解ؓ(f)一pd的小步骤执行QSun提供的HotSpot JVM支持这一Ҏ(gu)?
下面l出?jin)一个简单的内存泄露的例子。在q个例子中,我们循环甌Object对象Qƈ所甌的对象放入一个Vector中,如果我们仅仅释放引用本nQ那么Vector仍然引用该对象,所以这个对象对GC来说是不可回收的。因此,如果对象加入到Vector后,q必MVector中删除,最单的Ҏ(gu)是Vector对象讄为null?Vector v=new Vector(10); for (int i=1;i<100; i++) { Object o=new Object(); v.add(o); o=null; } //此时Q所有的Object对象都没有被释放Q因为变量v引用q些对象?如何(g)内存泄?最后一个重要的问题Q就是如何检Java的内存泄漏。目前,我们通常使用一些工h(g)查JavaE序的内存泄漏问题。市(jng)Z已有几种专业(g)查Java内存泄漏的工P它们的基本工作原理大同小异,都是通过监测JavaE序q行Ӟ所有对象的甌、释攄动作Q将内存理的所有信息进行统计、分析、可视化。开发h员将Ҏ(gu)q些信息判断E序是否有内存泄漏问题。这些工具包括Optimizeit ProfilerQJProbe ProfilerQJinSight , Rational 公司的Purify{?br /> (tng)
下面Q我们将单介lOptimizeit的基本功能和工作原理?Optimizeit Profiler版本4.11支持ApplicationQAppletQServlet和Romote Application四类应用Qƈ且可以支持大多数cd的JVMQ包括SUN JDKpdQIBM的JDKpdQ和Jbuilder的JVM{。ƈ且,该Y件是由Java~写Q因此它支持多种操作pȝ。Optimizeitpdq包括Thread Debugger和Code Coverage两个工具Q分别用于监运行时的线E状态和代码覆盖面?当设|好所有的参数?jin),我们可以在OptimizeIt环境下运行被程序,在程序运行过E中QOptimizeit可以监视内存的用曲U?如下?Q包括JVM甌的堆(heap)的大,和实际用的内存大小。另外,在运行过E中Q我们可以随时暂停程序的q行Q甚臛_行调用GCQ让GCq行内存回收。通过内存?sh)用曲线Q我们可以整体了(jin)解程序用内存的情况。这U监对于长期运行的应用E序非常有必要,也很Ҏ(gu)发现内存泄露?在运行过E中Q我们还可以从不同视角观查内存的使用情况QOptimizeit提供?jin)四U方式:(x) 堆视角?q是一个全面的视角Q我们可以了(jin)解堆中的所有的对象信息(数量和种c?Qƈq行l计、排序,qo(h)。了(jin)解相兛_象的变化情况?Ҏ(gu)视角。通过Ҏ(gu)视角Q我们可以得知每一U类的对象,都分配在哪些Ҏ(gu)中,以及(qing)它们的数量?对象视角。给定一个对象,通过对象视角Q我们可以显C它的所有出引用和入引用对象Q我们可以了(jin)解这个对象的所有引用关pR?引用图?l定一个根Q通过引用图,我们可以昄从该点出发的所有出引用?在运行过E中Q我们可以随时观察内存的使用情况Q通过q种方式Q我们可以很快找到那些长期不被释放,q且不再使用的对象。我们通过(g)查这些对象的生存周期Q确认其是否为内存泄霌Ӏ在实践当中Q寻扑ֆ存泄露是一仉帔R?ch)的事情Q它需要程序员Ҏ(gu)个程序的代码比较清楚Qƈ且需要丰富的调试l验Q但是这个过E对于很多关键的JavaE序都是十分重要的?lg所qͼJava也存在内存泄露问题,其原因主要是一些对象虽然不再被使用Q但它们仍然被引用。ؓ(f)?jin)解册些问题,我们可以通过软g工具来检查内存泄Ԍ(g)查的主要原理是暴露出所有堆中的对象Q让E序员寻N些无用但仍被引用的对象?
作者简?
Ƨ阳辎ͼ北京大学计算机硕士毕业,98qv开始研I基于java的Y件开发、测试,参与开发、测试过多个ZJava的应用程序和W(xu)eb服务目?
周欣Q北京大学计机pdd士生Q主要研I方向:(x)E序理解、逆向工程?qing)Y件度量,联系方式 zhouxin@sei.pku.edu.cn
]]>
此应用程序内的?tng)HttpServer1c?tng)与前文单的 (tng)WEB (tng)服务器应用程序中的HttpServer (tng)十分怼。但是,此应用程序内的?tng)HttpServer1 (tng)能服务静(rn)态资源和 (tng)servlet。如果要h一个静(rn)态资源,误入以下?tng)URLQ?br />
http://machineName:port/staticResource (tng)
它就是前文中提到的怎样在?tng)WEB (tng)服务器应用程序里h?rn)态资源。如果要h一个?tng)servletQ请输入以下 (tng)URLQ?br />
http://machineName:port/servlet/servletClass (tng)
如果(zhn)想在本地浏览器h一个?tng)PrimitiveServle (tng)servlet (tng)Q请输入以下 (tng)URLQ?br />
http://localhost:8080/servlet/PrimitiveServlet (tng)
下面 (tng)Listing (tng)2.2 (tng)cȝ (tng)await (tng)Ҏ(gu)Q是{待一个?tng)HTTP (tng)hQ直C个发布?tng)shutdown (tng)命o(h)。与前文的?tng)await (tng)Ҏ(gu)怼。?br />
Listing (tng)2.2. (tng)HttpServer1 (tng)cȝ (tng)await (tng)Ҏ(gu)
public (tng)void (tng)await() (tng){
ServerSocket (tng)serverSocket (tng)= (tng)null;
int (tng) (tng) (tng) (tng) (tng) (tng) (tng)port (tng) (tng)= (tng)8080;
try (tng){
serverSocket (tng)= (tng) (tng)new (tng)ServerSocket(port, (tng)1,InetAddress.getByName("127.0.0.1"));
(tng) (tng) (tng) (tng)}catch (tng)(IOException (tng)e) (tng){
e.printStackTrace();
System.exit(1);
(tng) (tng) (tng) (tng)}
// (tng)循环Q等待一个请?br />while (tng)(!shutdown) (tng){
Socket (tng)socket (tng) (tng) (tng) (tng) (tng) (tng) (tng)= (tng)null;
InputStream (tng)input (tng) (tng) (tng)= (tng)null;
OutputStream (tng)output (tng)= (tng)null;
try (tng){
socket (tng)= (tng)serverSocket.accept();
input (tng) (tng)= (tng)socket.getInputStream();
output (tng)= (tng)socket.getOutputStream();
// (tng)创徏h对象q解?br />Request (tng)request (tng)= (tng)new (tng)Request(input);
request.parse();
// (tng)创徏回应对象
Response (tng)response (tng)= (tng)new (tng)Response(output);
response.setRequest(request);
//(g)是否是 (tng)servlet (tng)或静(rn)态资源的h
//servlet (tng)h以?/servlet/" (tng)开始?br />if (tng)(request.getUri().startsWith("/servlet/")) (tng){
ServletProcessor1 (tng)processor (tng)= (tng)new (tng)ServletProcessor1();
processor.process(request, (tng)response);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
else (tng){
StaticResourceProcessor (tng)processor (tng)=new (tng)StaticResourceProcessor();
processor.process(request, (tng)response);
(tng) (tng) (tng) (tng) (tng) (tng)}
// (tng)关闭socket
socket.close();
//(g)是否前面的 (tng)URI (tng)是一个?tng)shutdown (tng)命o(h)
shutdown (tng)= (tng)request.getUri().equals(SHUTDOWN_COMMAND);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}catch (tng)(Exception (tng)e) (tng){
e.printStackTrace();System.exit(1);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} (tng) (tng) (tng) (tng)
}
} (tng)
此文 (tng)await (tng)Ҏ(gu)和前文的不同点就是,此文的?tng)await (tng)Ҏ(gu)中的h调度到StaticResourceProcessor (tng)或?tng)ervletProcessor (tng)。?br />如果 (tng)URI中包含?/servlet/."Q请求推q到后面Q否则,h传递到 (tng)StaticResourceProcessor (tng)实例 (tng)
Request (tng)c?br />
Servlet (tng)service (tng)Ҏ(gu)接受 (tng)servlet (tng)容器的?tng)javax.servlet.ServletRequest (tng)和javax.servlet.ServletResponse (tng)实例。因此,容器必须构徏 (tng)ServletRequest和ServletResponse对象Q然后将其传递到正在被服务的service (tng)Ҏ(gu)。?br />
ex02.pyrmont.Request (tng)cM表一个请求对象传递到 (tng)service (tng)Ҏ(gu)。同样地Q它必须实现 (tng)javax.servlet.ServletRequest (tng)接口。这个类必须提供接口内所有方法的实现。这里尽量简化它q只实现几个Ҏ(gu)。要~译 (tng)Request (tng)cȝ话,必须提供q些Ҏ(gu)的空实现。再来看看?tng)request (tng)c,内部所有需要返回一个对象实例都q回nullQ如下:(x) (tng)
public (tng)Object (tng)getAttribute(String (tng)attribute) (tng){
(tng) (tng) (tng) (tng) (tng)return (tng)null;
(tng) (tng)}
public (tng)Enumeration (tng)getAttributeNames() (tng){
(tng) (tng) (tng) (tng) (tng)return (tng)null;
(tng) (tng)}
public (tng)String (tng)getRealPath(String (tng)path) (tng){
(tng) (tng) (tng) (tng) (tng)return (tng)null;
(tng) (tng)}
另外Qrequest (tng)cM需有前文有介绍的?tng)parse (tng)和getUri (tng)Ҏ(gu)。?br />
Response (tng)c?br />
response (tng)cd玊Wjavax.servlet.ServletResponseQ同P该类也必L供接口内所有方法的实现。类g (tng)Request (tng)c,除?tng)getWriter (tng)Ҏ(gu)外,其他Ҏ(gu)的实现都为空。?br />
public (tng)PrintWriter (tng)getWriter() (tng){
// (tng)autoflush (tng)is (tng)true, (tng)println() (tng)will (tng)flush,
// (tng)but (tng)print() (tng)will (tng)not.
writer (tng)= (tng)new (tng)PrintWriter(output, (tng)true);
return (tng)writer;
}
PrintWriter (tng)cL建器的第二个参数是一个代表是否启用?tng)autoflush (tng)布尔|如果为真Q所有调用println (tng)Ҏ(gu)qflush (tng)输出。而?tng)print (tng)调用则不 (tng)flush (tng)输出。因此,如果在servelt (tng)的service (tng)Ҏ(gu)的最后一行调用?tng)printҎ(gu)Q则从浏览器上看不到此输出?tng)。这个不完整性在后面的应用程序内?x)有调整。?br />
response (tng)cM包含有前文中介绍的?tng)sendStaticResourceҎ(gu)。?br />
StaticResourceProcessor (tng)c?br />
StaticResourceProcessor (tng)cȝ于服务静(rn)态资源的h。它唯一的方法是 (tng)process。?br />
Listing (tng)2.3.StaticResourceProcessor (tng)cȝ (tng)processҎ(gu).
public (tng)void (tng)process(Request (tng)request, (tng)Response (tng)response) (tng){
try (tng){
response.sendStaticResource();
(tng) (tng) (tng) (tng)}catch (tng)(IOException (tng)e) (tng){
e.printStackTrace();
(tng) (tng) (tng) (tng)}
}
process (tng)Ҏ(gu)接受两个参数QRequest (tng)和?tng)Response (tng)实例。它仅仅是调用?tng)response (tng)cȝ (tng)sendStaticResource (tng)Ҏ(gu)?img src ="http://www.aygfsteel.com/matthew2006/aggbug/85799.html" width = "1" height = "1" />
]]>
(tng) (tng) (tng) (tng)存储q程是指保存在数据库q在数据库端执行的程序。你可以使用Ҏ(gu)的语法在JavacM调用存储q程。在调用Ӟ存储q程的名U及(qing)指定的参数通过JDBCq接发送给DBMSQ执行存储过Eƈ通过q接Q如果有Q返回结果。?br />使用存储q程拥有和用基于EJB或CORBAq样的应用服务器一L(fng)好处。区别是存储q程可以从很多流行的DBMS中免费用,而应用服务器大都非常昂贵。这q不只是许可证费用的问题。用应用服务器所需要花费的理、编写代码的费用Q以?qing)客L(fng)序所增加的复杂性,都可以通过DBMS中的存储q程所整个地替代。?br />
(tng) (tng) (tng) (tng)你可以用JavaQPythonQPerl或C~写存储q程Q但是通常使用你的DBMS所指定的特定语a。Oracle使用PL/SQLQPostgreSQL使用pl/pgsqlQDB2使用Procedural (tng)SQL。这些语a都非常相伹{在它们之间UL存储q程q不比在Sun的EJB规范不同实现版本之间ULSession (tng)Bean困难。ƈ且,存储q程是ؓ(f)嵌入SQL所设计Q这使得它们比Java或C{语a更加友好地方式表达数据库的机制。?br />
(tng) (tng) (tng) (tng)因ؓ(f)存储q程q行在DBMS自nQ这可以帮助减少应用E序中的{待旉。不是在Java代码中执?个或5个SQL语句Q而只需要在服务器端执行1个存储过E。网l上的数据往q次数的减少可以戏剧性地优化性能。?br />
使用存储q程 (tng)
(tng) (tng) (tng) (tng)单的老的JDBC通过CallableStatementcL持存储过E的调用。该cd际上是PreparedStatement的一个子cR假设我们有一个poets数据库。数据库中有一个设|诗人逝世q龄的存储过E。下面是对老酒鬼Dylan (tng)ThomasQold (tng)soak (tng)Dylan (tng)ThomasQ不指定是否有关典故、文化,h评指正。译注)(j)q行调用的详l代码:(x) (tng)
try{ (tng)
int (tng)age (tng)= (tng)39;
String (tng)poetName (tng)= (tng)"dylan (tng)thomas"; (tng)
CallableStatement (tng)proc (tng)= (tng)connection.prepareCall("{ (tng)call (tng)set_death_age?, (tng)?) (tng)}"); (tng)
proc.setString(1, (tng)poetName); (tng)
proc.setInt(2, (tng)age); (tng)
cs.execute(); (tng)
}catch (tng)(SQLException (tng)e){ (tng)// (tng)....} (tng)
(tng) (tng) (tng) (tng)传给prepareCallҎ(gu)的字串是存储q程调用的书写规范。它指定?jin)存储过E的名称Q?代表?jin)你需要指定的参数。?br />和JDBC集成是存储过E的一个很大的便利Qؓ(f)?jin)从应用中调用存储过E,不需要存根(stubQ类或者配|文Ӟ除了(jin)你的DBMS的JDBC驱动E序外什么也不需要。?br />
(tng) (tng) (tng) (tng)当这D代码执行时Q数据库的存储过E就被调用。我们没有去获取l果Q因存储q程q不q回l果。执行成功或p|通过例外得知。失败可能意味着调用存储q程时的p|Q比如提供的一个参数的cd不正)(j)Q或者一个应用程序的p|Q比如抛Z个例外指C在poets数据库中q不存在“Dylan (tng)Thomas”)(j) (tng)
l合SQL操作与存储过E?br />
(tng) (tng) (tng) (tng)映射Java对象到SQL表中的行相当单,但是通常需要执行几个SQL语句Q可能是一个SELECT查找IDQ然后一个INSERT插入指定ID的数据。在高度规格化(W合更高的范式,译注Q的数据库模式中Q可能需要多个表的更斎ͼ因此需要更多的语句。Java代码?x)很快地膨胀Q每一个语句的|络开销也迅速增加。?br />这些SQL语句转移C个存储过E中大大简化代码,仅涉?qing)一ơ网l调用。所有关联的SQL操作都可以在数据库内部发生。ƈ且,存储q程语言Q例如PL/SQLQ允怋用SQL语法Q这比Java代码更加自然。下面是我们早期的存储过E,使用Oracle的PL/SQL语言~写Q?br />
create (tng)procedure (tng)set_death_age(poet (tng)VARCHAR2, (tng)poet_age (tng)NUMBER) (tng)
poet_id (tng)NUMBER; (tng)
begin (tng)SELECT (tng)id (tng)I(yng)NTO (tng)poet_id (tng)FROM (tng)poets (tng)WHERE (tng)name (tng)= (tng)poet; (tng)
INSERT (tng)I(yng)NTO (tng)deaths (tng)(mort_id, (tng)age) (tng)VALUES (tng)(poet_id, (tng)poet_age); (tng)
end (tng)set_death_age; (tng)
(tng) (tng) (tng) (tng)很独特?不。我打赌你一定期待看C个poets表上的UPDATE。这也暗CZ(jin)使用存储q程实现是多么容易的一件事情。set_death_age几乎可以肯定是一个很烂的实现。我们应该在poets表中d一列来存储逝世q龄。Java代码中ƈ不关?j)数据库模式是怎么实现的,因ؓ(f)它仅调用存储q程。我们以后可以改变数据库模式以提高性能Q但是我们不必修Ҏ(gu)们代码。?br />
下面是调用上面存储过E的Java代码Q?br />
public (tng)static (tng)void (tng)setDeathAge(Poet (tng)dyingBard, (tng)int (tng)age) (tng)throws (tng)SQLException{ (tng)
Connection (tng)con (tng)= (tng)null; (tng)
CallableStatement (tng)proc (tng)= (tng)null; (tng)
try (tng){ (tng)
con (tng)= (tng)connectionPool.getConnection(); (tng)
proc (tng)= (tng)con.prepareCall("{ (tng)call (tng)set_death_age(?, (tng)?) (tng)}"); (tng)
proc.setString(1, (tng)dyingBard.getName()); (tng)
proc.setInt(2, (tng)age); (tng)proc.execute(); (tng)
} (tng)finally (tng){ (tng)
try (tng){ (tng)
proc.close(); (tng)
} (tng)catch (tng)(SQLException (tng)e) (tng){ (tng)
con.close(); (tng) (tng)} (tng)}
(tng) (tng) (tng) (tng)Z(jin)保可维护性,使用像这儿这L(fng)staticҎ(gu)。这也得调用存储过E的代码集中在一个简单的模版代码中。如果你用到许多存储q程Q就?x)发C需要拷贝、粘贴就可以创徏新的Ҏ(gu)。因Z码的模版化,甚至也可以通过脚本自动生调用存储q程的代码。?br />
Functions (tng)
(tng) (tng) (tng) (tng)存储q程可以有返回|所以CallableStatementcLcMgetResultSetq样的方法来获取q回倹{当存储q程q回一个值时Q你必须使用registerOutParameterҎ(gu)告诉JDBC驱动器该值的SQLcd是什么。你也必调整存储过E调用来指示该过E返回一个倹{?br />
下面接着上面的例子。这ơ我们查询Dylan (tng)Thomas逝世时的q龄。这ơ的存储q程使用PostgreSQL的pl/pgsqlQ?br />
create (tng)function (tng)snuffed_it_when (tng)(VARCHAR) (tng)returns (tng)integer (tng)''declare (tng)
poet_id (tng)NUMBER; (tng)
poet_age (tng)NUMBER; (tng)
begin (tng)
--first (tng)get (tng)the (tng)id (tng)associated (tng)with (tng)the (tng)poet. (tng)
SELECT (tng)id (tng)I(yng)NTO (tng)poet_id (tng)FROM (tng)poets (tng)WHERE (tng)name (tng)= (tng)$1; (tng)
--get (tng)and (tng)return (tng)the (tng)age. (tng)
SELECT (tng)age (tng)I(yng)NTO (tng)poet_age (tng)FROM (tng)deaths (tng)WHERE (tng)mort_id (tng)= (tng)poet_id; (tng)
return (tng)age; (tng)
end;'' (tng)language (tng)''pl/pgsql''; (tng)
(tng) (tng) (tng) (tng)另外Q注意pl/pgsql参数名通过Unix和DOS脚本?n语法引用。同Ӟ也注意嵌入的注释Q这是和Java代码相比的另一个优性。在Java中写q样的注释当然是可以的,但是看v来很凌ؕQƈ且和SQL语句pQ必d入到Java (tng)String中。?br />
下面是调用这个存储过E的Java代码Q?br />
connection.setAutoCommit(false); (tng)
CallableStatement (tng)proc (tng)= (tng)connection.prepareCall("{ (tng)? (tng)= (tng)call (tng)snuffed_it_when(?) (tng)}"); (tng)
proc.registerOutParameter(1, (tng)Types.INTEGER); (tng)
proc.setString(2, (tng)poetName); (tng)
cs.execute(); (tng)
int (tng)age (tng)= (tng)proc.getInt(2); (tng)
(tng) (tng) (tng) (tng)如果指定?jin)错误的q回值类型会(x)怎样Q那么,当调用存储过E时抛Z个RuntimeExceptionQ正如你在ResultSet操作中用了(jin)一个错误的cd所到的一栗?br />
复杂的返回值?br />
(tng) (tng) (tng) (tng)关于存储q程的知识,很多人好像就熟?zhn)我们所讨论的这些。如果这是存储过E的全部功能Q那么存储过E就不是其它q程执行机制的替换方案了(jin)。存储过E的功能比这强大得多。?br /> (tng) (tng) (tng) (tng)当你执行一个SQL查询ӞDBMS创徏一个叫做cursorQ游标)(j)的数据库对象Q用于在q回l果中P代每一行。ResultSet是当前时间点的游标的一个表C。这是Z么没有缓存或者特定数据库的支持,你只能在ResultSet中向前移动。?br />
(tng) (tng) (tng) (tng)某些DBMS允许从存储过E中q回游标的一个引用。JDBCq不支持q个功能Q但是Oracle、PostgreSQL和DB2的JDBC驱动器都支持在ResultSet上打开到游标的指针QpointerQ。?br />
(tng) (tng) (tng) (tng)设想列出所有没有活到退休年龄的诗hQ下面是完成q个功能的存储过E,q回一个打开的游标,同样也用PostgreSQL的pl/pgsql语言Q?br />
create (tng)procedure (tng)list_early_deaths (tng)() (tng)return (tng)refcursor (tng)as (tng)''declare (tng)
toesup (tng)refcursor; (tng)
begin (tng)open (tng)toesup (tng)for (tng)SELECT (tng)poets.name, (tng)deaths.age (tng)FROM (tng)poets, (tng)deaths (tng)
-- (tng)all (tng)entries (tng)in (tng)deaths (tng)are (tng)for (tng)poets. (tng)
-- (tng)but (tng)the (tng)table (tng)might (tng)become (tng)generic. (tng)
WHERE (tng)poets.id (tng)= (tng)deaths.mort_id (tng)AND (tng)deaths.age (tng)< (tng)60; (tng)
return (tng)toesup; (tng)
end;'' (tng)language (tng)''plpgsql''; (tng)
下面是调用该存储q程的JavaҎ(gu)Q将l果输出到PrintWriterQ?br />PrintWriter: (tng)
static (tng)void (tng)sendEarlyDeaths(PrintWriter (tng)out){ (tng)
Connection (tng)con (tng)= (tng)null; (tng)
CallableStatement (tng)toesUp (tng)= (tng)null; (tng)
try (tng){ (tng)
con (tng)= (tng)ConnectionPool.getConnection(); (tng)// (tng)PostgreSQL (tng)needs (tng)a (tng)transaction (tng)to (tng)do (tng)this... (tng)con. (tng)
setAutoCommit(false); (tng)// (tng)Setup (tng)the (tng)call. (tng)
CallableStatement (tng)toesUp (tng)= (tng)connection.prepareCall("{ (tng)? (tng)= (tng)call (tng)list_early_deaths (tng)() (tng)}"); (tng)
toesUp.registerOutParameter(1, (tng)Types.OTHER); (tng)
toesUp.execute(); (tng)
ResultSet (tng)rs (tng)= (tng)(ResultSet) (tng)toesUp.getObject(1); (tng)
while (tng)(rs.next()) (tng){ (tng)
String (tng)name (tng)= (tng)rs.getString(1); (tng)
int (tng)age (tng)= (tng)rs.getInt(2); (tng)
out.println(name (tng)+ (tng)" (tng)was (tng)" (tng)+ (tng)age (tng)+ (tng)" (tng)years (tng)old."); (tng)
} (tng)
rs.close(); (tng)
} (tng)catch (tng)(SQLException (tng)e) (tng){ (tng)
// (tng)We (tng)should (tng)protect (tng)these (tng)calls. (tng)
toesUp.close(); (tng)
con.close(); (tng)
} (tng)
} (tng)
(tng) (tng) (tng) (tng)因ؓ(f)JDBCq不直接支持从存储过E中q回游标Q我们用Types.OTHER来指C存储过E的q回cdQ然后调用getObject()Ҏ(gu)q对q回D行强制类型{换。?br />
(tng) (tng) (tng) (tng)q个调用存储q程的JavaҎ(gu)是mapping的一个好例子。Mapping是对一个集上的操作q行抽象的方法。不是在q个q程上返回一个集Q我们可以把操作传送进L行。本例中Q操作就是把ResultSet打印C个输出流。这是一个值得举例的很常用的例子,下面是调用同一个存储过E的另外一个方法实玎ͼ(x) (tng)
public (tng)class (tng)ProcessPoetDeaths{ (tng)
public (tng)abstract (tng)void (tng)sendDeath(String (tng)name, (tng)int (tng)age); (tng)
} (tng)
static (tng)void (tng)mapEarlyDeaths(ProcessPoetDeaths (tng)mapper){ (tng)
Connection (tng)con (tng)= (tng)null; (tng)
CallableStatement (tng)toesUp (tng)= (tng)null; (tng)
try (tng){ (tng)
con (tng)= (tng)ConnectionPool.getConnection(); (tng)
con.setAutoCommit(false); (tng)
CallableStatement (tng)toesUp (tng)= (tng)connection.prepareCall("{ (tng)? (tng)= (tng)call (tng)list_early_deaths (tng)() (tng)}"); (tng)
toesUp.registerOutParameter(1, (tng)Types.OTHER); (tng)
toesUp.execute(); (tng)
ResultSet (tng)rs (tng)= (tng)(ResultSet) (tng)toesUp.getObject(1); (tng)
while (tng)(rs.next()) (tng){ (tng)
String (tng)name (tng)= (tng)rs.getString(1); (tng)
int (tng)age (tng)= (tng)rs.getInt(2); (tng)
mapper.sendDeath(name, (tng)age); (tng)
} (tng)
rs.close(); (tng)
} (tng)catch (tng)(SQLException (tng)e) (tng){ (tng)
// (tng)We (tng)should (tng)protect (tng)these (tng)calls. (tng)
toesUp.close(); (tng)
con.close(); (tng)
} (tng)
} (tng)
q允许在ResultSet数据上执行Q意的处理Q而不需要改变或者复制获取ResultSet的方法:(x) (tng)
static (tng)void (tng)sendEarlyDeaths(final (tng)PrintWriter (tng)out){ (tng)
ProcessPoetDeaths (tng)myMapper (tng)= (tng)new (tng)ProcessPoetDeaths() (tng){ (tng)
public (tng)void (tng)sendDeath(String (tng)name, (tng)int (tng)age) (tng){ (tng)
out.println(name (tng)+ (tng)" (tng)was (tng)" (tng)+ (tng)age (tng)+ (tng)" (tng)years (tng)old."); (tng)
} (tng)
}; (tng)
mapEarlyDeaths(myMapper); (tng)
} (tng)
(tng) (tng) (tng)q个Ҏ(gu)使用ProcessPoetDeaths的一个匿名实例调用mapEarlyDeaths。该实例拥有sendDeathҎ(gu)的一个实玎ͼ和我们上面的例子一L(fng)方式把结果写入到输出。当?dng)q个技巧ƈ不是存储q程Ҏ(gu)的,但是和存储过E中q回的ResultSetl合使用Q是一个非常强大的工具。?br />
l论 (tng)
存储q程可以帮助你在代码中分逻辑Q这基本上L有益的。这个分ȝ好处有:(x) (tng)
•?tng)快速创建应用,使用和应用一h变和改善的数据库模式。?br />•?tng)数据库模式可以在以后改变而不影响Java对象Q当我们完成应用后,可以重新设计更好的模式。?br />•?tng)存储过E通过更好的SQL嵌入使得复杂的SQL更容易理解。?br />•?tng)编写存储过E比在Java中编写嵌入的SQL拥有更好的工PQ大部分~辑器都提供语法高(sh)Q?br />•?tng)存储过E可以在MSQL命o(h)行中试Q这使得调试更加Ҏ(gu)。?br />
q不是所有的数据库都支持存储q程Q但是存在许多很的实现Q包括免?开源的和非免费的,所以移植ƈ不是一个问题。Oracle、PostgreSQL和DB2都有cM的存储过E语aQƈ且有在线的社区很好地支持。?br />存储q程工具很多Q有像TOAD或TORAq样的编辑器、调试器和IDEQ提供了(jin)~写、维护PL/SQL或pl/pgsql的强大的环境。?br />
存储q程实增加?jin)你的代码的开销Q但是它们和大多数的应用服务器相比,开销得多?br />
查看原文
]]>
public (tng)static (tng)ByteToCharConverter (tng)getDefault(); (tng)
public (tng)static (tng)ByteToCharConverter (tng)getConverter(String (tng)encoding); (tng)
如果你不指定converterQ则pȝ?x)自动用当前的encoding,gbq_上用gbk,enq_上用8859_1?br />byte (tng)――〉charQ?br /> (tng)"?的gb码是Q?xc4e3 (tng),unicode?x4f60
(tng) (tng)String (tng)encoding (tng)= (tng)"gb2312";
(tng) (tng)byte (tng)b[] (tng)= (tng){(byte)'\u00c4',(byte)'\u00e3'};
(tng) (tng)ByteToCharConverter (tng)converter (tng)= (tng)ByteToCharConverter.getConverter(encoding);
(tng) (tng)char (tng)c[] (tng)= (tng)converter.convertAll(b);
(tng) (tng)for (tng)(int (tng)i (tng)= (tng)0; (tng)i (tng)< (tng)c.length; (tng)i++) (tng){
(tng) (tng) (tng) (tng) (tng) (tng)System.out.println(Integer.toHexString(c[i]));
(tng) (tng)}
(tng)l果是什么?0x4f60
(tng)如果encoding (tng)="8859_1"Q结果又是什么?0x00c4,0x00e3
(tng)如果代码改ؓ(f)
(tng)byte (tng)b[] (tng)= (tng){(byte)'\u00c4',(byte)'\u00e3'};
(tng)ByteToCharConverter (tng)converter (tng)= (tng)ByteToCharConverter. (tng)getDefault();
(tng)char (tng)c[] (tng)= (tng)converter.convertAll(b);
(tng)for (tng)(int (tng)i (tng)= (tng)0; (tng)i (tng)< (tng)c.length; (tng)i++) (tng){
(tng) (tng) (tng) (tng)System.out.println(Integer.toHexString(c[i]));
(tng)}
(tng)l果又是什么?Ҏ(gu)q_的编码而定?br />
(tng)char (tng)――〉byteQ?br /> (tng) (tng) (tng) (tng)String (tng)encoding (tng)= (tng)"gb2312";
(tng) (tng) (tng) (tng)char (tng)c[] (tng)= (tng){'\u4f60'};
(tng) (tng) (tng) (tng)CharToByteConverter (tng)converter (tng)= (tng)CharToByteConverter.getConverter(encoding);
(tng) (tng) (tng) (tng)byte (tng)b[] (tng)= (tng)converter.convertAll(c);
(tng) (tng) (tng) (tng)for (tng)(int (tng)i (tng)= (tng)0; (tng)i (tng)< (tng)b.length; (tng)i++) (tng){
(tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println(Integer.toHexString(b[i]));
(tng) (tng) (tng) (tng)}
l果是什么?0x00c4,0x00e3
如果encoding (tng)="8859_1"Q结果又是什么?0x3f
如果代码改ؓ(f)
String (tng)encoding (tng)= (tng)"gb2312";
(tng) (tng) (tng) (tng)char (tng)c[] (tng)= (tng){'\u4f60'};
(tng) (tng) (tng) (tng)CharToByteConverter (tng)converter (tng)= (tng)CharToByteConverter.getDefault();
(tng) (tng) (tng) (tng)byte (tng)b[] (tng)= (tng)converter.convertAll(c);
(tng) (tng) (tng) (tng)for (tng)(int (tng)i (tng)= (tng)0; (tng)i (tng)< (tng)b.length; (tng)i++) (tng){
(tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println(Integer.toHexString(b[i]));
(tng) (tng) (tng) (tng)}
l果又是什么?Ҏ(gu)q_的编码而定?br />很多中文问题是从这两个最单的cL生出来的。而却有很多类不直接支持把encoding输入Q这l我们带来诸多不ѝ很多程序难得用encoding?jin),直接用default的encodingQ这q我们UL带来?jin)很多困难?br />
2.utf-8
utf-8是和unicode一一对应的,其实现很?br />7位的unicode: (tng)0 (tng)_ (tng)_ (tng)_ (tng)_ (tng)_ (tng)_ (tng)_ (tng)
11位的unicode: (tng)1 (tng)1 (tng)0 (tng)_ (tng)_ (tng)_ (tng)_ (tng)_ (tng)1 (tng)0 (tng)_ (tng)_ (tng)_ (tng)_ (tng)_ (tng)_ (tng)
16位的unicode: (tng)1 (tng)1 (tng)1 (tng)0 (tng)_ (tng)_ (tng)_ (tng)_ (tng)1 (tng)0 (tng)_ (tng)_ (tng)_ (tng)_ (tng)_ (tng)_ (tng)1 (tng)0 (tng)_ (tng)_ (tng)_ (tng)_ (tng)_ (tng)_ (tng)
21位的unicode: (tng)1 (tng)1 (tng)1 (tng)1 (tng)0 (tng)_ (tng)_ (tng)_ (tng)1 (tng)0 (tng)_ (tng)_ (tng)_ (tng)_ (tng)_ (tng)_ (tng)1 (tng)0 (tng)_ (tng)_ (tng)_ (tng)_ (tng)_ (tng)_ (tng)1 (tng)0 (tng)_ (tng)_ (tng)_ (tng)_ (tng)_ (tng)_ (tng)
大多数情冉|只用到16位以下的unicode: (tng)
"?的gb码是Q?xc4e3 (tng),unicode?x4f60
(tng) (tng) (tng) (tng)0xc4e3的二q制Q?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)1100 (tng)Q?100 (tng)Q?110 (tng)Q?011
׃只有两位我们按照两位的编码来排,但是我们发现q行不通,因ؓ(f)W7位不?因此Q返??"
(tng) (tng) (tng) (tng)0x4f60的二q制Q?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)0100 (tng)Q?111 (tng)Q?110 (tng)Q?000
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)我们用utf-8补齐Q变成:(x)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)1110 (tng)Q?100 (tng)Q?011 (tng)Q?101 (tng)Q?010 (tng)Q?000
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)e4--bd-- (tng)a0
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)于是q回Q?xe4,0xbd,0xa0?br />
3.string和byte[]
string其实核心(j)是char[],然而要把byte转化成stringQ必ȝq编码。string.length()其实是char数组的长度,如果使用不同的编码,很可能会(x)错分Q造成散字和ؕ码?br />例如Q?br />String (tng)encoding (tng)= (tng)“?
byte (tng)[] (tng)b={(byte)'\u00c4',(byte)'\u00e3'}; (tng)
String (tng)str=new (tng)String(b,encoding);
如果encoding=8859_1Q会(x)有两个字Q但是encoding=gb2312只有一个字q个问题在处理分|l常发生 (tng)?br />
4.Reader,Writer (tng)/ (tng)I(yng)nputStream,OutputStream
Reader和W(xu)riter核心(j)是charQInputStream和OutputStream核心(j)是byte。但是Reader和W(xu)riter的主要目的是要把char?写InputStream/OutputStream?br />例如Q?br />文gtest.txt只有一??字,0xc4,0xe3
String (tng)encoding (tng)= (tng)"gb2312";
(tng) (tng) (tng) (tng)I(yng)nputStreamReader (tng)reader (tng)= (tng)new (tng)I(yng)nputStreamReader(new (tng)FileInputStream(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)"text.txt"), (tng)encoding);
(tng) (tng) (tng) (tng)char (tng)c[] (tng)= (tng)new (tng)char[10];
(tng) (tng) (tng) (tng)int (tng)length (tng)= (tng)reader.read(c);
(tng) (tng) (tng) (tng)for (tng)(int (tng)i (tng)= (tng)0; (tng)i (tng)< (tng)length; (tng)i++) (tng){
(tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println(c[i]);
(tng) (tng) (tng) (tng)}
l果是什么??br />如果encoding (tng)="8859_1"Q结果是什么???两个字符Q表CZ认识?br />反过来的例子自己做?br />
5.我们要对java的编译器有所?jin)解Q?br />javac (tng)?encoding
我们常常没有用到encodingq个参数。其实encodingq个参数对于跨^台的操作是很重要的。如果没有指定encodingQ则按照pȝ的默认encoding,gbq_上是gb2312Q英文^C是iso8859_1?br />java的编译器实际上是调用sun.tools.javac.main的类Q对文gq行~译Q这个类有compile函数中间有一个encoding的变?-encoding的参数其实直接传lencoding变量。编译器是Ҏ(gu)q个变量来读取java文g的,然后把用utf-8形式~译成class文g?br />例子代码Q?br />String (tng)str (tng)= (tng)"?;
(tng) (tng) (tng) (tng)FileWriter (tng)writer (tng)= (tng)new (tng)FileWriter("text.txt");
(tng) (tng) (tng) (tng)write.write(str);
(tng) (tng) (tng) (tng)writer.close();
如果用gb2312~译Q你?x)找到e4 (tng)bd (tng)a0的字D?tng)?br />如果?859_1~译Q?0c4 (tng)00e3的二q制Q?br />0000Q?000 (tng)Q?100Q?100 (tng)Q?000Q?000 (tng)Q?110Q?011
因ؓ(f)每个字符都大?位,因此?1位编码:(x) (tng)
1100Q?001Q?000Q?100Q?100Q?011Q?010Q?011 (tng)
c1-- (tng)84-- c3-- (tng)a3 (tng)
你会(x)扑ֈc1 (tng)84 (tng)c3 (tng)a3 (tng)?br />
但是我们往往忽略掉这个参敎ͼ因此q样往往?x)有跨^台的问题Q?br />样例代码在中文^C~译Q生成zhclass
样例代码在英文^C~译Q输出enclass
(tng) (tng)(1). (tng)zhclass在中文^C执行ok,但是在英文^C不行 (tng)
(tng) (tng)(2). (tng) (tng) (tng) (tng)enclass在英文^C执行ok,但是在中文^C不行
原因Q?br /> (tng) (tng)(1). (tng) (tng) (tng) (tng)在中文^C~译后,其实str在运行态的char[]?x4f60, 在中文^Cq行Qfilewriter的缺省编码是gb2312,因此 (tng)chartobyteconverter?x)自动用调用gb2312的converter,把str转化成byte输入到fileoutputstream中,于是0xc4,0xe3放进?jin)文件。?br />但是如果是在英文q_下,chartobyteconverter的缺省值是8859_1, (tng)filewriter?x)自动调?859_1去{化str,但是他无法解释,因此他会(x)输出"?"
(tng) (tng)(2). (tng) (tng) (tng) (tng)在英文^C~译后,其实str在运行态的char[]?x00c4 (tng)0x00e3, (tng)在中文^Cq行Q中文无法识别,因此?x)出??Q?br />在英文^CQ?x00c4-->0xc4,0x00e3->0xe3Q因?xc4,0xe3被放q了(jin)文g?br />
6. (tng) (tng) (tng) (tng)其它原因Q?lt;%@ (tng)page (tng)contentType="text/html; (tng)charset=GBK" (tng)%>
讄览器的昄~码Q如果response的数据是utf8~码Q显C将是ؕ码,但是q和上q原因还?sh)一栗?br />
7. (tng) (tng) (tng) (tng)发生~码的地方:(x)
?tng) (tng) (tng) (tng)从数据库到javaE序 (tng)byte――〉char
?tng) (tng) (tng) (tng)从javaE序到数据库 (tng)char――〉byte
?tng) (tng) (tng) (tng)从文g到javaE序 (tng)byte――〉char
?tng) (tng) (tng) (tng)从javaE序到文件?tng)char――〉byte
?tng) (tng) (tng) (tng)从javaE序到页面显C?tng)char――〉byte
?tng) (tng) (tng) (tng)从面form提交数据到javaE序byte――〉char
?tng) (tng) (tng) (tng)从到javaE序byte――〉char
?tng) (tng) (tng) (tng)从javaE序到流char――〉byte
谢志钢的解决Ҏ(gu)Q?br />我是使用配置qo(h)器的Ҏ(gu)解决中文q的:(x)
<web-app>
(tng) (tng)<filter>
(tng) (tng) (tng) (tng)<filter-name>RequestFilter</filter-name>
(tng) (tng) (tng) (tng)<filter-class>net.golden.uirs.util.RequestFilter</filter-class>
(tng) (tng) (tng) (tng)<init-param>
(tng) (tng) (tng) (tng) (tng) (tng)<param-name>charset</param-name>
(tng) (tng) (tng) (tng) (tng) (tng)<param-value>gb2312</param-value>
(tng) (tng) (tng) (tng)</init-param>
(tng) (tng)</filter>
(tng) (tng)<filter-mapping>
(tng) (tng) (tng) (tng)<filter-name>RequestFilter</filter-name>
(tng) (tng) (tng) (tng)<url-pattern>*.jsp</url-pattern>
(tng) (tng)</filter-mapping>
</web-app>
(tng) (tng)public (tng)void (tng)doFilter(ServletRequest (tng)req, (tng)ServletResponse (tng)res,
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)FilterChain (tng)fChain) (tng)throws (tng)I(yng)OException, (tng)ServletException (tng){
(tng) (tng) (tng) (tng)HttpServletRequest (tng)request (tng)= (tng)(HttpServletRequest) (tng)req;
(tng) (tng) (tng) (tng)HttpServletResponse (tng)response (tng)= (tng)(HttpServletResponse) (tng)res;
(tng) (tng) (tng) (tng)HttpSession (tng)session (tng)= (tng)request.getSession();
(tng) (tng) (tng) (tng)String (tng)userId (tng)= (tng)(String) (tng)session.getAttribute("userid");
req.setCharacterEncoding(this.filterConfig.getInitParameter("charset")); (tng)// (tng)讄字符集?
实际上是讄?jin)byte (tng)――〉char的encoding
(tng) (tng) (tng) (tng)try (tng){
(tng) (tng) (tng) (tng) (tng) (tng)if (tng)(userId (tng)== (tng)null (tng)|| (tng)userId.equals("")) (tng){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (tng)(!request.getRequestURL().toString().matches(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)".*/uirs/logon/logon(Controller){0,1}\\x2Ejsp$")) (tng){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)session.invalidate();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)response.sendRedirect(request.getContextPath() (tng)+
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)"/uirs/logon/logon.jsp");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng)else (tng){ (tng)// (tng)看看是否h信息上报pȝ的权?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (tng)(!net.golden.uirs.util.UirsChecker.check(userId, (tng)"信息上报pȝ",
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)net.golden.uirs.util.UirsChecker.ACTION_DO)) (tng){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if (tng)(!request.getRequestURL().toString().matches(
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)".*/uirs/logon/logon(Controller){0,1}\\x2Ejsp$")) (tng){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)response.sendRedirect(request.getContextPath() (tng)+
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)"/uirs/logon/logonController.jsp");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng)catch (tng)(Exception (tng)ex) (tng){
(tng) (tng) (tng) (tng) (tng) (tng)response.sendRedirect(request.getContextPath() (tng)+
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)"/uirs/logon/logon.jsp");
(tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng)fChain.doFilter(req, (tng)res);
(tng) (tng)}
点击查看原文
]]>
一、?tng)整型、实型、字W型变量中的怺转换
在Java中整型、实型、字W型被视为同一cL据,q些cd׃U到高分别?byteQshortQchar)??int??long??float??doubleQ低U变量可以直接{换ؓ(f)高变量Q例如,下面的语句可以在Java中直接通过Q?br />byte (tng)b;
int (tng)i=b;
而将高变量转换ZU变量时Q情况会(x)复杂一些,你可以用强制类型{换。即你必采用下面这U语句格式:(x)
int (tng)i;
byte (tng)b=(byte)i;
可以惌Q这U{换肯定可能会(x)D溢出或精度的下降Q因此我们ƈ不推荐用这U{换?br />
二、Java的包装类
在我们讨论其它变量类型之间的怺转换Ӟ我们需要了(jin)解一下Java的包装类Q所谓包装类Q就是可以直接将单类型的变量表示Z个类Q在执行变量cd的相互{换时Q我们会(x)大量使用q些包装cRJava共有六个包装c,分别是Boolean、Character、Integer、Long、Float和?tng)DoubleQ从字面上我们就可以看出它们分别对应于?tng)boolean、char、int、long、float和double。而String和Date本n是cR所以也׃存在什么包装类的概念了(jin)?br />
三、简单类型变量和包装cM间的怺转换
单类型的变量转换为相应的包装c,可以利用包装cȝ构造函数。即Q?br />Boolean(boolean (tng)value)、Character(char (tng)value)、Integer(int (tng)value)、Long(long (tng)value)、Float(float (tng)value)、Double(double (tng)value)
而在各个包装cMQL形ؓ(f)××Value()的方法,来得到其对应的简单类型数据。利用这U方法,也可以实C同数值型变量间的转换Q例如,对于一个双_ֺ实型c,intValue()可以得到其对应的整型变量Q而doubleValue()可以得到其对应的双精度实型变量?br />
四、Stringcd其它数据cd的相互{?br />对于上面的这些包装类Q除?jin)Character以外Q都有可以直接用字W串参数的构造函敎ͼq也׃得我们将Stringc{换ؓ(f)q些数据cd变得相当之简单,卻I(x)
Boolean(String (tng)s)、Integer(String (tng)s)、Long(String (tng)s)、Float(String (tng)s)、Double(String (tng)s)
而将Stringc{换ؓ(f)DatecM可以使用q样的构造函敎ͼ(x)Date(String (tng)s)
现在我们q剩下一个字W型变量Q事实上Stringcd以理解ؓ(f)一个char型数l,因此我们可以在StringcM扑ֈq样的方法来实现q种转换Q?tng)charAt(int (tng)index)可以得到StringcM某一位置上的字符QtoCharArray()更可以将整个Stringc{换成一个char的数l?br />对于所有的包装c都存在一个名为toString()的方法可以将其{换成对应的Stringc,而对于整型类和长整型c,q可以用?tng)toBinaryString(int (tng)i)、toHexString(int (tng)i)、toOctalString(int (tng)i)分别以二q制、十六进制和八进制的形式q行到Stringcȝ转换?br />
五、将字符型直接做为数D{换ؓ(f)其它数据cd
字W型变量转换为数值型变量实际上有两种对应关系Q在我们在第一部分所说的那种转换中,实际上是其转换成对应的ASCII码,但是我们有时q需要另一U{换关p,例如Q?’就是指的数?Q而不是其ASCII码,对于q种转换Q我们可以用Character的getNumericValue(char (tng)ch)Ҏ(gu)?br />
六、DatecM其它数据cd的相互{?br />整型和DatecM间ƈ不存在直接的对应关系Q只是你可以使用int型ؓ(f)分别表示q、月、日、时、分、秒Q这样就在两者之间徏立了(jin)一个对应关p,在作q种转换Ӟ你可以用DatecL造函数的三种形式Q?br />Date(int (tng)year, (tng)int (tng)month, (tng)int (tng)date)Q以int型表C年、月、日
Date(int (tng)year, (tng)int (tng)month, (tng)int (tng)date, (tng)int (tng)hrs, (tng)int (tng)min)Q以int型表C年、月、日、时、分
Date(int (tng)year, (tng)int (tng)month, (tng)int (tng)date, (tng)int (tng)hrs, (tng)int (tng)min, (tng)int (tng)sec)Q以int型表C年、月、日、时、分、秒
在长整型和DatecM间有一个很有趣的对应关p,是一个时间表CZؓ(f)距离格林治标准旉1970q?????U的毫秒数。对于这U对应关p,DatecM有其相应的构造函敎ͼ(x)Date(long (tng)date)
获取DatecM的年、月、日、时、分、秒以及(qing)星期你可以用DatecȝgetYear()、getMonth()、getDate()、?tng)getHours()、getMinutes()、getSeconds()、getDay()Ҏ(gu)Q你也可以将其理解ؓ(f)Datec{换成int?br />而DatecȝgetTime()Ҏ(gu)可以得到我们前面所说的一个时间对应的长整型数Q与包装cMPDatecM有一个toString()Ҏ(gu)可以其转换为StringcR?br />在Java的数据类型{换中Q你q有一些其它方法可用,但是Q上面所介绍的这些方法对于你的实际编E已l够了(jin)Q不是吗Q?br />
原文地址
]]>
本文主要包括以下几个斚wQ编码基本知识,javaQ系lYӞurlQ工兯Y件等。?br />
在下面的描述中,以"中文"两个字ؓ(f)例,l查表可以知道其GB2312~码?d6d0 (tng)cec4"QUnicode~码?4e2d (tng)6587"Q?tng)UTF~码是"e4b8ad (tng)e69687"。注意,q两个字没有iso8859-1~码Q但可以用iso8859-1~码?表示"。?br />
2. (tng)~码基本知识 (tng)
最早的~码是iso8859-1Q和ascii~码怼。但Z(jin)方便表示各种各样的语aQ逐渐出现?jin)很多标准编码,重要的有如下几个。?br />
2.1. (tng)iso8859-1 (tng)
属于单字节编码,最多能表示的字W范围是0-255Q应用于英文pd。比如,字母'a'的编码ؓ(f)0x61=97。?br />
很明显,iso8859-1~码表示的字W范围很H,无法表示中文字符。但是,׃是单字节~码Q和计算机最基础的表C单位一_(d)所以很多时候,仍旧使用 (tng)iso8859-1~码来表C。而且在很多协议上Q默认用该~码。比如,虽然"中文"两个字不存在iso8859-1~码Q以gb2312~码ZQ应该是"d6d0 (tng)cec4"两个字符Q用iso8859-1~码的时候则它拆开?个字节来表示Q?d6 (tng)d0 (tng)ce (tng)c4"Q事实上Q在q行存储的时候,也是以字节ؓ(f)单位处理的)(j)。而如果是UTF~码Q则?个字?e4 (tng)b8 (tng)ad (tng)e6 (tng)96 (tng)87"。很明显Q这U表C方法还需要以另一U编码ؓ(f)基础。?br />
2.2. (tng)GB2312/GBK (tng)
q就是汉子的国标码,专门用来表示汉字Q是双字节编码,而英文字母和iso8859-1一_(d)兼容iso8859-1~码Q。其中gbk~码能够用来同时表示J体字和体字Q而gb2312只能表示体字Qgbk是兼容gb2312~码的。?br />
2.3. (tng)unicode (tng)
q是最l一的编码,可以用来表示所有语a的字W,而且是定长双字节Q也有四字节的)(j)~码Q包括英文字母在内。所以可以说它是不兼容iso8859-1~码的,也不兼容M~码。不q,相对于iso8859-1~码来说Quniocode~码只是在前面增加了(jin)一?字节Q比如字?a'?00 (tng)61"。?br />
需要说明的是,定长~码便于计算机处理(注意GB2312/GBK不是定长~码Q,而unicode又可以用来表C所有字W,所以在很多软g内部是用unicode~码来处理的Q比如java。?br />
2.4. (tng)UTF (tng)
考虑到unicode~码不兼容iso8859-1~码Q而且Ҏ(gu)占用更多的空_(d)(x)因ؓ(f)对于英文字母Qunicode也需要两个字节来表示。所以?tng)unicode不便于传输和存储。因此而生了(jin)utf~码Qutf~码兼容iso8859-1~码Q同时也可以用来表示所有语a的字W,不过Qutf~码是不定长~码Q每一个字W的长度?-6个字节不{。另外,utf~码自带单的校验功能。一般来Ԍ英文字母都是用一个字节表C,而汉字用三个字节。?tng)?br />
注意Q虽然说utf是ؓ(f)?jin)用更的I间而用的Q但那只是相对于unicode~码来说Q如果已l知道是汉字Q则使用 (tng)GB2312/GBK无疑是最节省的。不q另一斚wQ值得说明的是Q虽然utf~码Ҏ(gu)字?个字节,但即使对于汉字网,utf~码也会(x)比?tng)unicode~码节省Q因为网中包含?jin)很多的英文字符。?br />
3. (tng)java对字W的处理 (tng)
在java应用软g中,?x)有多处涉?qing)到字W集~码Q有些地斚w要进行正的讄Q有些地斚w要进行一定程度的处理。?br />
3.1. (tng)getBytes(charset) (tng)
q是java字符串处理的一个标准函敎ͼ其作用是字W串所表示的字W按照charset~码Qƈ以字节方式表C。注意字W串在java内存?sh)L按?tng)unicode~码存储的。比?中文"Q正常情况下Q即没有错误的时候)(j)存储?4e2d (tng)6587"Q如果charset?gbk"Q则被编码ؓ(f) (tng)"d6d0 (tng)cec4"Q然后返回字?d6 (tng)d0 (tng)ce (tng)c4"。如果charset?utf8"则最后是"e4 (tng)b8 (tng)ad (tng)e6 (tng)96 (tng)87"。如果是"iso8859-1"Q则׃无法~码Q最后返回?3f (tng)3f"Q两个问P(j)。?br />
3.2. (tng)new (tng)String(charset) (tng)
q是java字符串处理的另一个标准函敎ͼ和上一个函数的作用相反Q将字节数组按照charset~码q行l合识别Q最后{换ؓ(f)unicode存储。参考上qgetBytes的例子,"gbk" (tng)?utf8"都可以得出正的l果"4e2d (tng)6587"Q但iso8859-1最后变成了(jin) (tng)"003f (tng)003f"Q两个问P(j)。?br />
因ؓ(f)utf8可以用来表示/~码所有字W,所以new (tng)String( (tng)str.getBytes( (tng)"utf8" (tng)), (tng)"utf8" (tng)) (tng)=== (tng)strQ即完全可逆。?br />
3.3. (tng)setCharacterEncoding() (tng)
该函数用来设|httph或者相应的~码。?br />
对于requestQ是指提交内容的~码Q指定后可以通过getParameter()则直接获得正的字符Ԍ如果不指定,则默认用iso8859-1 (tng)~码Q需要进一步处理。参见下q?表单输入"。值得注意的是在执行setCharacterEncoding()之前Q不能执行Q何?tng)getParameter()。java (tng)doc上说明:(x) (tng)This (tng)method (tng)must (tng)be (tng)called (tng)prior (tng)to (tng)reading (tng)request (tng)parameters (tng)or (tng)reading (tng)input (tng)using (tng)getReader (tng)()。而且Q该指定只对POSTҎ(gu)有效Q对GETҎ(gu)无效。分析原因,应该是在执行W一个getParameter()的时候,java会(x)按照~码分析所有的提交内容Q而后l的getParameter()不再q行分析Q所以setCharacterEncoding()无效。而对于GETҎ(gu)提交表单是,提交的内容在URL中,一开始就已经按照~码分析所有的提交内容QsetCharacterEncoding()自然无效。?br />
对于responseQ则是指定输出内容的~码Q同Ӟ该设|会(x)传递给览器,告诉览器输出内Ҏ(gu)采用的编码。?br />
3.4. (tng)处理q程 (tng)
下面分析两个有代表性的例子Q说明java对编码有关问题的处理Ҏ(gu)。?br />
3.4.1. (tng)表单输入 (tng)
User (tng)input (tng) (tng)* (tng)(gbk:d6d0 (tng)cec4) (tng) (tng)browser (tng) (tng)*(gbk:d6d0 (tng)cec4) (tng) (tng)web (tng)server (tng) (tng)iso8859-1(00d6 (tng)00d (tng)000ce (tng)00c4) (tng) (tng) (tng)classQ需要在class中进行处理:(x)getbytes("iso8859-1")为d6 (tng)d0 (tng)ce (tng)c4Qnew (tng)String (tng)("gbk")为d6d0 (tng)cec4Q内存(sh)以unicode~码则ؓ(f)4e2d (tng)6587。?br />
l (tng)用户输入的编码方式和面指定的编码有养I也和用户的操作系l有养I所以是不确定的Q上例以gbkZ。?br />
l (tng)从browser到web (tng)serverQ可以在表单中指定提交内Ҏ(gu)使用的字W集Q否则会(x)使用面指定的编码。而如果在url中直接用?的方式输入参敎ͼ则其~码往往是操作系l本w的~码Q因时和面无关。上qC旧以gbk~码Z。?br />
l (tng)Web (tng)server (tng)接收到的是字节流Q默认时QgetParameterQ会(x)以iso8859-1~码处理之,l果是不正确的,所以需要进行处理。但如果预先讄?jin)编码(通过request. (tng)setCharacterEncoding (tng)()Q,则能够直接获取到正确的结果。?br />
l (tng)在页面中指定~码是个好习(fn)惯,否则可能失去控制Q无法指定正的~码。?br />
3.4.2. (tng)文g~译 (tng)
假设文g是gbk~码保存的,而编译有两种~码选择Qgbk或者iso8859-1Q前者是中文windows的默认编码,后者是linux的默认编码,当然也可以在~译时指定编码。?br />
Jsp (tng) (tng)* (tng)(gbk:d6d0 (tng)cec4) (tng) (tng)java (tng)file (tng) (tng)*(gbk:d6d0 (tng)cec4) (tng) (tng)compiler (tng)read (tng) (tng)uincode(gbk: (tng) (tng)4e2d (tng)6587; (tng)iso8859-1: (tng)00d6 (tng)00d (tng)000ce (tng)00c4) (tng) (tng)compiler (tng)write (tng) (tng)utf(gbk: (tng)e4b8ad (tng)e69687; (tng) (tng)iso8859-1: (tng)*) (tng) (tng)compiled (tng)file (tng) (tng)unicode(gbk: (tng)4e2d (tng)6587; (tng)iso8859-1: (tng)00d6 (tng)00d (tng)000ce (tng)00c4) (tng) (tng) (tng)class。所以用gbk~码保存Q而用iso8859-1~译的结果是不正的。?br />
class (tng) (tng)unicode(4e2d (tng)6587) (tng) (tng)system.out (tng)/ (tng)jsp.out (tng) (tng)gbk(d6d0 (tng)cec4) (tng) (tng)os (tng)console (tng)/ (tng)browser。?br />
l (tng)文g可以以多U编码方式保存,中文windows下,默认为ansi/gbk。?br />
l (tng) (tng)~译器读取文件时Q需要得到文件的~码Q如果未指定Q则使用pȝ默认~码。一般class文gQ是以系l默认编码保存的Q所以编译不?x)出问题Q但对于 (tng)jsp文gQ如果在中文windows下编辑保存,而部|在英文linux下运?~译Q则?x)出现问题。所以需要在jsp文g中用 (tng)pageEncoding指定~码。?br />
l (tng)Java~译的时候会(x)转换成统一的unicode~码处理Q最后保存的时候再转换为utf~码。?br />
l (tng) (tng)当系l输出字W的时候,?x)按指定~码输出Q对于中文windows下,System.out用gbk~码Q而对于responseQ浏览器Q,则用?tng)jsp文g头指定的contentTypeQ或者可以直接ؓ(f)response指定~码。同Ӟ?x)告诉browser|页的编码。如果未指定Q则?x)用 (tng)iso8859-1~码。对于中文,应该为browser指定输出字符串的~码。?br />
l (tng)browser昄|页的时候,首先使用response中指定的~码Qjsp文g头指定的contentType最l也反映在response上)(j)Q如果未指定Q则?x)用网中metaҎ(gu)定中的contentType。?br />
3.5. (tng)几处讄 (tng)
对于web应用E序Q和~码有关的设|或者函数如下。?br />
3.5.1. (tng)jsp~译 (tng)
指定文g的存储编码,很明显,该设|应该置于文件的开头。例如:(x)<%@page (tng)pageEncoding="GBK"%>。另外,对于一般class文gQ可以在~译的时候指定编码。?br />
3.5.2. (tng)jsp输出 (tng)
指定文g输出到browser是用的~码Q该讄也应该置于文件的开头。例如:(x)<%@ (tng)page (tng)contentType="text/html; (tng) (tng)charset= (tng)GBK" (tng)%>。该讄和response.setCharacterEncoding("GBK"){效。?br />
3.5.3. (tng)meta讄 (tng)
指定|页使用的编码,该设|对?rn)态网尤其有作用。因为静(rn)态网|法采用jsp的设|,而且也无法执行response.setCharacterEncoding()。例如:(x) (tng)
如果同时采用?jin)jsp输出和meta讄两种~码指定方式Q则jsp指定的优先。因为jsp指定的直接体现在response中。?br />
需要注意的是,apache有一个设|可以给无编码指定的|页指定~码Q该指定{同于jsp的编码指定方式,所以会(x)覆盖?rn)态网中的meta指定。所以有人徏议关闭该讄。?br />
3.5.4. (tng)form讄 (tng)
当浏览器提交表单的时候,可以指定相应的编码。例如:(x)。一般不必不使用该设|,览器会(x)直接使用|页的编码。?br />
4. (tng)pȝ软g (tng)
下面讨论几个相关的系lY件。?br />
4.1. (tng)mysql数据库?br />
很明显,要支持多语言Q应该将数据库的~码讄成utf或者unicodeQ而utf更适合与存储。但是,如果中文数据中包含的英文字母很少Q其实unicode更ؓ(f)适合。?br />
数据库的~码可以通过mysql的配|文件设|,例如default-character-set=utf8。还可以在数据库链接URL中设|,例如Q?tng) (tng)useUnicode=true&characterEncoding=UTF-8。注意这两者应该保持一_(d)在新的sql版本里,在数据库链接URL里可以不q行讄Q但也不能是错误的设|。?br />
4.2. (tng)apache (tng)
appache和编码有关的配置在httpd.conf中,例如AddDefaultCharset (tng)UTF-8。如前所qͼ该功能会(x)所有静(rn)态页面的~码讄为UTF-8Q最好关闭该功能。?br />
另外Qapacheq有单独的模块来处理|页响应_(d)其中也可能对~码q行讄。?br />
4.3. (tng)linux默认~码 (tng)
q里所说的linux默认~码Q是指运行时的环境变量。两个重要的环境变量是LC_ALL和LANGQ默认编码会(x)影响到java (tng)URLEncode的行为,下面有描q。?br />
都设|ؓ(f)"zh_CN.UTF-8"。?br />
4.4. (tng)其它 (tng)
Z(jin)支持中文文g名,linux在加载磁盘时应该指定字符集,例如Qmount (tng)/dev/hda5 (tng)/mnt/hda5/ (tng)-t (tng)ntfs (tng)-o (tng)iocharset=gb2312。?br />
另外Q如前所qͼ使用GETҎ(gu)提交的信息不支持request.setCharacterEncoding()Q但可以通过tomcat的配|文件指定字W集Q在tomcat的server.xml文g中,形如Q。这U方法将l一讄所有请求,而不能针对具体页面进行设|,也不一定和browser使用的编码相同,所以有时候ƈ不是所期望的。?br />
5. (tng)URL地址 (tng)
URL地址中含有中文字W是很麻?ch)的Q前面描q过使用GETҎ(gu)提交表单的情况,使用GETҎ(gu)Ӟ参数是包含在URL中。?br />
5.1. (tng)URL~码 (tng)
对于URL中的一些特D字W,览器会(x)自动q行~码。这些字W除?/?&"{外Q还包括unicode字符Q比如汉子。这时的~码比较Ҏ(gu)。?br />
IE (tng)有一个选项"L使用UTF-8发送URL"Q当该选项有效ӞIE会(x)对特D字W进行UTF-8~码Q同时进行URL~码。如果改选项无效Q则使用默认~码"GBK"Qƈ且不q行URL~码。但是,对于URL后面的参敎ͼ则L不进行编码,相当于UTF-8选项无效。比?中文.html?a=中文"Q当UTF-8选项有效Ӟ发送链?%e4%b8%ad%e6%96%87.html?a=\x4e\x2d\x65\x87"Q而UTF-8选项无效Ӟ发送链?\x4e\x2d\x65\x87.html?a=\x4e\x2d\x65\x87"。注意后者前面的"中文"两个字只?个字节,而前者却?8个字节,q主要时URL~码的原因。?br />
当web (tng)serverQtomcatQ接收到该链接时Q将?x)进行URL解码Q即L (tng)"%"Q同时按照ISO8859-1~码Q上面已l描qͼ可以使用URLEncoding来设|成其它~码Q识别。上qC子的l果分别?\ue4\ (tng)ub8\uad\ue6\u96\u87.html?a=\u4e\u2d\u65\u87"?\u4e\u2d\u65\u87.html?a=\ (tng)u4e\u2d\u65\u87"Q注意前者前面的"中文"两个字恢复成?个字W。这里用"\u"Q表C是unicode。?br />
所以,׃客户端设|的不同Q相同的链接Q在服务器上得到?jin)不同结果。这个问题(sh)h都遇刎ͼ却没有很好的解决办法。所以有的网站会(x)用户试关闭UTF-8选项。不q,下面?x)描qC个更好的处理办法。?br />
5.2. (tng)rewrite (tng)
熟?zhn)的h都知道,apache有一个功能强大的rewrite模块Q这里不描述其功能。需要说明的是该模块?x)自动将URL解码Q去?Q,卛_成上qWweb (tng)serverQtomcatQ的部分功能。有相关文档介绍说可以用[NE]参数来关闭该功能Q但我试验ƈ未成功,可能是因为版本(我用的是?tng)apache (tng)2.0.54Q问题。另外,当参C含有"?& (tng)"{符L(fng)时候,该功能将Dpȝ得不到正常结果。?br />
rewrite本ng完全是采用字节处理的方式Q而不考虑字符串的~码Q所以不?x)带来编码问题。?br />
5.3. (tng)URLEncode.encode() (tng)
q是Java本n提供对的URL~码函数Q完成的工作和上qUTF-8选项有效时浏览器所做的工作怼。值得说明的是Qjava已经不赞成不指定~码来用该Ҏ(gu)QdeprecatedQ。应该在使用的时候增加编码指定。?br />
当不指定~码的时候,该方法用系l默认编码,q会(x)D软gq行l果得不定。比如对?中文"Q当pȝ默认~码?gb2312"Ӟl果?%4e% (tng)2d%65%87"Q而默认编码ؓ(f)"UTF-8"Q结果却?%e4%b8%ad%e6%96%87"Q后l程序将难以处理。另外,q儿说的pȝ默认~码是由q行tomcat时的环境变量LC_ALL和LANG{决定的Q曾l出现过tomcat重启后就出现q的问题,最后才郁闷的发现是因ؓ(f)修改修改?jin)这两个环境变量。?br />
l一指定?UTF-8"~码Q可能需要修改相应的E序。?br />
5.4. (tng)一个解x(chng)案?br />
上面说vq,因ؓ(f)览器设|的不同Q对于同一个链接,web (tng)server收到的是不同内容Q而Y件系l有无法知道q中间的区别Q所以这一协议目前q存在缺陗?br />
针对具体问题Q不应该侥幸认ؓ(f)所有客L(fng)IE讄都是UTF-8有效的,也不应该_暴的徏议用户修改IE讄Q要知道Q用户不可能去记住每一个web (tng)server的设|。所以,接下来的解决办法只能是让自qE序多一Ҏ(gu)能:(x)Ҏ(gu)内容来分析编码是否UTF-8。?br />
比较q运的是UTF-8~码相当有规律,所以可以通过分析传输q来的链接内容,来判断是否是正确的UTF-8字符Q如果是Q则以UTF-8处理之,如果不是Q则使用客户默认~码Q比?GBK"Q,下面是一个判断是否UTF-8的例子,如果你了(jin)解相应规律,容易理解。?br />
public (tng)static (tng)boolean (tng)isValidUtf8(byte[] (tng)b,int (tng)aMaxCount){ (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng)int (tng)lLen=b.length,lCharCount=0; (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng)for(int (tng)i=0;i
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)byte (tng)lByte=b[i++];//to (tng)fast (tng)operation, (tng)++ (tng)now, (tng)ready (tng)for (tng)the (tng)following (tng)for(;;) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if(lByte>=0) (tng)continue;//>=0 (tng)is (tng)normal (tng)ascii (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if(lByte<(byte)0xc0 (tng)|| (tng)lByte>(byte)0xfd) (tng)return (tng)false; (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)int (tng)lCount=lByte>(byte)0xfc?5:lByte>(byte)0xf8?4 (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng):lByte>(byte)0xf0?3:lByte>(byte)0xe0?2:1; (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)if(i+lCount>lLen) (tng)return (tng)false; (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)for(int (tng)j=0;j=(byte)0xc0) (tng)return (tng)false; (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng)} (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng)return (tng)true; (tng)
} (tng)
相应圎ͼ一个用上q方法的例子如下Q?br />
public (tng)static (tng)String (tng)getUrlParam(String (tng)aStr,String (tng)aDefaultCharset) (tng)
throws (tng)UnsupportedEncodingException{ (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng)if(aStr==null) (tng)return (tng)null; (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng)byte[] (tng)lBytes=aStr.getBytes("ISO-8859-1"); (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng)return (tng)new (tng)String(lBytes,StringUtil.isValidUtf8(lBytes)?"utf8":aDefaultCharset); (tng)
} (tng)
不过Q该Ҏ(gu)也存在缺P如下两方面:(x) (tng)
l (tng)没有包括对用户默认编码的识别Q这可以Ҏ(gu)h信息的语a来判断,但不一定正,因ؓ(f)我们有时候也?x)输入一些韩文,或者其他文字。?br />
l (tng)可能?x)错误判断UTF-8字符Q一个例子是"学习(fn)"两个字,其GBK~码? (tng)\xd1\xa7\xcf\xb0"Q如果用上qisValidUtf8Ҏ(gu)判断Q将q回true。可以考虑使用更严格的判断Ҏ(gu)Q不q估计效果不大。?br />
有一个例子可以证明google也遇C(jin)上述问题Q而且也采用了(jin)和上q相似的处理Ҏ(gu)Q比如,如果在地址栏中输入"http: (tng)//www.google.com/search?hl=zh-CN&newwindow=1&q=学习(fn)"Qgoogle无法正识别,而其他汉字一般能够正常识别。?br />
最后,应该补充说明一下,如果不用rewrite规则Q或者通过表单提交数据Q其实ƈ不一定会(x)遇到上述问题Q因时可以在提交数据时指定希望的~码。另外,中文文g名确实会(x)带来问题Q应该}慎用。?br />
6. (tng)其它 (tng)
下面描述一些和~码有关的其他问题。?br />
6.1. (tng)SecureCRT (tng)
除了(jin)览器和控制C~码有关外,一些客L(fng)也很有关pR比如在使用SecureCRTq接linuxӞ应该让SecureCRT的显C编码(不同的sessionQ可以有不同的编码设|)(j)和linux的编码环境变量保持一致。否则看到的一些帮助信息,可能是q。?br />
另外Qmysql有自q~码讄Q也应该保持和SecureCRT的显C编码一致。否则通过SecureCRT执行sql语句的时候,可能无法处理中文字符Q查询结果也?x)出Cؕ码。?br />
对于Utf-8文gQ很多编辑器Q比如记事本Q会(x)在文件开头增加三个不可见的标志字节,如果作ؓ(f)mysql的输入文Ӟ则必要Lq三个字W。(用?tng)linux的vi保存可以Lq三个字W)(j)。一个有的现象是,在中文windows下,创徏一个新txt文gQ用C本打开Q输?q?两个字,保存Q再打开Q你?x)发C个字没了(jin)Q只留下一个小黑点。?br />
6.2. (tng)qo(h)器?br />
如果需要统一讄~码Q则通过filterq行讄是个不错的选择。在filter (tng)class中,可以l一为需要的h或者回应设|编码。参加上qsetCharacterEncoding()。这个类apache已经l出?jin)可以直接用的例子SetCharacterEncodingFilter。?br />
6.3. (tng)POST和GET (tng)
很明显,以POST提交信息ӞURL有更好的可读性,而且可以方便的用setCharacterEncoding()来处理字W集问题。但GETҎ(gu)形成的URL能够更容易表辄늚实际内容Q也能够用于收藏。?br />
从统一的角度考虑问题Q徏议采用GETҎ(gu)Q这要求在程序中获得参数是进行特D处理,而无法用setCharacterEncoding()的便利,如果不考虑rewriteQ就不存在IE的UTF-8问题Q可以考虑通过讄URIEncoding来方便获取URL中的参数。?br />
6.4. (tng)J体~码转换 (tng)
GBK (tng)同时包含体和J体~码Q也是说同一个字Q由于编码不同,在GBK~码下属于两个字。有时候,Z(jin)正确取得完整的结果,应该繁体和体进行统一。可以考虑UTF、GBK中的所有繁体字Q{换ؓ(f)相应的简体字QBIG5~码的数据,也应该{化成相应的简体字。当?dng)仍旧以UTF~码存储。?br />
例如Q对?语言 (tng)?a"Q用UTF表示?\xE8\xAF\xAD\xE8\xA8\x80 (tng)\xE8\xAA\x9E\xE8\xA8\x80"Q进行简J体~码转换后应该是两个相同的?\xE8\xAF\xAD\xE8\xA8\x80>"。?br />
]]>
(tng) (tng) (tng)我看到很多脓(chung)子,上面描述MD5加密解密{话题,因此写此文章Z(jin)把MD5加密问题单的说个透彻Qƈ且给大家已经实践q的代码?br />
其次
(tng) (tng) (tng)MD5加密q不是把原文加密Q这个大家得注意Q既然没有把原文加密何来的解密呢Q简直是个笑话。MD5的用途就是把一D原文数据通过一定的法生成16字节的密文,通过q个密文我们可以(g)查原文的数据是否被修改过。常用在|络中明文数据传输,防止传输q程中内容被恶意修改。典型的应用协议为radiusQradius协议中有16byte是MD5所留的Q把用户的密码加在报文尾部进行MD5Q把l果存在|络中,所以明文部分看不到用户的密码,当服务器收到此包Q用同样的方法进行MD5Q如果加密出来的16byte一P说明是有效的未被恶意修改的网l包?br />
最?/b>
附上实现的代?br />
]]>
public String GetDateTime()
SimpleDateFormat myFormatter = new SimpleDateFormat("yyyy-MM- dd");
]]>
1,作用域public,protected,private,以及(qing)不写时的区别
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)作用域?tng) (tng) (tng)?/font> (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) 当前c?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)?同一package (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)子孙c?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)?其他package
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) public (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) √?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)?√?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)?√?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)??/font>
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) protected (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) √?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)?√?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)?√?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)?×
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) friendly (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) √?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)?√?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)× (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)?×
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) private (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)√?tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)?× (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) × (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)×
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)不写旉认ؓ(f)friendly
2,ArrayList和Vector的区?HashMap和Hashtable的区?/p>
{:(x)ArrayList与Vector主要从二斚w来说.
一.同步?Vector是线E安全的Q也是说是同步的,而ArrayList是线E序不安全的Q不是同步的
?数据增长:当需要增长时,Vector默认增长为原来一培,而ArrayList却是原来的一?
HashMap与HashTable主要从三斚w来说?
一.历史原因:Hashtable是基于陈旧的DictionarycȝQHashMap是Java 1.2引进的Map接口的一个实?
?同步?Hashtable是线E安全的Q也是说是同步的,而HashMap是线E序不安全的Q不是同步的
?|(x)只有HashMap可以让你空gZ个表的条目的key或value
3,char型变量能不能定义Z个中?Z?
是能够定义成Z个中文的Q因为java中以unicode~码Q一个char?6个字节,所以放一个中文是没问题的
4,多线E有几种表示Ҏ(gu),都是什?同步有几U实现方?都是什?
多线E有两种实现Ҏ(gu)Q分别是l承ThreadcM实现Runnable接口
同步的实现方面有一U,使用synchronized,wait,notify
5,l承时候类的执行顺序问?一般都是选择?问你会(x)打印Z?
6,内部cȝ实现方式?
7,垃圾回收机制,如何优化E序?
8,float型float f=3.4是否正确?
Jsp斚w
1,jsp有哪些内|对?作用分别是什?
2,jsp有哪些动?作用分别是什?
3,include的两U实现方式的区别?
4,两种跌{方式分别是什?有什么区?
Servlet斚w
1,说一说Servlet的生命周?
2,Servlet版本?忘(sh)(jin)问的是哪两个版本?的不?
Jdbc,Jdo斚w
1,可能?x)让你写一DJdbcqOracle的程?
2,Class.forName的作?Z么要?
3,Jdo是什?
JDO是Java对象持久化的规范之一Qؓ(f)java data object的简U?是一个用于存取某U数据仓库中的对象的标准化API。JDO提供?jin)透明的对象存储,因此对开发h员来_(d)存储数据对象完全不需要额外的代码Q如JDBC API的用)(j)。这些繁琐的例行工作已经转移到JDO产品提供商n上,使开发h员解脱出来,从而集中时间和_֊在业务逻辑上。另外,JDO很灵z,因ؓ(f)它可以在M数据底层上运行。JDBC只是面向关系数据库(RDBMS)JDO更通用Q提供到M数据底层的存储功能,比如关系数据库、文件、XML以及(qing)对象数据库(ODBMSQ等{,使得应用可移植性更强?/font>
Xml斚w
1,xml有哪些解析技?区别是什?
DOM:处理大型文g时其性能下降的非常厉実뀂这个问题是由DOM的树(wi)l构所造成的,q种l构占用的内存较多,而且DOM必须在解析文件之前把整个文档装入内存,适合对XML的随?/font>
SAX:不现于DOM,SAX是事仉动型的XML解析方式。它序dXML文gQ不需要一ơ全部装载整个文件。当遇到像文件开_(d)文档l束Q或者标{ּ头与标签l束Ӟ它会(x)触发一个事Ӟ用户通过在其回调事g中写入处理代码来处理XML文gQ适合对XML的顺序访?
STAX:Streaming API for XML (StAX)
2,你在目中用C(jin)xml技术的哪些斚w?如何实现?
用到?jin)数据存贮,信息配置两方面。在做数据交换^台时Q将不同数据源的数据l装成XML文gQ然后将XML文g压羃打包加密后通过|络传送给接收者,接收解密与解压羃后再同XML文g中还原相关信息进行处理。在做Y仉|时Q利用XML可以很方便的q行QY件的各种配置参数都存贮在XML文g中?/font>
3,用jdom解析xml文g时如何解决中文问?如何解析?
EJB斚w
1,EJB2.0有哪些内?分别用在什么场? EJB2.0和EJB1.1的区?
MVC斚w
1,MVC的各个部分都有那些技术来实现?如何实现?
设计模式斚w:
1,开发中都用C(jin)那些设计模式?用在什么场?
JavaScript斚w
(tng) (tng) (tng) (tng) (tng) 1,如何校验数字?
CORBA
(tng) (tng) (tng) (tng) (tng) 1,CORBA是什?用途是什?
(tng)
以上是我的ȝ,可能不是全部,因ؓ(f)旉问题,如果能够记v?我会(x)再加?有些问题描述的可能不准确,希望大家批评指正,问题都很基础,即不知?׃一Ҏ(gu)间查?csdn/java?p弄懂,希望Ҏ(gu)在找工作的朋友有所帮助,有所提醒.一份正率很高的笔试卷可能?x)?f)你的面试减轻负担,问不少问题.
当然我还是要提醒?br />
扑ַ作要面试Q有面试有对付面试的办法。以下一些题目来自我和我朋友痛苦的面试经历,提这些问题的公司包括IBM, E*Trade, Siebel, Motorola, SUN, 以及(qing)其它大小公司?br />
面试是没什么道理可讲的Q它的题目有的不合情理、脱d际。有在纸上写的,有当面考你的,也有在电(sh)话里问的Q给你I(yng)DE的估计很?否则你赶快去买彩, 说不定中)。所以如果你看完此文后,请不要抱怨说q些问题都能用IDE来解冟뀂你必须在Q何情况下准确回答q些问题Q在面试中如果出C两题回答不准很 有可能你p拒之门外?jin)?br />
当然q些都是Java的基本题Q那些面试的人大多数不会(x)问你Hibernate有多先进QEclipse的三个组成部分,或command design patternQ他们都是老一辈了(jin)Q最喜欢问的是基础知识。别看?jin)这些基Q我朋友水^一,l果栽在一到基知识的问题(sh)Q和高薪无缘?br />
好了(jin)废话说Q开始正题?br />
W一Q谈谈final, finally, finalize的区别?br />最常被问到?/p>
final—修饰符Q关键字Q如果一个类被声明ؓ(f)finalQ意味着它不能再z出新的子c,不能作ؓ(f)父类被ѝ因此一个类不能既被声明?abstract的,又被声明为final的。将变量或方法声明ؓ(f)finalQ可以保证它们在使用中不被改变。被声明为final的变量必d声明时给定初|而在以后的引用中只能dQ不可修攏V被声明为final的方法也同样只能使用Q不能重?
finally—再异常处理时提?finally 块来执行M清除操作。如果抛Z个异常,那么相匹配的 catch 子句׃(x)执行Q然后控制就?x)进?finally 块(如果有的话)(j)?
finalize—方法名。Java 技术允怋?finalize() Ҏ(gu)在垃圾收集器对象从内存?sh)清除出M前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对q个对象调用的。它是在 Object cM定义的,因此所有的c都l承?jin)它。子c覆?finalize() Ҏ(gu)以整理系l资源或者执行其他清理工作。finalize() Ҏ(gu)是在垃圾攉器删除对象之前对q个对象调用的?
W二QAnonymous Inner Class (匿名内部c? 是否可以extends(l承)其它c,是否可以implements(实现)interface(接口)?
匿名的内部类是没有名字的内部cR不能extends(l承) 其它c,但一个内部类可以作ؓ(f)一个接口,由另一个内部类实现?/font>
W三QStatic Nested Class ?Inner Class的不同,说得多好(面试题有的很W统)?/p>
(tng)
Nested Class Q一般是C++的说法)(j)QInner Class (一般是JAVA的说?。Java内部cMC++嵌套cL大的不同在于是否有指向外部的引用上。具体可见http: //www.frontfree.net/articles/services/view.asp?id=704&page=1
注:(x) ?rn)态内部类QInner ClassQ意味着1创徏一个static内部cȝ对象Q不需要一个外部类对象Q?不能从一个static内部cȝ一个对象访问一个外部类对象
W四Q?amp;?amp;&的区别?br />q个问得很少?/p>
&是位q算W?amp;&是布?yu)(dng)逻辑q算W?br />
W五QHashMap和Hashtable的区别?br />帔R?/p>
都属于Map接口的类Q实C(jin)惟一键映到特定的g?
HashMap cL有分cL者排序。它允许一?null 键和多个 null 倹{?
Hashtable cM?HashMapQ但是不允许 null 键和 null 倹{它也比 HashMap 慢,因ؓ(f)它是同步的?br />
W六QCollection ?Collections的区别?br />你千万别说一个是单数一个是复数?/p>
Collections是个java.util下的c,它包含有各种有关集合操作的静(rn)态方法?
Collection是个java.util下的接口Q它是各U集合结构的父接口?
W七Q什么时候用assert?br />APIU的技术h员有可能?x)问q个?/p>
断言是一个包含布?yu)(dng)表辑ּ的语句,在执行这个语句时假定该表辑ּ?true。如果表辑ּ计算?falseQ那么系l会(x)报告一?AssertionError。它用于调试目的Q?
assert(a > 0); // throws an AssertionError if a <= 0
断言可以有两UŞ式:(x)
assert Expression1 ;
assert Expression1 : Expression2 ;
Expression1 应该L产生一个布?yu)(dng)倹{?
Expression2 可以是得Z个值的L表达式。这个值用于生成显C更多调试信息的 String 消息?
断言在默认情况下是禁用的。要在编译时启用断言Q需要?source 1.4 标记Q?
javac -source 1.4 Test.java
要在q行时启用断aQ可使用 -enableassertions 或?-ea 标记?
要在q行旉择用断言Q可使用 -da 或?-disableassertions 标记?
要系l类中启用断aQ可使用 -esa 或?-dsa 标记。还可以在包的基上启用或者禁用断a?
可以在预计正常情况下不会(x)到达的Q何位|上攄断言。断a可以用于验证传递给U有Ҏ(gu)的参数。不q,断言不应该用于验证传递给公有Ҏ(gu)的参敎ͼ因ؓ(f)不管是否启用?jin)断aQ公有方法都必须(g)查其参数。不q,既可以在公有Ҏ(gu)中,也可以在非公有方法中利用断言试后置条g。另外,断言不应该以M方式改变E序的状态?
W八QGC是什? Z么要有GC?
基础?br />
GC是垃圾收集器。Java E序员(sh)用担?j)内存管理,因?f)垃圾攉器会(x)自动q行理。要h垃圾攉Q可以调用下面的Ҏ(gu)之一Q?
System.gc()
Runtime.getRuntime().gc()
W九(ji)QString s = new String("xyz");创徏?jin)几个String Object?
问题太bt,偶不回答Q?br />
W十QMath.round(11.5){於多少? Math.round(-11.5){於多少?
Math.round(11.5)q回QlongQ?2QMath.round(-11.5)q回QlongQ?11;
W十一Qshort s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
面试题都是很变态的Q要做好受虐的准备?/p>
short s1 = 1; s1 = s1 + 1;有错Qs1是short型,s1+1是int?不能昑ּ转化为short型。可修改为s1 =(short)(s1 + 1) 。short s1 = 1; s1 += 1正确。?Q?br />
W十二,sleep() ?wait() 有什么区?
搞线E的最爱?/p>
sleep()Ҏ(gu)是ɾU程停止一D|间的Ҏ(gu)。在sleep 旉间隔期满后,U程不一定立x(chng)复执行。这是因为在那个时刻Q其它线E可能正在运行而且没有被调度ؓ(f)攑ּ执行Q除?a)“醒来”的U程h更高的优先
(b)正在q行的线E因为其它原因而阻塞?
wait()是线E交互时Q如果线E对一个同步对象x 发出一个wait()调用Q该U程?x)暂停执行,被调对象q入{待状态,直到被唤醒或{待旉到?
W十三,Java有没有goto?
很十三的问题Q如果哪个面试的问到q个问题Q我劝你q是别进q家公司?/p>
Goto—java中的保留字,现在没有在java中用?/font>
W十四,数组有没有length()q个Ҏ(gu)? String有没有length()q个Ҏ(gu)?
数组没有length()q个Ҏ(gu)Q有length的属性?
String有有length()q个Ҏ(gu)?
W十五,Overload和Override的区别。Overloaded的方法是否可以改变返回值的cd?
帔R?/p>
Ҏ(gu)的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父cM子类之间多态性的一U表玎ͼ重蝲Overloading是一个类中多态性的一U表现。如果在子类中定义某Ҏ(gu)与其父类有相同的名称和参敎ͼ我们说该Ҏ(gu)被重?(Overriding)。子cȝ对象使用q个Ҏ(gu)Ӟ调用子cM的定义,对它而言Q父cM的定义如同被“屏蔽”了(jin)。如果在一个类中定义了(jin)多个同名的方法,它们或有不同的参C数或有不同的参数cdQ则UCؓ(f)Ҏ(gu)的重?Overloading)。Overloaded的方法是可以改变q回值的cd?
W十六,Set里的元素是不能重复的Q那么用什么方法来区分重复与否? 是用==q是equals()? 它们有何区别?
Set里的元素是不能重复的Q那么用iterator()Ҏ(gu)来区分重复与否。equals()是判M个Set是否相等?
equals()?=Ҏ(gu)军_引用值是否指向同一对象equals()在类中被覆盖Qؓ(f)的是当两个分ȝ对象的内容和cd盔R的话Q返回真倹{?Q不知所云)(j)
W十七,l我一个你最常见到的runtime exception?br />如果你这个答不出来,面试的h?x)认Z没有实际~程l验?/p>
ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException, EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException,
ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFormatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException
W十八,error和exception有什么区?
error 表示恢复不是不可能但很困隄情况下的一U严重问题。比如说内存溢出。不可能指望E序能处理这L(fng)情况?
exception 表示一U设计或实现问题。也是_(d)它表C如果程序运行正常,从不?x)发生的情?/font>?br />
W十?ji),List, Set, Map是否l承自Collection接口?
ListQSet?
Map不是
W二十,abstract class和interface有什么区?
帔R?/p>
声明Ҏ(gu)的存在而不d现它的类被叫做抽象类Qabstract classQ,它用于要创徏一个体现某些基本行为的c,qؓ(f)该类声明Ҏ(gu)Q但不能在该cM实现该类的情c(din)不能创建abstract cȝ实例。然而可以创Z个变量,其类型是一个抽象类Qƈ让它指向具体子类的一个实例。不能有抽象构造函数或抽象?rn)态方法。Abstract cȝ子类为它们父cM的所有抽象方法提供实玎ͼ否则它们也是抽象cMؓ(f)。取而代之,在子cM实现该方法。知道其行ؓ(f)的其它类可以在类中实现这些方法?
接口QinterfaceQ是抽象cȝ变(sh)。在接口中,所有方法都是抽象的。多l承性可通过实现q样的接口而获得。接口中的所有方法都是抽象的Q没有一个有E序体。接口只可以定义static final成员变量。接口的实现与子cȝ|除了(jin)该实现类不能从接口定义中l承行ؓ(f)。当cd现特D接口时Q它定义Q即程序体l予Q所有这U接口的Ҏ(gu)。然后,它可以在实现?jin)该接口的类的Q何对象上调用接口的方法。由于有抽象c,它允怋用接口名作ؓ(f)引用变量的类型。通常的动态联~将生效。引用可以{换到接口cd或从接口cd转换Qinstanceof q算W可以用来决定某对象的类是否实现?jin)接口?/font>
W二十一Qabstract的method是否可同时是static,是否可同时是nativeQ是否可同时是synchronized?
不能
W二十二Q接口是否可l承接口? 抽象cL否可实现(implements)接口? 抽象cL否可l承实体c?concrete class)?
接口可以l承接口。抽象类可以实现(implements)接口Q抽象类是否可承实体类Q但前提是实体类必须有明的构造函数?
W二十三Q启动一个线E是用run()q是start()?
启动一个线E是调用start()Ҏ(gu)QɾU程所代表的虚拟处理机处于可运行状态,q意味着它可以由JVM调度q执行。这q不意味着U程׃(x)立即q行。run()Ҏ(gu)实执行的内容?/font>
W二十四Q构造器Constructor是否可被override?
构造器Constructor不能被承,因此不能重写OverridingQ但可以被重载Overloading?/font>
W二十五Q是否可以承Stringc?
W二十六Q当一个线E进入一个对象的一个synchronizedҎ(gu)后,其它U程是否可进入此对象的其它方?
W二十七Qtry {}里有一个return语句Q那么紧跟在q个try后的finally {}里的code?x)不会(x)被执行Q什么时候被执行Q在return前还是后?
W二十八Q编E题: 用最有效率的Ҏ(gu)出2乘(sh)8{於?
有C背景的程序员特别喜欢问这U问题?br />
W二十九(ji)Q两个对象值相?x.equals(y) == true)Q但却可有不同的hash codeQ这句话对不?
W三十,当一个对象被当作参数传递到一个方法后Q此Ҏ(gu)可改变这个对象的属性,q可q回变化后的l果Q那么这里到底是g递还是引用传?
W三十一Qswtich是否能作用在byte上,是否能作用在long上,是否能作用在String?
W三十二Q编E题: 写一个Singleton出来?br />