java基础增强(泛型,反射, 注解,日志)

来源:互联网 发布:自学python 编辑:程序博客网 时间:2024/05/21 18:46

泛型

作用:异常提前到编译期

    // 运行时期异常     @Test    public void testGeneric() throws Exception {        // 集合的声明        List list = new ArrayList();        list.add("China");        list.add(1);        // 集合的使用        String str = (String) list.get(1);    }    // 使用泛型    @Test    public void testGeneric2() throws Exception {        // 声明泛型集合的时候指定元素的类型        List<String> list = new ArrayList<String>();        list.add("China");//      list.add(1);// 编译时期报错        String str = list.get(1);     }

泛型擦除,

泛型只在编译时期有效,编译后的字节码文件中不存在有泛型信息!
    public void save(List<Person> p){    }    public void save(List<Dept> d){    // 报错: 与上面方法编译后一样    }

写法

// 泛型写法    @Test    public void testGeneric3() throws Exception {        // 声明泛型集合,集合两端类型必须一致        List<Object> list = new ArrayList<Object>();        List<String> list1 = new ArrayList<String>();        List list2 = new ArrayList<String>();        List<Integer> list3 = new ArrayList();        // 错误        //List<Object> list4 = new ArrayList<String>();        // 错误: 泛型类型必须是引用类型,不能为基本类型        List<int> list5 = new ArrayList<int>();    }

泛型类

public class GenericDemo<T> {    // 定义泛型方法    public <K> T save(T t,K k) {        return null;    }    public void update(T t) {    }    // 测试方法    @Test    public void testMethod() throws Exception {        // 泛型类:  在创建爱泛型类对象的时候,确定类型        GenericDemo<String> demo = new GenericDemo<String>();        demo.save("test", 1);    }}

泛型方法

public class GenericDemo {    // 定义泛型方法    public <K,T> T save(T t,K k) {        return null;    }    // 测试方法    @Test    public void testMethod() throws Exception {        // 使用泛型方法:  在使用泛型方法的时候,确定泛型类型        save(1.0f, 1);    }}

泛型接口

/** * 泛型接口 * @author Jie.Yuan * * @param <T> */public interface IBaseDao<T> {    void save(T t );    void update(T t );}//泛型接口类型确定: 实现泛型接口的类也是抽象,那么类型在具体的实现中确定或创建泛型类的时候确定public class BaseDao<T> implements IBaseDao<T> {//泛型接口类型确定: 在业务实现类中直接确定接口的类型public class PersonDao implements IBaseDao<Person>{

泛型关键字

泛型中:
? 指定只是接收值
extends 元素的类型必须继承自指定的类
super 元素的类型必须是指定的类的父类

/** *? * 泛型, 涉及到一些关键字 *  * Ctrl + shift + R   查看当前项目中类 * Ctrl + shift + T   查看源码jar包中的类 * @author Jie.Yuan * */public class App_extends_super {    //只带泛型特征的方法    public void save(List<?> list) {        // 只能获取、迭代list;  不能编辑list    }    @Test    public void testGeneric() throws Exception {        // ?  可以接收任何泛型集合, 但是不能编辑集合值; 所以一般在方法参数中用        List<?> list = new ArrayList<String>();        //list.add("");// 报错    }}
public class App_extends_super {    /**     * extends     * list集合只能处理 Double/Float/Integer等类型     * 限定元素范围:元素的类型要继承自Number类  (上限)     * @param list     */    public void save(List<? extends Number> list) {    }    @Test    public void testGeneric() throws Exception {        List<Double> list_1 = new ArrayList<Double>();        List<Float> list_2 = new ArrayList<Float>();        List<Integer> list_3 = new ArrayList<Integer>();        List<String> list_4 = new ArrayList<String>();        // 调用        save(list_1);        save(list_2);        save(list_3);        //save(list_4);    }}
/** * super * 泛型, 涉及到一些关键字 *  * Ctrl + shift + R   查看当前项目中类 * Ctrl + shift + T   查看源码jar包中的类 * @author Jie.Yuan * */public class App_super {    /**     * super限定元素范围:必须是String父类   【下限】     * @param list     */    public void save(List<? super String> list) {    }    @Test    public void testGeneric() throws Exception {        // 调用上面方法,必须传入String的父类        List<Object> list1 = new ArrayList<Object>();        List<String> list2 = new ArrayList<String>();        List<Integer> list3 = new ArrayList<Integer>();        //save(list3);    }}

泛型反射的应用

Type 接口:
任何类型默认的接口!
包括: 引用类型、原始类型、参数化类型

参数化类型: ParameterizedType
如:“ArrayList ” 为参数化类型

public class AdminDao extends BaseDao<Admin> {}public class AccountDao extends BaseDao<Account> {}/** * 所有dao的公用的方法,都在这里实现 * @author Jie.Yuan * */public class BaseDao<T>{    // 保存当前运行类的参数化类型中的实际的类型    private Class clazz;    // 表名    private String tableName;    // 构造函数: 1. 获取当前运行类的参数化类型; 2. 获取参数化类型中实际类型的定义(class)    public BaseDao(){        //  this  表示当前运行类  (AccountDao/AdminDao)        //  this.getClass()  当前运行类的字节码(AccountDao.class/AdminDao.class)        //  this.getClass().getGenericSuperclass();  当前运行类的父类,即为BaseDao<Account>        //  其实就是“参数化类型”, ParameterizedType           Type type = this.getClass().getGenericSuperclass();        // 强制转换为“参数化类型”  【BaseDao<Account>】        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>         *   ----》 得到Account.class         */        String sql = "select * from " + tableName + " where id=? ";        try {            return JdbcUtils.getQuerrRunner().query(sql, new BeanHandler<T>(clazz), id);        } catch (SQLException e) {            throw new RuntimeException(e);        }    }       /**     * 查询全部     * @return     */    public List<T> getAll(){        String sql = "select * from " + tableName ;        try {            return JdbcUtils.getQuerrRunner().query(sql, new BeanListHandler<T>(clazz));        } catch (SQLException e) {            throw new RuntimeException(e);        }    }}

反射

public class Admin {    // Field    private int id = 1000;    private String name = "匿名";    // Constructor    public Admin(){        System.out.println("Admin.Admin()");    }    public Admin(String name){        System.out.println("Admin.Admin()" + name);    }    // Method    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}// 反射技术public class App {    // 1. 创建对象    @Test    public void testInfo() throws Exception {        // 类全名        String className = "cn.itcast.c_reflect.Admin";        // 得到类字节码        Class<?> clazz = Class.forName(className);        // 创建对象1: 默认构造函数简写        //Admin admin = (Admin) clazz.newInstance();        // 创建对象2: 通过带参数构造器创建对象        Constructor<?> constructor = clazz.getDeclaredConstructor(String.class);        Admin admin = (Admin) constructor.newInstance("Jack");    }    @Test    //2. 获取属性名称、值    public void testField() throws Exception {        // 类全名        String className = "cn.itcast.c_reflect.Admin";        // 得到类字节码        Class<?> clazz = Class.forName(className);        // 对象        Admin admin =  (Admin) clazz.newInstance();        // 获取所有的属性名称        Field[]  fs =  clazz.getDeclaredFields();        // 遍历:输出每一个属性名称、值        for (Field f : fs) {            // 设置强制访问            f.setAccessible(true);            // 名称            String name = f.getName();            // 值            Object value = f.get(admin);            System.out.println(name + value);        }    }    @Test    //3. 反射获取方法    public void testMethod() throws Exception {        // 类全名        String className = "cn.itcast.c_reflect.Admin";        // 得到类字节码        Class<?> clazz = Class.forName(className);        // 对象        Admin admin =  (Admin) clazz.newInstance();        // 获取方法对象    public int getId() {        Method m = clazz.getDeclaredMethod("getId");        // 调用方法        Object r_value = m.invoke(admin);        System.out.println(r_value);    }}

注解

注解与注释,
注解,告诉编译器如何运行程序!
注释, 给程序员阅读,对编译、运行没有影响;

注解作用,
1. 告诉编译器如何运行程序;
2. 简化(取代)配置文件 【案例后再看】

常用注解

// 重写父类的方法    @Override    public String toString() {        return super.toString();    }    // 抑制编译器警告    @SuppressWarnings({"unused","unchecked"})    private void save() {        List list = null;    }    // 标记方法以及过时    @Deprecated    private void save1() {    }

自定义注解

通过自定义注解,可以给类、字段、方法上添加描述信息!
基本写法:

/** * 自定义注解  (描述一个作者) * @author Jie.Yuan * */public @interface Author {    /**     * 注解属性     *    1. 修饰为默认或public     *    2. 不能有主体     */    String name();    int age();}//使用@Author(name = "Jet", age = 30)    public void save() {    }

带默认值的注解:

public @interface Author {    /**     * 注解属性     *    1. 修饰为默认或public     *    2. 不能有主体     */    String name();    int age() default 30;   // 带默认值的注解;  使用的时候就可以不写此属性值}

默认名称:

public @interface Author {    // 如果注解名称为value,使用时候可以省略名称,直接给值    // (且注解只有一个属性时候才可以省略名称)    String value();}//使用@Author("Jet")@Author(value = "Jet")

类型为数组时:

public @interface Author {    String[] value() default {"test1","test2"};}使用:@Author({“”,“”})    public void save() {    }

元注解:

元注解,表示注解的注解!

指定注解的可用范围:
@Target({
TYPE, 类
FIELD, 字段
METHOD, 方法
PARAMETER, 参数
CONSTRUCTOR, 构造器
LOCAL_VARIABLE 局部变量
})

// 元注解 - 2. 指定注解的声明周期
@Retention(RetentionPolicy.SOURCE) 注解只在源码级别有效
@Retention(RetentionPolicy.CLASS) 注解在字节码即别有效 默认值
@Retention(RetentionPolicy.RUNTIME) 注解在运行时期有效

注解反射:

    @Author(remark = "保存信息!!!", age = 19)    public void save() throws Exception {        // 获取注解信息: name/age/remark        // 1. 先获取代表方法的Method类型;        Class clazz = App_2.class;        Method m = clazz.getMethod("save");        // 2. 再获取方法上的注解        Author author = m.getAnnotation(Author.class);        // 获取输出注解信息        System.out.println(author.authorName());        System.out.println(author.age());        System.out.println(author.remark());    }

注解的应用:

import static java.lang.annotation.ElementType.TYPE;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 注解,描述表名称 * @author Jie.Yuan * */@Target({TYPE})@Retention(RetentionPolicy.RUNTIME)  // 指定注解在运行时期有效public @interface Table {    String tableName();}
import static java.lang.annotation.ElementType.FIELD;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 描述一个主键字段 * @author Jie.Yuan * */@Target({FIELD})@Retention(RetentionPolicy.RUNTIME)  // 指定注解在运行时期有效public @interface Id {}
import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;import static java.lang.annotation.ElementType.FIELD;/** * 描述一个字段 * @author Jie.Yuan * */@Target({FIELD})@Retention(RetentionPolicy.RUNTIME)  // 指定注解在运行时期有效public @interface Column {    String columnName();}
/** * 解决优化的问题: *    1. 当数据库表名与类名不一致、  *    2. 字段与属性不一样、 *    3. 主键不叫id  *     */public class BaseDao<T> {    // 当前运行类的类型    private Class<T> clazz;    // 表名    private String tableName;    // 主键    private String id_primary;    // 拿到当前运行类的参数化类型中实际的类型  ( BaseDao<Admin> ,  Admin.class)    public BaseDao(){        Type type = this.getClass().getGenericSuperclass();        ParameterizedType pt = (ParameterizedType) type;        Type[] types = pt.getActualTypeArguments();        clazz = (Class<T>) types[0];        //已经拿到:  Admin.class        /*******1. 获取表名*******/        Table table = clazz.getAnnotation(Table.class);        tableName = table.tableName();        /*******2. 获取主键字段*******/        //获取当前运行类的所有字段、遍历、获取每一个字段上的id注解        Field[] fs = clazz.getDeclaredFields();        for (Field f : fs) {            // 设置强制访问            f.setAccessible(true);            // 获取每一个字段上的id注解            Id anno_id = f.getAnnotation(Id.class);            // 判断            if (anno_id != null) {                // 如果字段上有id注解,当前字段(field)是主键; 再获取字段名称                Column column = f.getAnnotation(Column.class);                // 主键                id_primary = column.columnName();                // 跳出循环                break;            }        }        System.out.println("表:" + tableName);        System.out.println("主键:" + id_primary);    }    public T findById(int id){        try {            String sql = "select * from " + tableName + " where " + id_primary +"=?";            /*             * DbUtils的已经封装好的工具类:BeanHandler?   属性=字段             */            return JdbcUtils.getQuerrRunner().query(sql, new BeanHandler<T>(clazz), id);        } catch (Exception e) {            throw new RuntimeException(e);        }    }    public List<T> getAll(){        try {            String sql = "select * from " + tableName;            return JdbcUtils.getQuerrRunner().query(sql, new BeanListHandler<T>(clazz));        } catch (Exception e) {            throw new RuntimeException(e);        }    }}/** * 自定义结果集:封装单个Bean对象 */class BeanHandler<T> implements ResultSetHandler<T>{    // 保存传入的要封装的类的字节码    private Class<T> clazz;    public BeanHandler(Class<T> clazz) {        this.clazz = clazz;    }    // 封装结果集的方法    @Override    public T handle(ResultSet rs) throws SQLException {        try {            // 创建要封装的对象  ‘1’            T t = clazz.newInstance();             // 向下读一行            if (rs.next()) {                // a. 获取类的所有的Field字段数组                Field[] fs = clazz.getDeclaredFields();                // b. 遍历, 得到每一个字段类型:Field                for (Field f : fs) {                    // c. 获取”属性名称“                    String fieldName = f.getName();                    // e. 获取Field字段上注解   【@Column(columnName = "a_userName")】                    Column column =  f.getAnnotation(Column.class);                    // f. ”字段名“                    String columnName = column.columnName();        // 数据库中字段 a_userName                    // g. 字段值                    Object columnValue = rs.getObject(columnName);                    // 设置(BeanUtils组件)                    BeanUtils.copyProperty(t, fieldName, columnValue);                }            }            return t;        } catch (Exception e) {            throw new RuntimeException(e);        }    }}/** * 自定义结果集:封装多个Bean对象到List集合 */class BeanListHandler<T> implements ResultSetHandler<List<T>>{    // 要封装的单个对象    private Class<T> clazz;    public BeanListHandler(Class<T> clazz){        this.clazz = clazz;    }    // 把从数据库查询到的没一行记录,封装为一个对象,再提交到list集合, 返回List<T>    @Override    public List<T> handle(ResultSet rs) throws SQLException {        List<T> list = new ArrayList<T>();        try {            // 向下读一行            while (rs.next()) {                // 创建要封装的对象  ‘1’                T t = clazz.newInstance();                 // a. 获取类的所有的Field字段数组                Field[] fs = clazz.getDeclaredFields();                // b. 遍历, 得到每一个字段类型:Field                for (Field f : fs) {                    // c. 获取”属性名称“                    String fieldName = f.getName();                    // e. 获取Field字段上注解   【@Column(columnName = "a_userName")】                    Column column =  f.getAnnotation(Column.class);                    // f. ”字段名“                    String columnName = column.columnName();        // 数据库中字段 a_userName                    // g. 字段值                    Object columnValue = rs.getObject(columnName);                    // 设置(BeanUtils组件)                    BeanUtils.copyProperty(t, fieldName, columnValue);                }                // 对象添加到集合                list.add(t);            }            return list;        } catch (Exception e) {            throw new RuntimeException(e);        }    }}

Log4j

配置文件:

# 通过根元素指定日志输出的级别、目的地: #  日志输出优先级: debug < info < warn < error log4j.rootLogger=info,console,file############# 日志输出到控制台 ############## 日志输出到控制台使用的api类log4j.appender.console=org.apache.log4j.ConsoleAppender# 指定日志输出的格式: 灵活的格式log4j.appender.console.layout=org.apache.log4j.PatternLayout# 具体格式内容log4j.appender.console.layout.ConversionPattern=%d %p %c.%M()-%m%n############# 日志输出到文件 #############log4j.appender.file=org.apache.log4j.RollingFileAppender# 文件参数: 指定日志文件路径log4j.appender.file.File=../logs/MyLog.log# 文件参数: 指定日志文件最大大小log4j.appender.file.MaxFileSize=5kb# 文件参数: 指定产生日志文件的最大数目log4j.appender.file.MaxBackupIndex=100# 日志格式log4j.appender.file.layout=org.apache.log4j.PatternLayoutlog4j.appender.file.layout.ConversionPattern=%d %c.%M()-%m%n
public class App {    Log log = LogFactory.getLog(App.class);    @Test    public void save() {        try {            log.info("保存: 开始进入保存方法");            int i = 1/0;            log.info("保存: 执行保存结束,成功");        } catch (Exception e) {            log.error("执行App类Save()方法出现异常!");  // 异常            e.printStackTrace();        }    }    /*     * 思考: 日志的输出级别作用?     *   ----> 控制日志输出的内容。     */    @Test    public void testLog() throws Exception {        // 输出不同级别的提示        log.debug("调试信息");        log.info("信息提示");        log.warn("警告");        log.error("异常");    }}
0 0
原创粉丝点击