Java/Web
1、Map的get和containsKey方法。对于get,API中说“如果此映射包含满足 (key==null ? k==null : key.equals(k))
的键 k
到值 v
的映射关系,则此方法返回 v
;否则返回 null
。”实际上不止如此,还要比较hashCode。所以要实现以对象查对象,必须同时重写key类的equals和hashCode。containsKey也是如此,《Java编程思想》对此有详细解释,这里写的也很好http://blog.csdn.net/RichardSundusky/archive/2007/02/12/1508028.aspx。
2、Statement compensationSt = derbyConn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);这个大家都知道,意思是结果集可前后滚动,对修改不敏感,而且是一个可更新的结果集,即支持结果集的UPDATE/DELETE。但是如果Sql带有Order By子句,那么结果集就不再可更新了,即使用updateRow或deleteRow就会出错。
3、关于String:http://zangweiren.javaeye.com/blog/209895,http://topic.csdn.net/u/20081222/15/e77deb11-11a2-4a31-a478-f7331270230a.html
4、static块是在类装载时运行的,所以块里面即使有常量初始化赋值,也不能在编译期确定:2 final int B;
3 static {
4 B = 2;
5 }
6 int C = A; //编译期确定C的值,即此句等同于int C = 1;
7 int D = B; //虽然B为常量,但编译期尚不确定其值,所以不等同于int D = 2;
5、HttpSession持久化
http://blog.csdn.net/djsl6071/archive/2007/01/19/1487937.aspx文章中已经写得很明白了,要在server.xml中配置:
<Manager className="org.apache.catalina.session.PersistentManager" debug="0" saveOnRestart="true" maxActiveSessions="-1" minIdleSwap="-1" maxIdleSwap="-1" maxIdleBackup="-1" >
<Store className="org.apache.catalina.session.FileStore" directory="session"/>
</Manager>
</Context>
若是Eclipse WTP,默认保存地址大约在<Workspace>\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\work\Catalina\honstname\applicatonname\下。
这样Tomcat会把Session存储为文件,即使Tomcat关闭重启,服务器依然可以读取上次的Session,代码不需要什么更改,比如:
System.out.println(nickname);
if(nickname==null){
nickname = "kissrat";
session.setAttribute("nickname", nickname);
}
再次启动时就会自动读取以保存的Session。但是,持久化Session也是有限制条件的,比如只能存储已实现Serializable的对象:
private static final long serialVersionUID = 1448912554730655971L;
}
NewClass nc = (NewClass)session.getAttribute("nc");
if(nc==null){
System.out.println("若NewClass没有实现Serializable,则每次都会执行到这里。");
nc = new NewClass();
session.setAttribute("nc", nc);
}
当然,这个NewClass如果有其他对象成员,则所有成员对象的类都必须实现过Serializable。
6、必然导致的死锁(Guaranteed Deadlock)
2 static final Object lock1 = new Object(), o2 = new Object();
3
4 class Thread2 extends Thread{
5 public void run(){
6 synchronized(lock1){
7 lock1.notifyAll();
8 synchronized(o2){
9 }
10 }
11 }
12 }
13
14 class Thread1 extends Thread{
15 public void run(){
16 synchronized(lock1){
17 synchronized(o2){
18 Thread2 t2 = new Thread2();
19 t2.start();
20 try {
21 lock1.wait();
22 } catch (InterruptedException e) {
23 }
24 }
25 }
26 }
27 }
28
29 public void deadlock(){
30 Thread1 t1 = new Thread1();
31 t1.start();
32 }
33
34 public static void main(String[] args) {
35 new DeadLock().deadlock();
36 }
37
38}
如果用时序上的特殊调度来导致死锁是不能达到要求的,不能指望调度器来产生必然的死锁。比如:
2 static void noop(){}
3 private static Thread t;
4 public synchronized static void main(final String[] args) throws InterruptedException {
5 (t = new Thread() {
6 public synchronized void run() {
7 synchronized (DeadLock.class) {
8 }
9 }
10 }).start();
11 //noop(); //参考二:t一定先获得自身锁吗?
12 synchronized (t) {
13 t.wait(100); //参考一:看起来可靠,有本事不要这句
14 }
15 }
16}
参考精简版(http://www.jroller.com/skavish/entry/how_to_create_a_guaranteed):
2static final Object lock2 = new Object();
3
4public static void main( String[] args ) {
5 new Thread(new Runnable() {
6 public void run() {
7 synchronized(lock1) {
8 synchronized(lock2) {
9 new Thread(new Runnable() {
10 public void run() {
11 synchronized(lock1) {
12 lock1.notifyAll();
13 synchronized(lock2) {
14 System.out.println("never get here");
15 }
16 }
17 }
18 }).start();
19 try {
20 lock1.wait();
21 } catch( InterruptedException e ) {
22 }
23 }
24 }
25 }
26 }).start();
27}
2 private static Thread thread = null;
3 public static void main(final String[] args) throws Exception {
4 Runnable r = new Runnable() {
5 public synchronized void run() {
6 }
7 };
8 synchronized (r) {
9 (thread = new Thread(r)).start();
10 thread.join();
11 }
12 }
13}
7、强制类型转换赋值在编译期不会出错,但在运行时可能会抛出ClassCastException异常。
2
3 class Super{
4 }
5
6 public class Sub extends Super{
7 static Super getSub(){
8 return new Sub();
9 }
10
11 public static void main(String args[]){
12 Super sup= getSub();
13 Sub sub = new Sub();
14 sub = (Sub)sup;
15 }
16 }
若是把第8行改成return new Super();虽然编译能够通过,但运行时会出错。原因是sup对象可能不能被Cast到Sub类型。
8. finally有权覆盖try{}catch{}块中所有的Exception和return值:
2 try{
3 throw new RuntimeException();
4 } finally {
5 return 0;
6 }
7 }
由于被finally的return语句块覆盖,RuntimeException是不会被抛出的。
2 try{
3 return 1;
4 } finally {
5 return 0;
6 }
7 }
第3句的return会被finally覆盖,因此第5句return会执行,函数返回0;
2 int i = 1;
3 try{
4 return i;
5 } finally {
6 i = 0;
7 }
8 }
当然这次的返回值不会被finally改变,虽然finally一定会执行,但是reutrn语句的执行已经将返回值写入了栈中,再对变量i赋值已经没意义了,除非像上面一样再来一次return重新将i的值写回栈。
8. 编译时如果能确定变量未初始化就被使用,则会出现编译错误。
System.out.println(s); //Compile Error: The local variable s may not have been initialized
System.out.println(s); //输出为null
9. 处理简单的XML就用W3C DOM:字符串直接转为XML Document对象:
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(xml)));
...
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
参考:http://www.yesky.com/394/1757894_2.shtml,http://www.blogjava.net/hopeshared/archive/2006/07/06/56919.aspx
10. Base64编码, DES加解密参考:
http://yidinghe.cnblogs.com/articles/449212.html
http://blog.csdn.net/cmj198799/article/details/6866705
注意:如果发现同样的代码加密的结果却不同,请检查Java源文件的编码!
11. JSON的处理使用GSON,http://code.google.com/p/google-gson/
Json字符串格式为{...},不带变量名var json={...};