1 public class App { 2 3 Log log = LogFactory.getLog(App.class); 4 5 @Test 6 public void save() { 7 try { 8 log.info("保存: 开始进入保存方法"); 9 10 int i = 1/0;11 12 log.info("保存: 执行保存结束,成功");13 } catch (Exception e) {14 15 log.error("执行App类Save()方法出现异常!"); // 异常16 17 e.printStackTrace();18 }19 }20 21 /*22 * 思考: 日志的输出级别作用?23 * ----> 控制日志输出的内容。24 */25 @Test26 public void testLog() throws Exception {27 // 输出不同级别的提示28 log.debug("调试信息");29 log.info("信息提示");30 log.warn("警告");31 log.error("异常");32 33 }34 }35 public class Index extends HttpServlet {36 37 38 Log log = LogFactory.getLog(Index.class);39 40 public void doGet(HttpServletRequest request, HttpServletResponse response)41 throws ServletException, IOException {42 try {43 log.info("进入servlet");44 int i = 1/0;45 log.info("进入servlet结束");46 } catch (Exception e) {47 log.error("计算异常!",e);48 }49 }50 }
6、枚举完全讲解
6.1基本概念
l 为什么使用枚举类
n 一些方法在运行的过程中所需要的值不是任意的,而是在一个范围中。在jdk1.5出现之前解决的方案,就是自己实现一个带有枚举功能的类。
l Jdk1.5新增的enum关键字用于定义一个枚举类,一旦定义一个枚举类之后,这个枚举类及自动继承了,java类库中的Enum
自定义枚举类/** * 自己手动的创建一个 枚举类 * 1、私有化,private,隐藏构造方法不让别人使用 * 2、蒂尼几个public static final的实例,给外界使用 * * 手动实现的一个枚举类就是 Grade * 为Student类中定义一个,Grade,当为这个grade复制的时候,只能是Grade中定义好的几个public static final型的值,否则就会出现变异问题 * 一旦定义其他值就会出错,于是就达到了,枚举的作用,但是这样做还是比较麻烦的,于是,java中退出了一个枚举类 * @author YUCHEN * */class Grade{ private Grade(){ } public static final Grade A = new Grade(); public static final Grade B = new Grade(); public static final Grade C = new Grade(); public static final Grade D = new Grade(); public static final Grade E = new Grade();}class Student{ private Grade grade; //考试等级 public Grade getGrade() { return this.grade; } public void setGrade(Grade grade){ this.grade = grade; }}
6.2默认构造函数枚举
按下面步骤,读下面案例:
1 // 1. 枚举类定义 2 enum Grade{ 3 A,B,C,D,E; 4 } 5 class Student{ 6 private String name; 7 8 // 2. 使用枚举类型 9 private Grade grade; //ABCDE10 public Grade getGrade() {11 return grade;12 }13 public void setGrade(Grade grade) {14 this.grade = grade;15 }16 }17 public class Demo1 {18 public static void main(String[] args) {19 Student stu = new Student();20 // 3. 给枚举类型赋值,只能是枚举类定义的值(第1步中所定义)21 stu.setGrade(Grade.A);22 23 System.out.println(stu.getGrade());24 }25 }
1 // 运行时期异常 2 @Test 3 public void testGeneric() throws Exception { 4 // 集合的声明 5 List list = new ArrayList(); 6 list.add("China"); 7 list.add(1); 8 9 // 集合的使用10 String str = (String) list.get(1);11 12 }13 14 // 使用泛型15 @Test16 public void testGeneric2() throws Exception {17 // 声明泛型集合的时候指定元素的类型18 List list = new ArrayList ();19 list.add("China");20 // list.add(1);// 编译时期报错21 22 String str = list.get(1); 23 }
泛型擦除,泛型只在编译时期有效,编译后的字节码文件中不存在有泛型信息!
1 /*2 * 泛型擦除实例 3 4 public void save(List p){5 }6 public void save(List d){ // 报错: 与上面方法编译后一样7 }8 */
泛型的写法:
1 // 泛型写法 2 @Test 3 public void testGeneric3() throws Exception { 4 // 声明泛型集合,集合两端类型必须一致 5 List list = new ArrayList(); 6 List list1 = new ArrayList (); 7 List list2 = new ArrayList (); 8 List list3 = new ArrayList(); 9 10 // 错误11 //List list4 = new ArrayList ();12 // 错误: 泛型类型必须是引用类型,不能为基本类型13 List list5 = new ArrayList ();14 }
b. 泛型方法/泛型类/泛型接口
作用:
设计公用的类、方法,对公用的业务实现进行抽取!
使程序更灵活!
1. 泛型方法:
1 public class GenericDemo { 2 3 // 定义泛型方法 4 public T save(T t,K k) { 5 return null; 6 } 7 8 // 测试方法 9 @Test10 public void testMethod() throws Exception {11 // 使用泛型方法: 在使用泛型方法的时候,确定泛型类型12 save(1.0f, 1);13 }14 }
2. 泛型类:
1 public class GenericDemo { 2 3 // 定义泛型方法 4 public T save(T t,K k) { 5 return null; 6 } 7 8 public void update(T t) { 9 10 }11 12 // 测试方法13 @Test14 public void testMethod() throws Exception {15 16 // 泛型类: 在创建爱泛型类对象的时候,确定类型17 GenericDemo demo = new GenericDemo ();18 demo.save("test", 1);19 }20 }
3. 泛型接口:
1 /** 2 * 泛型接口 3 * @author Jie.Yuan 4 * 5 * @param 6 */ 7 public interface IBaseDao { 8 void save(T t ); 9 void update(T t );10 }11 12 =======================================13 泛型接口类型确定: 实现泛型接口的类也是抽象,那么类型在具体的实现中确定或创建泛型类的时候确定14 public class BaseDao implements IBaseDao {15 ======================================16 泛型=接口类型确定: 在业务实现类中直接确定接口的类型17 public class PersonDao implements IBaseDao {18 }
c. 泛型关键字
泛型中:
? 指定只是接收值
extends 元素的类型必须继承自指定的类
super 元素的类型必须是指定的类的父类
关键字: ?
1 /** 2 * 泛型, 涉及到一些关键字 3 * 4 * Ctrl + shift + R 查看当前项目中类 5 * Ctrl + shift + T 查看源码jar包中的类 6 * @author Jie.Yuan 7 * 8 */ 9 public class App_extends_super {10 11 //只带泛型特征的方法12 public void save(List list) {13 // 只能获取、迭代list; 不能编辑list14 }15 16 @Test17 public void testGeneric() throws Exception {18 19 // ? 可以接收任何泛型集合, 但是不能编辑集合值; 所以一般在方法参数中用20 List list = new ArrayList ();21 //list.add("");// 报错22 }23 }
关键字: extends 【上限】
1 public class App_extends_super { 2 3 4 /** 5 * list集合只能处理 Double/Float/Integer等类型 6 * 限定元素范围:元素的类型要继承自Number类 (上限) 7 * @param list 8 */ 9 public void save(List list) {10 }11 12 @Test13 public void testGeneric() throws Exception {14 List list_1 = new ArrayList ();15 List list_2 = new ArrayList ();16 List list_3 = new ArrayList ();17 18 List list_4 = new ArrayList ();19 20 // 调用21 save(list_1);22 save(list_2);23 save(list_3);24 //save(list_4);25 }26 }
关键字: super 【下限】
1 /** 2 * 泛型, 涉及到一些关键字 3 * 4 * Ctrl + shift + R 查看当前项目中类 5 * Ctrl + shift + T 查看源码jar包中的类 6 * @author Jie.Yuan 7 * 8 */ 9 public class App_super {10 11 12 /**13 * super限定元素范围:必须是String父类 【下限】14 * @param list15 */16 public void save(List list) {17 }18 19 @Test20 public void testGeneric() throws Exception {21 // 调用上面方法,必须传入String的父类22 List list1 = new ArrayList();23 List list2 = new ArrayList ();24 25 List list3 = new ArrayList ();26 //save(list3);27 }28 }
d. 泛型的反射
案例,设置通用方法,会用到反射泛型!下面有简单代码
步骤:
1. 案例分析 / 实现
2. 涉及知识点(jdk api)
3. 优化 / 反射泛型
反射泛型涉及API:
Student 类型的表示
Id name
参数化类型的表示
ArrayList<String>();
Type 接口,任何类型默认的接口!
包括:引用类型、原始类型、参数化类型
List<String> list = new ArrayList<String>();
泛型集合: list
集合元素定义:new ArrayList<String>(); 中的String
参数化类型:
即:“ArrayList<String> ” 为参数化类型
public class AdminDao extends BaseDao {}public class AccountDao extends BaseDao {}/** * 所有dao的公用的方法,都在这里实现 * @author Jie.Yuan * */public class BaseDao { // 保存当前运行类的参数化类型中的实际的类型 private Class clazz; // 表名 private String tableName; // 构造函数: 1. 获取当前运行类的参数化类型; 2. 获取参数化类型中实际类型的定义(class) public BaseDao(){ // this 表示当前运行类 (AccountDao/AdminDao) // this.getClass() 当前运行类的字节码(AccountDao.class/AdminDao.class) // this.getClass().getGenericSuperclass(); 当前运行类的父类,即为BaseDao // 其实就是“参数化类型”, ParameterizedType Type type = this.getClass().getGenericSuperclass(); // 强制转换为“参数化类型” 【BaseDao 】 ParameterizedType pt = (ParameterizedType) type; // 获取参数化类型中,实际类型的定义 【new Type[]{Account.class}】 Type types[] = pt.getActualTypeArguments(); // 获取数据的第一个元素:Accout.class clazz = (Class) types[0]; // 表名 (与类名一样,只要获取类名就可以) tableName = clazz.getSimpleName(); } /** * 主键查询 * @param id 主键值 * @return 返回封装后的对象 */ public T findById(int id){ /* * 1. 知道封装的对象的类型 * 2. 表名【表名与对象名称一样, 且主键都为id】 * * 即, * ---》得到当前运行类继承的父类 BaseDao * ----》 得到Account.class */ String sql = "select * from " + tableName + " where id=? "; try { return JdbcUtils.getQuerrRunner().query(sql, new BeanHandler (clazz), id); } catch (SQLException e) { throw new RuntimeException(e); } } /** * 查询全部 * @return */ public List getAll(){ String sql = "select * from " + tableName ; try { return JdbcUtils.getQuerrRunner().query(sql, new BeanListHandler (clazz)); } catch (SQLException e) { throw new RuntimeException(e); } }}
这里额外回顾反射,直接看代码:
1 public class Admin { 2 3 // Field 4 private int id = 1000; 5 private String name = "匿名"; 6 7 // Constructor 8 public Admin(){ 9 System.out.println("Admin.Admin()");10 }11 public Admin(String name){12 System.out.println("Admin.Admin()" + name);13 }14 15 // Method16 public int getId() {17 return id;18 }19 public void setId(int id) {20 this.id = id;21 }22 public String getName() {23 return name;24 }25 public void setName(String name) {26 this.name = name;27 }28 29 }30 31 32 // 反射技术33 public class App {34 35 // 1. 创建对象36 @Test37 public void testInfo() throws Exception {38 // 类全名39 String className = "cn.itcast.c_reflect.Admin";40 // 得到类字节码41 Class clazz = Class.forName(className);42 43 // 创建对象1: 默认构造函数简写44 //Admin admin = (Admin) clazz.newInstance();45 46 // 创建对象2: 通过带参数构造器创建对象47 Constructor constructor = clazz.getDeclaredConstructor(String.class);48 Admin admin = (Admin) constructor.newInstance("Jack");49 50 }51 @Test52 //2. 获取属性名称、值53 public void testField() throws Exception {54 55 // 类全名56 String className = "cn.itcast.c_reflect.Admin";57 // 得到类字节码58 Class clazz = Class.forName(className);59 // 对象60 Admin admin = (Admin) clazz.newInstance();61 62 // 获取所有的属性名称63 Field[] fs = clazz.getDeclaredFields();64 // 遍历:输出每一个属性名称、值65 for (Field f : fs) {66 // 设置强制访问67 f.setAccessible(true);68 // 名称69 String name = f.getName();70 // 值71 Object value = f.get(admin);72 73 System.out.println(name + value);74 }75 }76 77 @Test78 //3. 反射获取方法79 public void testMethod() throws Exception {80 81 // 类全名82 String className = "cn.itcast.c_reflect.Admin";83 // 得到类字节码84 Class clazz = Class.forName(className);85 // 对象86 Admin admin = (Admin) clazz.newInstance();87 88 // 获取方法对象 public int getId() { 89 Method m = clazz.getDeclaredMethod("getId");90 // 调用方法91 Object r_value = m.invoke(admin);92 93 System.out.println(r_value);94 }95 96 }
3. 注解
概述
注解与注释,
注解,告诉编译器如何运行程序!
注释,给程序员阅读,对编译、运行没有影响;
注解作用,
1. 告诉编译器如何运行程序;
2. 简化(取代)配置文件 【案例后再看】
常用的注解,
// 重写父类的方法 @Override public String toString() { return super.toString(); } // 抑制编译器警告 @SuppressWarnings({"unused","unchecked"}) private void save() { List list = null; } // 标记方法以及过时 @Deprecated private void save1() { }
1 public class App { 2 3 Log log = LogFactory.getLog(App.class); 4 5 @Test 6 public void save() { 7 try { 8 log.info("保存: 开始进入保存方法"); 9 10 int i = 1/0;11 12 log.info("保存: 执行保存结束,成功");13 } catch (Exception e) {14 15 log.error("执行App类Save()方法出现异常!"); // 异常16 17 e.printStackTrace();18 }19 }20 21 /*22 * 思考: 日志的输出级别作用?23 * ----> 控制日志输出的内容。24 */25 @Test26 public void testLog() throws Exception {27 // 输出不同级别的提示28 log.debug("调试信息");29 log.info("信息提示");30 log.warn("警告");31 log.error("异常");32 33 }34 }35 public class Index extends HttpServlet {36 37 38 Log log = LogFactory.getLog(Index.class);39 40 public void doGet(HttpServletRequest request, HttpServletResponse response)41 throws ServletException, IOException {42 try {43 log.info("进入servlet");44 int i = 1/0;45 log.info("进入servlet结束");46 } catch (Exception e) {47 log.error("计算异常!",e);48 }49 }50 }
6、枚举完全讲解
6.1基本概念
l 为什么使用枚举类
n 一些方法在运行的过程中所需要的值不是任意的,而是在一个范围中。在jdk1.5出现之前解决的方案,就是自己实现一个带有枚举功能的类。
l Jdk1.5新增的enum关键字用于定义一个枚举类,一旦定义一个枚举类之后,这个枚举类及自动继承了,java类库中的Enum
自定义枚举类/** * 自己手动的创建一个 枚举类 * 1、私有化,private,隐藏构造方法不让别人使用 * 2、蒂尼几个public static final的实例,给外界使用 * * 手动实现的一个枚举类就是 Grade * 为Student类中定义一个,Grade,当为这个grade复制的时候,只能是Grade中定义好的几个public static final型的值,否则就会出现变异问题 * 一旦定义其他值就会出错,于是就达到了,枚举的作用,但是这样做还是比较麻烦的,于是,java中退出了一个枚举类 * @author YUCHEN * */class Grade{ private Grade(){ } public static final Grade A = new Grade(); public static final Grade B = new Grade(); public static final Grade C = new Grade(); public static final Grade D = new Grade(); public static final Grade E = new Grade();}class Student{ private Grade grade; //考试等级 public Grade getGrade() { return this.grade; } public void setGrade(Grade grade){ this.grade = grade; }}
6.2默认构造函数枚举
按下面步骤,读下面案例:
1 // 1. 枚举类定义 2 enum Grade{ 3 A,B,C,D,E; 4 } 5 class Student{ 6 private String name; 7 8 // 2. 使用枚举类型 9 private Grade grade; //ABCDE10 public Grade getGrade() {11 return grade;12 }13 public void setGrade(Grade grade) {14 this.grade = grade;15 }16 }17 public class Demo1 {18 public static void main(String[] args) {19 Student stu = new Student();20 // 3. 给枚举类型赋值,只能是枚举类定义的值(第1步中所定义)21 stu.setGrade(Grade.A);22 23 System.out.println(stu.getGrade());24 }25 }