Day13-reflect反射

反射的概念

反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。(对于Java程序来说,状态和行为就是类的变量和方法)

反射是框架的灵魂!

反射的作用
* - 在运行时判断任意一个对象所属的类(对象.getClass().getName())
* - 在运行时构造任意一个类的对象(不用new,直接使用字节码文件对象就能给你创建对象)

 User user1 =(User) class1.newInstance();
           user1.say();
* - 在运行时判断任意一个类所具有的成员变量和方法
* - 在运行时调用任意一个对象的方法。通过反射甚至可以调用到private方法。
* - 生成动态代理(代理模式中的一种)

获得字节码文件的三种方式(没有字节码文件,反射就是空谈)

* - 对象.getClass()        connection.getClass()
* - 使用Class类的forName()静态方法,全路径类名,该方法最常使用           Class.forName("com.mysql.jdbc.Driver");
* - 使用“类型名.class” 类似于User.class
    * 这个方法其实不能单独使用,后面要加上函数,比如User.class.getName();

获取一个类的全路径名字的小技巧:
选中要获取的类,然后右键点击,选中:Copy Qualified Name

利用字节码生成对象

  • 使用无参构造方法,只需调用这个类对应的Class对象的newInstance()方法
User user1 =(User) class1.newInstance();
  • 使用带参数的构造函数生成对象

    • Class对象调用getConstructor(参数类型的Class对象),获取带参数的构造函数;
    • 构造函数调用newInstance(参数)生成对象
Class<?> forName = Class.forName("com.User");
Constructor<?> constructor = forName.getConstructor(int.class,String.class,String.class,String.class); 
//获取到该类的有参数的构造函数
 User user2 =(User) constructor.newInstance(2,"otra","123","rows");
//通过有参数的构造函数调用newInstance(参数)方法
 user2.say();

Class对象的方法一览

  • public String getName()
    - 返回此 Class 对象所表示的实体的全限定名称。
    -field.get(object)
    可以获取指定对象object的某个变量的值。
    如果要获取私有变量的值的话,要先把私有变量的权限设置了。
    setAccessable(true);
  • public String getSimpleName()
    - 返回此 Class 对象所表示的实体的全限定名称。
  • public Field[] getFields()
    - 返回此 Class 对象所表示的实体的所有公共属性。
  • public Field[] getField(String name)
    - 返回此 Class 对象所表示的实体的指定属性名称的公共属性。
  • public Field[] getDeclaredFields()
    - 返回此 Class 对象所表示的实体的所有属性,包括私有属性,但不包括继承父类的属性。
  • public Method[] getMethods()
    - 返回此 Class 对象所表示的实体的所有公共属性。(包括父类中的方法)
  • public Method[] getDeclaredMethods()
    - 返回此 Class 对象表示的实体的所有方法,包括私有方法,但不包括继承父类的方法。
  • public Method getMethod(String name, Class… parameterTypes)
    - 返回此 Class 对象所表示的实体的指定公共成员方法,
    - name指定方法名称,parameterTypes指定方法参数类型
    • public Constructor[] getConstructors()
      • 返回此 Class 对象所表示的类的所有公共构造方法。
  • public Constructor[] getDeclaredConstructors()
    - 返回此 Class 对象表示的类声明的所有构造方法,包括私有构造方法。
  • public Constructor getDeclaredConstructor(Class… parameterTypes)
    - 返回此 Class 对象所表示的类的指定构造方法。
  • public Class
- invoke(Object o,Object... args)
  • o是调用该方法的对象,args是调用该方法时传入的参数

案例:
用反射自定义DBUtils,复写DBUtils框架的基本功能:

package com.itheima.myDBUtils;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

public class MyDBUtils{
      DataSource ds;
      public MyDBUtils(DataSource ds){
           super();
           this.ds = ds;
      }

      public <E> List<E> queryBeenList(String sql,Object[] params,Class<E> clazz) throws Exception{
           //建立连接
           Connection connection = ds.getConnection();
           //创建执行sql语句的对象
           PreparedStatement prepareStatement = connection.prepareStatement(sql);
           //将参数导入都sql语句中去
           if(params != null){
                 for(int i=0;i<params.length;i++){
                      prepareStatement.setObject(i+1, params[i]);
                 }
           }
           //执行sql语句
           ResultSet resultSet = prepareStatement.executeQuery();
           ResultSetMetaData metaData = prepareStatement.getMetaData();
           //获得列数
           int columnCount = metaData.getColumnCount();
           Method[] methods = clazz.getMethods();
           List<E> list = new ArrayList<>();
           //处理结果集
           while(resultSet.next()){
                 E e = clazz.newInstance();
                 //获取列名
                 for(int i=0;i<columnCount;i++){
                      //获取列名
                      String columnName = metaData.getColumnName(1+i);
                      //获取列的值
                      Object object = resultSet.getObject(columnName);
                      //设置值
                      for(int j=0;j<methods.length;j++){
                            if(methods[j].getName().equalsIgnoreCase("set"+columnName)){
                                 methods[j].invoke(e, object);
                            }
                      }
                 }
                 list.add(e);

           }


           return list;
      }
}

调用主函数类:

package com.itheima.myDBUtils;

import java.util.List;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class MainTest02 {
      public static void main(String[] args) throws Exception {
           MyDBUtils myDBUtils = new MyDBUtils(new ComboPooledDataSource());
           String sql = "select * from userinfo";
           List<User> user = myDBUtils.queryBeenList(sql, null, User.class);
           System.out.println(user);
      }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值