反射的总结及案例

目录

 

反射

什么是反射?

为什么使用反射以及Class类的方法?

反射的步骤?

如何通过反射操作构造方法?

如何通过反射操作字段?

如何通过反射操作方法?

如何使用反射实现通用查询方法的封装?


反射

什么是反射?

提供了一种动态获取的机制,允许在程序运行时,直接操作class文件,获取属性、方法、构造器等。

为什么使用反射以及Class类的方法?

  • 获取任意类的名称、package信息、所有属性、方法、注解、类型、类加载器等

Class<Student> stuclass = Student.class;
stuclass.getName();//返回完整类名带包名
stuclass.getSimpleName();//返回类名
Field[] fields = stuclass.getDeclaredFields();//返回类中所有的属性
for (Field field : fields) {
    System.out.println(field);//遍历数组依次输出
}
Method[] methods = stuclass.getDeclaredMethods();//返回类中所有的实例方法
for (Method method : methods) {
    System.out.println(method);
}
Constructor<Student>[] stu =(Constructor<Student>[]) stuclass.getConstructors();//获取构造器

  • 获取任意对象的属性,并且能改变该属性

操作字段步骤:

1.创建对象  

 Class<Student> cls = Student.class;    

Student stu = cls.newInstance();

2.获取字段    

Field field = cls.getDeclaredField("name");

field.setAccessible(true);//允许访问私有属性

3.操作字段  

field.set(stu,"名字");//设置属性

System.out.println(field.get(stu).toString());

  • 调用任意对象的方法

Class<StuDao> stuDaoClass = StuDao.class;

Method method = stuDaoClass.getMethod("方法名",Student.class);//获取指定的方法 对象 参数1:方法名 后续参数:方法中的参数的类型

  • 实例化任意一个类的对象

Class<Student> cls = Student.class;

Student stu = cls.newInstance();//创建对象 

  • 判断任意一个对象所属的类

  • 通过反射我们可以实现动态装配,降低代码的耦合度,动态代理等

反射的步骤?

  • 首先,获取Class类的实例:

三种方法:

1. 类名.class;
2. 对象.getClass();
3.Class.forName("类的完全限定名");//包名+类名

  • 其次,通过Class可以获取构造方法、属性、方法等

public Field[] getFields();//返回类中public修饰的属性

public Field[] getDeclaredFields();//返回类中所有的属性

public Field getDeclaredField(String name);//根据属性名name获取指定的属性

public Method[] getDeclaredMethods();//返回类中所有的实例方法

public Method getDeclaredMethod(String name, Class<?>… parameterTypes);//根据方法名name和方法形参获取指定方法

public Constructor getDeclaredConstructor(Class<?>… parameterTypes);//根据方法形参获取指定的构造方法

如何通过反射操作构造方法?

public class Test{
    public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Class<Student> stuclass = Student.class;
        Constructor<Student> constructor = stuclass.getConstructor();//获取无参构造
        Student stu = constructor.newInstance();//通过构造器创建实例
        System.out.println(stu);
        //获取带参数的构造方法
        Constructor<Student> constructor1 = stuclass.getConstructor(String.class);
       //给构造方法传递参数
        Student stu1 = constructor1.newInstance("名字");
        System.out.println(stu1);
    }
}

如何通过反射操作字段?

public class Test {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchFieldException {
         Class<Student> stuclass = Student.class;
        //获取所有字段
        Field[] fields = stuclass.getDeclaredFields();
        for (Field field : fields) {
            System.out.println(field);
        }
        Student stu = stuclass.newInstance();
        Field name = stuclass.getDeclaredField("name");//根据字段名获取字段
        name.setAccessible(true);//允许访问私有属性
        name.set(stu,"名字");
        System.out.println(name.get(stu));
    }
}

如何通过反射操作方法?

public class Test {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
        Class<StuDaoImpl> stuDaoClass = StuDaoImpl.class;
        StuDaoImpl stuDao = stuDaoClass.newInstance();
        //获取指定的方法 对象 参数1:方法名 后续参数:方法中的参数的类型
        Method insert = stuDaoClass.getMethod("insert",Student.class);
        //调用方法
        boolean result = (boolean) insert.invoke(stuDao, new Student("名字"));
        System.out.println(result);
​
        Method[] methods = stuDaoClass.getMethods();返回类中所有的公有方法
        for (Method method : methods) {
            System.out.println(method);
        }
    }
}

如何使用反射实现通用查询方法的封装?

//查询
    public static <T> List<T> query(Class<T> tclass,String sql,Object...params){
        List<T> list = new ArrayList<>();//集合
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        try {
            connection = getConnection();
            statement = connection.prepareStatement(sql);
            setParams(statement, params);
            resultSet = statement.executeQuery();
            ResultSetMetaData metaData = resultSet.getMetaData();
            while(resultSet.next()){
                //获取T的对象
                T t = tclass.newInstance();
                for (int i = 1; i <= metaData.getColumnCount(); i++) {
                    String columnName = metaData.getColumnLabel(i);//获取字段名
                    Object columnValue = resultSet.getObject(i);//获取字段值,引用类型
                   //获取字段名对应的实体类型的属性
                    Field field = tclass.getDeclaredField(columnName);
                    field.setAccessible(true);
                    //如果结果集中的字段类型不能直接转成实体的属性类型,强制转换
                    if(columnValue instanceof Long){//判断该字段是否是Long
                        Long value = (Long) columnValue;//Object--->转为Long
                        if(field.getType()==int.class){//如果实体中的该字段的类型是int类型
                            field.set(t,value.intValue());//获取Long中整型数字
                        }
                    }else if(columnValue instanceof Date){
                        Date value = (Date) columnValue;
                        if(field.getType() == LocalDate.class){
                            field.set(t,value.toLocalDate());
                        }
                    }
                    else {
                        field.set(t, columnValue);
                    }
                }
                list.add(t);
            }
        } catch (SQLException | InstantiationException | IllegalAccessException e) {
            System.out.println(e.getMessage());
        } catch (NoSuchFieldException e) {
            System.out.println(e.getMessage());
        } finally {
            closeAll(connection, statement, resultSet);
        }
        return list;
    }
//关闭所有
private static void closeAll(Connection connection, PreparedStatement statement, ResultSet resultSet) {
        if(resultSet !=null){
            try {
                resultSet.close();
            } catch (SQLException e) {
                System.out.println(e.getMessage());
            }
        }
        if(statement !=null){
            try {
                statement.close();
            } catch (SQLException e) {
                System.out.println(e.getMessage());
            }
        }
        if(connection !=null){
            try {
                connection.close();
            } catch (SQLException e) {
                System.out.println(e.getMessage());
            }
        }
    }
//绑定参数
    private static void setParams(PreparedStatement statement, Object[] params) throws SQLException {
        if(params !=null){
            for (int i = 0; i < params.length; i++) {
                statement.setObject(i+1, params[i]);
            }
        }
    }
//获取连接
    private static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, user, pwd);
    }

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值