Java开发经验总结
论坛系统
统一用户Util.class。
publicUtil(){
try{
if(!LOG_FILES.equals(LOG_FILES_OLD)){
LOG_FILE=newFileOutputStream(LOG_FILES,true);
}
LOG_FILES_OLD=LOG_FILES;
LOG_FILE_AD=newFileOutputStream(LOG_FILES_AD,true);
}catch(Exceptione){
}
}
错误/不合理:
打开文件后没有关闭,结果会造成最后打开文件过多的错误。
此类为静态类,可以直接调用,不用生成类实例,所以此构造函数是不会被调用。
解决方法:
将try{}中内容放在一个静态块中static{},这样,在第一次使用此静态类是,系统将执行此静态块中的内容,此后就不会再执行了。这样系统将一直打开此日值文件,减少了打开关闭文件的开销。
SMSManager.class
try
{
DBConnectdbc=newDBConnect();
Stringsql="SelectCount(id)FrommessageWhereflag=0andissend=1anddelR=0Andincept=?";
dbc.prepareStatement(sql);
dbc.setBytes(1,userName.getBytes("GBK"));
ResultSetrs=dbc.executeQuery();
if(rs.next())
{
smsSign=true;
}
dbc.close();
}
catch(Exceptione){
e.printStackTrace();
}
错误/不合理:
放在try块中的语句过多,影响性能,应尽量减少try块中的语句数。如以下语句应放在try块外。
Stringsql="SelectCount(id)FrommessageWhereflag=0andissend=1anddelR=0Andincept=?";
在bjhy.jsp中,try块过大,更不应将html语句放在其中,这些语句在编译时都会作为try块内的一部分。
同样,synchronized块内的语句也不应过多,synchronized块中语句的执行速度要比没有synchronized慢的多。
常用的字符串应为静态变量,减少实例化String类的开销,应将
Stringsql=“….”改成privatestatocfinalCOUNT_SQL=“…”。
一下语句也应将UJBBUName设为静态常量。
GCookie.setCookie(response,"UJBBUName",userName,cookieDate);
数据库连接有可能不释放,如果dbc.prepareStatement(sql);报错,则dbc.close();将不会释放,应将释放资源的语句放在finally里。以下是标准数据库释放语句,其它释放资源语句类似。
publicsynchronizedvoidsaveToDb(){
Connectioncon=null;
PreparedStatementpstmt=null;
try{
con=ConnectionManager.getConnection();
pstmt=con.prepareStatement(SAVE);
pstmt.setString(1,name);
pstmt.setString(2,description);
pstmt.executeUpdate();
}
catch(SQLExceptionsqle){
sqle.printStackTrace();
}
finally{
try{pstmt.close();}
catch(Exceptione){e.printStackTrace();}
try{con.close();}
catch(Exceptione){e.printStackTrace();}
}
}
net.acai.forum.SkinUtil.GetTopList()
case7:
sql="selectusername,useremail,userclass,oicq,homePage,article,addDate,userwealthaswealth,userIDfromuserwhereindustry=''"+industry+"''orderbyAddDatedesc";
错误/不合理:
不要用如此写sql语句,此语句会因选出过大的结果集而使系统瘫痪。
解决方法:
应用各数据库对于分页的优化,商业数据库对此都有优化处理。如oracle可以在where语句中加上rowid>10androwid<30。
还可运用java.sql.Statement.setFetchSize(),和java.sql.Statement.setMaxRows()来控制返回的记录数。
如象mysql这样对此没有优化的数据库,最好运用缓存(如JCS)技术。每次select只选出记录的主键(id),如此可减少返回结果集的大小。再从库中将查出对应每个id的记录放入缓存中。下次用户访问就会从缓存中读取数据。
程序启动
java的堆是一个运行时数据区,类的实例(对象)从中分配空间。java虚拟机(jvm)的堆中储存着正在运行的应用程序所建立的所有对象。程序结束后这个堆会自动释放。这是java对内存的保护,Java中出现内存漏洞的情况会少得多–Xmx128Mmainclass
另外,启动程序时,可以通过-verbosegc参数来检测JVM垃圾回收情况,通过此可以确定程序需要占用的堆大小。
String类
String是使用用得最多的类,也是最容易占用系统资源类。以下是关于使用String的方法总结。
对于常量,一定要用privatestaticfinal
如非必要不要用Stringvriable=“”;来初始化一个String对象,直接String或Stringvariable=null即可。更不要用Stringvariable=newString(“”);。
多用StringBuffer,而不是String。StringBuffer构造对象的开销比String要小,而且对于字符串的处理比String要快的多。
不要向标准输出写无用数据
System.out.println();此语句在程序中随处可见,都是在调试时使用的,在程序正式运行时也没有将其去掉,结果就是日志中有大量的无用数据,不仅使得日值不易分析,也增加了系统的开销。如要记日志可用sun的java.util.logging包,或apache的log4j。
不要在循环中构造和释放对象
如net.acai.forum.ForumSearch第475行,语句如下:
do{
ForumTopictheTopic=newForumTopic();
theTopic.setLockTopic(rs.getInt(1));
theTopic.setForumID(rs.getInt(2));
theTopic.setRootID(rs.getInt(3));
theTopic.setAnnounceID(rs.getInt(4));
theTopic.setBody(rs.getString(5));
theTopic.setExpression(rs.getString(6));
theTopic.setTopic(rs.getString(7));
theTopic.setUserName(rs.getString(8));
theTopic.setChildNum(rs.getInt(9));
theTopic.setHits(rs.getInt(10));
theTopic.setDateAndTime(rs.getString(11));
searchResult.add(theTopic);
i++;
if(i==perPage){
break;
}
}
while(rs.next());}
代码中ForumTopictheTopic=newForumTopic();可以移到循环之外,这样ForumTopic只需实例化一次,减少了开销。为此,还需将searchResult.add(theTopic);改为searchResult.add(theTopic.clone());
其它经验
对象回收
对象只有在没有任何引用的情况下,在生命期结束后才能够被JVM所回收。当使用对象集合时应特别注意这点,应全面考虑对象在程序中被使用的状态,有时需要自己手动将对象回收(variable=null即可)。如AWT中,要删除一个组件对象,如按钮,除了要考虑从界面中删除他,还要考虑此组件是否被监听,如监听,则也要从监听器中删除。
大对象应及时回收,不要等到他的生命期结束后让系统回收,如果在他的生命期程序要运行很长时间,那么大对象将一直保存在内存中,知道生命期结束。
数据读写
数据读写一定要加缓存,不仅可以大幅度提高读写速度,而且可以保证数据的完整可靠。用BufferedWriter,BufferedReader,BufferedInputStream,BufferedoutputStream等,如以下代码:
DataInputStreamin=newDataInputStream(newBufferedInputStream(
newFileInputStream(fileName)));
DataOutpubStreamout=newDataOutpubStream(newBufferedOutputStream(newFileOutputStream(
fileName))));
尽量使用局部变量
调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快。其他变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢。另外,依赖于具体的编译器/JVM,局部变量还可能得到进一步优化。
不要重复初始化变量
默认情况下,调用类的构造函数时,Java会把变量初始化成确定的值:所有的对象被设置成null,整数变量(byte、short、int、long)设置成0,float和double变量设置成0.0,逻辑值设置成false。当一个类从另一个类派生时,这一点尤其应该注意,因为用new关键词创建一个对象时,构造函数链中的所有构造函数都会被自动调用。
向下转型的用法
ArrayList.next()
编程思想上的容器一章容器没有类型取出来后要强制转换到合适的类型
-大海(18322129)10:55:04
Tiger中有范型机制可以避免此类情况
枫(918147)10:55:55
object可以换成想到的类型,但你必须知道原来的传进来的object什么类型
比如你先传一个String,在方法中,在参数中定义object,在方法中,在传成string啊。
5
|
|