1、Question Person p1 = (Person) s2.get(Person.class, “402881e4345a53ce01345a543b9a0004“);System.out.println(“第一次查询“+p1); /查询获取一个新的对象s2.clear(); /将一级缓存中的数据清除boolean boo = /判断二级缓存中,是否存在此对象,为trueHibernateUtils.getSessionFactory().getCache().containsEntity(Person.class,“402881e4345a53ce01345a543b9a0004“);
2、System.out.println(“是否存在这个对象: “+boo);/truePerson p2 = (Person) s2.get(Person.class, “402881e4345a53ce01345a543b9a0004“);/read-writeg下为什么不查二级缓存System.out.println(“同一个session第二次查询“+p2);/使用同一个session查询,结果因为是 read-write,/因为对象已经上锁,所以不会从二级缓存中返回数据/s2.close(); /关闭或是不关闭System.out.println(“上一个Session关闭以后“);Se
3、ssion s3 = HibernateUtils.openSession();boo = HibernateUtils.getSessionFactory().getCache().containsEntity(Person.class,“402881e4345a53ce01345a543b9a0004“);System.out.println(“是否存在这个对象: “+boo);/truePerson p3 = (Person) s3.get(Person.class, “402881e4345a53ce01345a543b9a0004“);/read-write下,为什么这儿查二级缓存S
4、ystem.out.println(p3);s3.close();2、为什么 16 进制数要与 OxFF 与运算以下是 MD5 加密算法示例,其中使用了 OxFF 的与运算:Testpublic void md5() throws ExceptionString pwd = “1234“;MessageDigest md = MessageDigest.getInstance(“MD5“);byte bts = md.digest(pwd.getBytes();/16位pwd = “;for(byte bt : bts)System.err.println(“src: “+bt);String
5、 str = Integer.toHexString(bt);System.err.println(“src:-“ +str);str = Integer.toHexString(bt /为儿在算MD5时为什么与要0xff进行与运算呢System.err.println(“dest:“ +str);if(str.length():“+str);g2d.dispose();ImageIO.write(img, “JPEG“,resp.getOutputStream();4、MySQL 区分大小写的查询mysql 查询默认是不区分大小写的 如:select * from table_name wh
6、ere a like a% select * from table_name where a like A% select * from table_name where a like a%select * from table_name where a like A%效果是一样的。 要让 mysql 查询区分大小写,可以:select * from table_name where binary a like a% select * from table_name where binary a like A% select * from table_name where binary a l
7、ike a%select * from table_name where binary a like A%也可以在建表时,加以标识 create table table_name(a varchar(20) binary5、在 Hibernate 的区分大小写的查询首先,必须要创建数据库时,指字某个列为区别大小写:CREATE TABLE person(id VARCHAR(32) PRIMARY KEY,NAME VARCHAR(30) BINARY /此列使用了 binary,是指区别大小写的查询);然后在 Hibernate 中:String hql = “from Person whe
8、re lower(name)=jjj“; /注意这儿使用的lower关键字List list = sess.createQuery(hql).list()System.err.println(list);list = sess.createCriteria(Person.class).add(Restrictions.eq(“name“, “jjj“).ignoreCase().list(); /注意这儿使用了ignoreCase方法。System.err.println(“:“+list);6、MySql 执行存储过程时错误的处理方式创建一个简单的存储过程:DELIMITER $CREATE
9、 PROCEDURE proc_book()BEGINSELECT * FROM book;END $DELIMITER ;调用这个存储过程:CALL proc_book();有可能会出现以下错误代码:ERROR 1436 (HY000): Thread stack overrun修改方式如下:修改My.ini 中的配置thread_stack = 256K 原来是 128K,将内存修改成 256K 即可。7、反射判断一个方法拥有什么参数设置不同的值package cn.itcast.loader2;/* 被反射类* author 王健* version 1.0 2012-3-7*/publi
10、c class Hello /假设以下方法有什么参数都不明确public void sayHi(String aa,Integer age,int mm)System.err.println(“Hello:“+aa+“,“+age+“,“+mm);调用类如下:package cn.itcast.loader2;import java.lang.reflect.Method;/* 判断有什么类型的参数,设置不同的值* author 王健* version 1.0 2012-3-7*/public class ParamDemo public static void main(String arg
11、s) throws Exception Class cls = Hello.class;Method ms = cls.getDeclaredMethods();for(Method m:ms)if(m.getName().equals(“sayHi“)Class clses = m.getParameterTypes();Object oo = new Objectclses.length;for(int i=0;i。其中可以定义 N 多个它的子类。返回的数据:由用户自己定义,或是系统已经定义。1、简单回调函数package cn.itcast.test;/* 回调函数的简单写法* auth
12、or 王健* version 2012-1-11*/public class TT public static void main(String args) One a = new One();a.abc(“Hello“,new A() /这是没有返回值的回调函数public void abc(String ss) System.err.println(“SSS:“+ss););class One /定义一个调用类public void abc(String sql,A a)a.abc(sql);interface A /定义规范public void abc(String ss);2、拥有任
13、意返回值的回调函数1、以下是返回一个值的回调函数:package cn.itcast.test;/* 返回指定的泛型的回调函数* author 王健* version 2012-1-11*/public class CallBack public static void main(String args) B b = new B();String str = b.getO(new IB()public String getObject()return “ddd“;);System.err.println(str);class B /声明一个类,此方法返回一个普通的值public T getO(
14、IB b)/声明方法同时接收一个回调函数,注意泛型的使用return b.getObject();interface IB /将泛型定义到类上,直接在类上声明泛型,这样在声明时就可以设置泛型了public T getObject();2、以下是返回 List类型的回调函数 :package cn.itcast.test;import java.util.ArrayList;import java.util.List;/* 返回 list类型的回调函数* author 王健* version 2012-1-11*/public class CallBack2 public static void
15、 main(String args) C c = new C(); /以下是测试代码List list = c.getObjs(new IC()public String getObject(int row) return “Hello“+row;);System.err.println(“:“+list);class C /定义被调用的类public List getObjs(IC ic) /在类上定义泛型多处使用List list = new ArrayList(); /里面声明一个List并多次调用回调函数的方法for(int i=0;i /定义回调规范public T getObjec
16、t(int row);9、线程池 ExecutorService 的 submit 和 execute在 Java5 之后,并发线程这块发生了根本的变化,最重要的莫过于新的启动、调度、管理线程的一大堆 API 了。在 Java5 以后,通过 Executor 来启动线程比用 Thread 的 start()更好。在新特征中,可以很容易控制线程的启动、执行和关闭过程,还可以很容易使用线程池的特 性。一、创建任务任务就是一个实现了 Runnable 接口的类。创建的时候实 run 方法即可。二、执行任务通过 java.util.concurrent.ExecutorService 接口对象来执行任
17、务,该接口对象通过工具类 java.util.concurrent.Executors 的静态方法来创建。Executors 此包中所定义的 Executor、ExecutorService 、ScheduledExecutorService 、ThreadFactory 和 Callable 类的工厂和实用方法。ExecutorService 提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。 可以关闭 ExecutorService,这将导致其停止接受新任务。关闭后,执行程序将最后终止,这时没有任务在执行,也没有任务在等待执行,并且无法提交新任 务。
18、executorService.execute(new TestRunnable();1、创建 ExecutorService通过工具类 java.util.concurrent.Executors 的静态方法来创建。Executors 此包中所定义的 Executor、ExecutorService 、ScheduledExecutorService 、ThreadFactory 和 Callable 类的工厂和实用方法。比如,创建一个 ExecutorService 的实例,ExecutorService 实际上是一个线程池的管理工具:ExecutorService executorSer
19、vice = Executors.newCachedThreadPool();ExecutorService executorService = Executors.newFixedThreadPool(3);ExecutorService executorService = Executors.newSingleThreadExecutor();2、将任务添加到线程去执行当将一个任务添加到线程池中的时候,线程池会为每个任务创建一个线程,该线程会在之后的某个时刻自动执行。示例 1:Testpublic void testDemo() throws Exception /单例线程,任意时间(同一
20、时间) 池中只能有一个线程ExecutorService es = Executors.newSingleThreadExecutor();es.execute(new Runnable() Overridepublic void run() System.err.println(“线程启动并运行 “+Thread.currentThread().getName(););es.execute(new Runnable() Overridepublic void run() System.err.println(“第二个也运行了 “+Thread.currentThread().getName(
21、););/Thread.sleep(1000 * 60 * 60);运行结果如下:两个都会执行,但程序只会使用一个线程来运行。线程启动并运行pool-1-thread-1第二个也运行了 pool-1-thread-1示例:Testpublic void testDemo3() throws Exception /声明一个线程池ExecutorService ex = Executors.newCachedThreadPool();for (int i = 0; i “+Thread.currentThread().getName()+“,“+Thread.currentThread().isD
22、aemon();tryThread.sleep(2000);catch(Exception e)e.printStackTrace(););Thread.sleep(1000*60*60);输出的结果如下:从中可以发现,第四个一组输出,即一共创建了四个线程,每次每个线程都会执行输出,但不按顺序:位每一次输出都四个算是一组测试0pool-1-thread-1,false测试3pool-1-thread-4,false测试2pool-1-thread-3,false测试1pool-1-thread-2,false测试0pool-1-thread-1,false测试3pool-1-thread-4,
23、false测试2pool-1-thread-3,false测试1pool-1-thread-2,false测试1pool-1-thread-2,false测试2pool-1-thread-3,false测试3pool-1-thread-4,false测试0pool-1-thread-1,false示例:public void testCall() throws Exception/声明一个类,可以被调用,类似于线程,但它可以拥有返回值class MyCall implements Callableprivate int seq;public MyCall(int seq)this.seq=se
24、q;/抛出异常并可以拥有返回值public String call() throws Exception System.err.println(“执行“+seq+“,“+Thread.currentThread().getName();Thread.sleep(3000);System.err.println(“Weak up “+seq);return “完成“+seq; /这是返回值ExecutorService es = Executors.newCachedThreadPool();/创建线程池对象List result = new ArrayList();/放结果用的集合for(in
25、t i=0;i f=es.submit(new MyCall(i);/线程执行完成以后可以通过引用获取返回值result.add(f);for(Future f:result)System.err.println(“返回值:“+f.get();/ 输出返回的值System.err.println(“完成“ );10、JDK 的动态代理为什么必须要使用接口JDK 的代理 Proxy 必须要使用接口,才可以实现对方法的拦截。为什么呢?先让我们看一个 JDK 动态代理的示例:接口类:public interface IPerson public void sayHi(String nm);接口实现类
26、:public class Person implements IPersonpublic Person()private String name;public Person(String name)this.name=name;public void sayHi(String str)System.err.println(name+“ Hello :“+str);使用 JDK 代理 Person 类的方法:Testpublic void testJdkProxy() throws Exceptionfinal Dog dog = new Dog();/以下必须返回接口,因为Proxy内部,会
27、根据接口创建一个 IAnimal的子类,/创建的这个子类是Dog类的兄弟关系。子类可以转换成父类,但对于平行的两个转换将失败,/这就是为什么必须要使用接口的原因IAnimal dog2 = (IAnimal)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),dog.getClass().getInterfaces(),new InvocationHandler() public Object invoke(Object proxy, Method method, Object args)throws Throwable Syst
28、em.err.println(“Before.“);Object o = method.invoke(dog, args);return o;);dog2.eat();boolean boo = Proxy.isProxyClass(dog2.getClass();System.err.println(“是否是被代理对象:“+boo+“,“+dog2.getClass();代码说明:Proxy 返回的对象必须要强转为 Ianimal 的类型。如果要转成 Dog 类型则会抛出 ClassCastException。Proxy 代理可以使用以下简图加以说明:创建一个子类实现接口2 调用用户的实现类
29、IPerson 接口Person 实现类Proxy 代理容器$Proxy$实现 IPerson 接口InvocationHandlerinvoke 方法上图中,最关键,也是最重要的部分就是 Proxy 在接收到 Person 类的实例以后,创建了 IPerson 类的一个子类取名为$Proxy$,此时$Proxy$类与 Person类为同级兄弟关系。所以如果使用以下代码将会抛出 ClassCastException:Person person = (Person)Proxy.newInstance();但使用接口就不会出现异常,即:IPerson peson = (IPerson)Proxy.
30、newInstance();、为了更加清楚为什么会抛出转换异常,我再做如下测试:声明一个 IAnimal 接口类:public interface IAnimal public void eat();实现 IAnimal 接口的 Dog 类:public class Dog implements IAnimal private String food;public Dog(String food)this.food=food;public void eat() System.err.println(“小狗吃:“ +food);实现 IAnimal 接口的 Cat 类:public class
31、Cat implements IAnimal private String food;public Cat(String food)this.food=food;IAnimal 接口Dog 实现类 Cat 实现类public void eat() System.err.println(“小猫吃:“ +food);测试是否可以将 Dog 类的实例转换成 Cat,转换时,将会抛出 ClassCastException:IAnimal dog = new Dog(“骨头“);IAnimal cat = new Cat(“小鱼“);Dog dog2 = (Dog) cat;/cat 与 dog 是兄弟
32、关系不能转换成功,抛出 ClassCastExceptiondog = cat; /此时将转换成功,因为 dog 是 IAnimal 类型,可以指向自己的子类2、然后再测试使用反射IAnimal dog = new Dog(“骨头“);IAnimal cat = new Cat(“小鱼“);boolean boo = dog.getClass()=cat.getClass();System.err.println(boo);Method m = dog.getClass().getMethod(“eat“);/从dog中获取m.invoke(cat);/不成功,说明反射从哪儿获取方法,就应该调
33、用谁的实例/但如果是从最高接口中获取到的方法,则可以执行,如下:Method m2 = IAnimal.class.getMethod(“eat“);m2.invoke(dog);/执行成功System.err.println(“-“);m.invoke(cat);/执行成功上例中:Method m = dog.getClass.getMethod(“eat”);m.invoke(dog);只可以执行 dog 的方法,如果填入 cat 则会执行不成功。因为 Dog 类拥有自己的字节码。而如果修改成:Method m = IAnimal.class.getMethod(“eat”);m.invo
34、ke(dog);m.invoke(cat);/两个调用都可以执行成功因为, Dog 和 Cat 拥有相同的父类接口,而 IAnimal 字节码只有一份。11、使用 CGLIB 动态代理Cglib 是一个优秀的动态代理框架,它的底层使用 ASM 在内存中动态的生成被代理类的子类。使用 CGLIB 即使被代理类没有实现任何接口也可以实现动态代理功能。CGLIB 具有简单易用,它的运行速度要远远快于 JDK 的 Proxy 动态代理:使用 CGLIB 需要导入以下两个 jar 文件:asm.jar CGLIB 的底层实现。cglib.jar CGLIB 的核心 jar 包。CGLIB 的核心类:ne
35、t.sf.cglib.proxy.Enhancer 主要的增强类net.sf.cglib.proxy.MethodInterceptor 主要的方法拦截类,它是 Callback 接口的子接口,需要用户实现net.sf.cglib.proxy.MethodProxy JDK 的 java.lang.reflect.Method 类的代理类,可以方便的实现对源对象方法的调用, 如使用:Object o = methodProxy.invokeSuper(proxy, args);/虽然第一个参数是被代理对象,也不会出现死循环的问题。费话少说,上代码:1、使用 CGLIB 的代理:以下测试代理一个
36、没有实现任何接口的 Person 类:Testpublic void testProxy1() throws Exception final Person p1 = new Person(); /Person类没有实现任何接口Enhancer en = new Enhancer(); /声明增加类实例en.setSuperclass(Person.class); /设置被代理类字节码,CGLIB 根据字节码生成被代理类的子类en.setCallback(new MethodInterceptor() / 设置回调函数,即一个方法拦截public Object intercept(Object
37、target, Method method,Object args, MethodProxy proxy) throws Throwable Object o = method.invoke(p1,args); /注意参数p1,仍然为外部声明的源对象,且Method为JDK的Method 反射System.err.println(“After.“);return o;);Person p = (Person) en.create(); /通过create 方法返回Person类的代理System.err.println(p.getClass();/被代理的对象p.sayHi(“Hello“);
38、2、以下测试代理一个拥有接口的类:IAnimal 是接口,Dog 是实现类,具体代码如下:Testpublic void testProxy2() throws Exception final Dog dog = new Dog(); /声明被代理对象Enhancer en = new Enhancer(); /声明CGLIB 增强类en.setSuperclass(IAnimal.class); /设置接口类,也可以设置成dog实现类,会影响create返回的对象en.setCallback(new MethodInterceptor() public Object intercept(Ob
39、ject target, Method method,Object args, MethodProxy proxy) throws Throwable System.err.println(“Before.“);Object o = method.invoke(dog, args);System.err.println(“After.“);return o;);/Dog dog2 = (Dog) en.create();/必须转型为接口 ,否则抛出ClassCastExceptionIAnimal dog2 = (IAnimal)en.create();dog2.eat();说明:由于上例中,
40、设置了 en.setSuperclass(IAnimal.class),所以 en.create()方法,返回的对象,必须要转换成 IAnimal 接口。如果转换成 Dog 则会抛出ClassCastException。3、将 CGLIB 再做一个简单的包装:class CglibProxy implements MethodInterceptorprivate Object srcTarget;private CglibProxy(Object o)this.srcTarget = o;SuppressWarnings(“unchecked“)public static T proxyTar
41、get(T t)Enhancer en = new Enhancer();en.setSuperclass(t.getClass();en.setCallback(new CglibProxy(t);T tt = (T) en.create();return tt;Overridepublic Object intercept(Object obj, Method method, Object args,MethodProxy proxy) throws Throwable System.err.println(“拦截前.“);Object o = method.invoke(srcTarge
42、t, args);System.err.println(“拦截后“ );return o;包装以后的调用代码如下,主要是快速的实现获取被代理类:Person p = CglibProxy.proxyTarget(new Person();p.sayHi(“HJello“);IAnimal dog = CglibProxy.proxyTarget(new Dog();dog.eat();4、使用静态方法代理一个没有接口的对象以下代码,包含在一个测试方法或是 main 方法中运行:final Person src = new Person();/直接使用静态方法代理一个对象Person p = (
43、Person) Enhancer.create(Person.class,new MethodInterceptor()public Object intercept(Object proxyedObj, Method method, Object args,MethodProxy proxy) throws Throwable System.err.println(“Hello“);/使用原生的方法调用,注意里面的src/Object oo = method.invoke(src, args);/使用MethodProxy调用父类的代码,同样有效Object oo = proxy.invok
44、eSuper(proxyedObj, args);return oo;);System.err.println(p.getClass();p.abc();12、深入 ThreadLocal 的内部机制早在 JDK 1.2 的版本中就提供 java.lang.ThreadLocal,ThreadLocal 为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。ThreadLocal 并不是一个 Thread,而是 Thread 的局部变量。当使用 ThreadLocal 维护变量时,ThreadLocal 为每个使用该变量的线程提供独立的变量副本。Thr
45、eadLocal 的接口方法:void set(Object value):设置当前线程的线程局部变量的值。public Object get():该方法返回当前线程所对应的线程局部变量。public void remove():将当前线程局部变量的值删除,目的是为了减少内存的占用,该方法是 JDK 5.0 新增的方法。需要指出的是,当线程结束后,对应该线程的局部变量将自动被垃圾回收,所以显式调用该方法清除线程的局部变量并不是必须的操作,但它可以加快内存回收的速度。protected Object initialValue():返回该线程局部变量的初始值,该方法是一个 protected 的方
46、法,显然是为了让子类覆盖而设计的。这个方法是一个延迟调用方法,在线程第 1 次调用 get()或 set(Object)时才执行,并且仅执行 1 次。ThreadLocal 中的缺省实现直接返回一个 null。在 JDK5.0 中,ThreadLocal 已经支持泛型,该类的类名已经变为 ThreadLocal。ThreadLocal 是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单:在 ThreadLocal 类中有一个 Map,用于存储每一个线程的变量副本模拟 ThreadLocal 代码清单:package cn.itcast.ref;import java.util.Co
47、llections;import java.util.HashMap;import java.util.Map;import java.util.Random;public class MyThreadLocal /使用同步的map维护对象private static Map map = Collections.synchronizedMap(new HashMap(); public static Object get()/获取当前线程Thread currentThread = Thread.currentThread();Object o = map.get(currentThread)
48、;if(o=null)o = new Random().nextInt(100);/假设是一个随机数map.put(currentThread, o);return o;public static void remove()Thread currentThread = Thread.currentThread();if(map.containsKey(currentThread)map.remove(currentThread);虽然这个ThreadLocal实现版本显得比较幼稚,但它和JDK所提供的ThreadLocal 类在实现思路上是相近的。测试代码清单:Testpublic void testMyThreadLocal()Object o1 = MyThreadLocal.get();Object o2 = MyThreadLocal.get();/以下因为是同一个线程所有值相同System.err.println(o1+“,“+o2);new Thread()public void run() /在新的线程中获取对象为不同的值Object o3 = MyThreadLocal.get();System.err.println(“o3:“+o3);