Day13-reflect反射

来源:互联网 发布:商之翼yii2源码 编辑:程序博客网 时间:2024/06/14 18:40

反射的概念

反射的概念是由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);      }}
原创粉丝点击