公司新进来了两位新同事,因而有必要对他们进行一下基础的培训,一来是要适应新的同事关系,二来也是对楼主一个不小的考验啊,专业的基础差不多全部还给老师了有木有。。。
不过好在不管在何种危难时刻,楼主总有力挽狂澜之势,查JDK API,看原码,一边解释与人一边自我复习,脸不红,心不跳,平稳过渡,总算没给咱丢了的面子。
讲到JDK5新特性,无非不外乎泛型,自动装箱自动拆箱,for增强循环,可变参数和枚举类型了。
- 泛型 泛型的引入在很大程度上加大了Java语法的复杂度,尤其对初学者是个挑战,它的主要优点是在编译期间能够捕捉类型不匹配的错误,原来的运行时异常变成了编译错误,因而防止了能够导致运行时异常的严重错误。一个例子:
上个例子中使用了泛型,规定了list中只能装载Person的实例,而一旦往里面加入String类型的元素则报错。ArrayList<Person> list = new ArrayList<Person>(); list.add(new Person("name","male",20)); //list.add("Person");//编译出错
除此之外,泛型还能用于代码的重用,特别是在分层结构的系统中。
看下面的例子:
BaseDAO Interface/** * @author Linbao.Lee@gmail.com * @time 2013年11月29日 * @param <T> * @ToDo */ public interface IBaseDao<T> { public abstract List<T> query(T t,Pager pager) throws Exception; public abstract T getById(int id) throws NonUniqueObjectException; }
定义一个基础服务公共实现类 BaseDaoHibernateImpl,提供基础的增删查改方法
(可根据不同框架定义不同的公共类如BaseDaoIbatisImpl)/** * @author Linbao.Lee@gmail.com * @time 2013年11月29日 * @version 2.0 * @param <T> * @ToDo */ public class BaseDaoHibernateImpl<T> { private SessionFactory sessionFactory; private Session session; /** * @param sessionFactory * @param session */ @SuppressWarnings("unchecked") private String getGClassName(){ ParameterizedType parameterizedType = (ParameterizedType) this.getClass().getGenericSuperclass(); Class<T> clazz = (Class<T>) parameterizedType.getActualTypeArguments()[0]; return clazz.getSimpleName().toString(); } @SuppressWarnings("unchecked") public List<T> query(T t, Pager pager) throws Exception{ int offest = 0; String sql = "from "+ getGClassName()+" "; offest = (pager.getCurrentPage()-1)<= 0 ? 0 : pager.getCurrentPage() * pager.getPageSize() ; Query query = this.getSession().createQuery(sql); query.setFirstResult(offest); query.setMaxResults(pager.getPageSize()); System.out.println("page size is "+pager.getPageSize()); System.out.println("offest is "+offest); System.out.println("Final SQL is : "+ sql); return query.list(); } @SuppressWarnings("unchecked") public T getById(int id) throws NonUniqueObjectException{ return (T) this.getSession() .createQuery("from "+ this.getGClassName()+" where id = ?") .setInteger(0, id).uniqueResult(); } }
根据业务Model定义自己的接口
User DaoInterface : IUserDao/** * @author Linbao.Lee@gmail.com * @time 2013年12月1日 * @version 2.0 * @param <T> * @ToDo */ public interface IUserDao extends IBaseDao<User>{//有自己新定义的方法同时拥有IBaseDao所有定义的方法 public abstract boolean isExist(String username) throws Exception; public abstract User countUser(String username,String password) throws Exception; }
自定义Dao的实现 UserDaoImpl
如此,当我们再需要定义新的Dao的,一些重复的工作比如增删查改都可以通过继承BaseDaoHibernateImpl 而得到其所有定义好的方法。这其中泛型的使用起到了一个关键的作用/** * @author Linbao.Lee@gmail.com * @time 2013年12月1日 * @version 2.0 * @param <T> * @ToDo */ public class UserDaoImpl extends BaseDaoHibernateImpl<User> implements IUserDao{//继承了BaseDaoHibernateImpl 同时也完成自己的业务需要IUserDao @Override public boolean isExist(String username) throws Exception { User user = null; user = (User) this.getSession().createCriteria(User.class) .add(Restrictions.eq("username", username)) .uniqueResult(); if(null != user) return true; else return false; } @Override public User countUser(String username, String password) throws Exception { User user = null; user = (User) this.getSession().createCriteria(User.class) .add(Restrictions.eq("username", username)) .add(Restrictions.eq("password", password)) .uniqueResult(); return user; } }
- 自动装箱自动拆箱
什么时候用到了装箱?
需要注意的是Integer类有一个缓存,它会缓存介于-128~127之间的整数。ArrayList<Integer> list = new ArrayList<Integer>();//由于int不是Object,所以不能new ArrayList<int>(); list.add(1);//自动装箱 --- 自动把int的类型转化成Integer list.add(new Integer(2));//手动创建Integer类型 for(int i=0;i<list.size();i++){ System.out.println(list.get(i)+2);//自动拆箱 --- 将Integer转化成int 运算完成后又自动装箱成Integer并调用其toString()方法输出 }
Integer num1 = new Integer(100); Integer unm2 = new Integer(100); System.out.println(num1 == num2); //输出true
(可自已动手去查看JDK java.lang.Integer 中的 valueOf()方法 )。Integer num1 = new Integer(200); Integer unm2 = new Integer(200); System.out.println(num1 == num2); //输出false
- for增强型循环
直接上代码List list = new ArrayList(); list.add("a"); list.add("b"); list.add("c"); //老式的for循环 for(int i=0;i<list.size();i++){ System.out.println(list.get(i)); } //增强型for循环 for(String str : list){ System.out.println(str); } //无法进行下标运算
- 可变参数列表
可变参数本质上就是一个数组,对于某个声明了可变参数的方法来说,我们既可以传递离散的值(实参),也可以传递一个数组对象。但如果方法中定义的参数为数组,那只能传递数组对象作为实参。
可变参数必须作为方法的参数列表的最后一个参数。即一个方法中不能同时定义两个或两个以上的可变参数。public int sum(int... nums){ int result = 0; for(int num : nums ){ result += num; } return result; }
- 枚举类型
这里列举几个枚举类型的例子
switch增加了对enum的支持,JDK5以后总共有五种类型可以放在switch语句中:byte,short,char,int,enumpublic enum Color { //定义 Red,Green,Blue } class TestColor{ public static void main(String[] args){ System.out.println(Color.Red);//所有的枚举类型都是public static final 的 } } //输出Red
高级一点的枚举类型的应用public enum Direction{ LEFT,RIGHT,BACK,AHEAD } class TestDirection{ public static void walk(enum dir){ switch (dir){ case dir.LEFT: System.out.println("turn left"); break; case dir.RIGHT: System.out.println("turn right"); break; case dir.BACK: System.out.println("back"); break; case dir.AHEAD: System.out.println("go ahead"); break; } } public static void main(String[] args){ walk(Direction.BACK); } }
每个枚举的成员其实就是你定义的枚举类型的一个实例(Instance),它们都被设为public static final的,本质上就是在定义一个类别,只不过很多细节编译器都帮你完成了。public enum WeekDay { Monday("星期一"),Tuesday("星期二"),Wednesday("星期三"),Thresday("星期四"),Friday("星期五"); private String value; WeekDay(String value) { this.value = value; } public String getValue(){ return value; } } class TestWeekDay{ public static void main(String[] args){ System.out.println(WeekDay.Friday.getValue()); } }//输出星期五