Java反射

参考:反射技术菜鸟从入门到精通(一)_weixin_30952535的博客-CSDN博客

1、实例化带参数的内部类:

public class Out {
    private final class Worker {
        String name;

        Worker(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }

    private void test11(String hh) {
        System.out.println("kkk=" + hh);

    }
}

 

  public Object getInstance(Object instance,String className,Object object) throws ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException {
      

        Class<?> enclosingClass = Class.forName(className);
        Constructor constructor = enclosingClass.getDeclaredConstructors()[0];

        constructor.setAccessible(true);
        return  constructor.newInstance(instance,object);
    }
 Out2 out2=new Out2();
        Object ll=out2.getInstance(out2,"thread.Out$Worker","ddddddddd");
        System.out.println(ll);

 

 Runnable firstTask=new Runnable() {
            @Override
            public void run() {
                System.out.println("Runnable-init");
            }
        };
        MyThreadPool threadPoolExecutor=TestThreadPool.getMyThreadPool();
        Object w=out2.getInstance(threadPoolExecutor,"java.util.concurrent.ThreadPoolExecutor$Worker",firstTask);
        System.out.println(w);

2、获取内部类的属性值

Thread t= (Thread)out2.getPrivateValue(w,"thread");
        System.out.println(t);
    public  Object getPrivateValue(Object obj ,String propName) {
        Object value = null;
        try {

            // 通过属性获取对象的属性
            //.getDeclaredFields() 获得某个类的所有声明的字段,即包括public、private和proteced但不包括父类申明字段
            //.getClass() 是?个对象实例的?法,只有对象实例才有这个?法,具体的类是没有的

            Field field = obj.getClass().getDeclaredField(propName);
            // 对象的属性的访问权限设置为可访问
            //允许获取实体类private的参数信息
            field.setAccessible(true);
            // 获取属性的对应的值
            value = field.get(obj);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return value;
    }

3、 调用私有化方法,并传参数

 获取Method时,getDeclaredMethod方法一定需要参数名称 和参数类型,才可获取Method对象

Class c = obj.getClass().getSuperclass();

// https://blog.csdn.net/qq_34626094/article/details/122687833
 //getDeclaredMethod java.lang.NoSuchMethodException的异常原因在于调用getDeclaredMethod时要同时指定方法名和参数名,这两个不能错误。
 Method method = c.getDeclaredMethod(propName,val.getClass());
Object a1=out2.getPrivateMethodValue(threadPoolExecutor,"addWorkerFailed",w);
        System.out.println(a1);
    public Object getPrivateMethodValue(Object obj, String propName,Object val) {
        //Object value = null;
        try {
            Class c = obj.getClass().getSuperclass();

           // https://blog.csdn.net/qq_34626094/article/details/122687833
            //getDeclaredMethod java.lang.NoSuchMethodException的异常原因在于调用getDeclaredMethod时要同时指定方法名和参数名,这两个不能错误。
            Method method = c.getDeclaredMethod(propName,val.getClass());
            method.setAccessible(true);
            Object[] values = new Object[1];
            values[0] = val;
            return method.invoke(obj,values);
        } catch (Exception e) {
            return null;
        }
    }

JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

Java的反射机制是在编译并不确定是哪个类被加载了,而是在程序运行的时候才加载、操作。使用在编译期并不知道的类,这样的特点就是反射。

反射的作用?

  1. 由于众多框架都是用到了反射机制(例如Spring的IOC与AOP,Hibernate的对象实体关系映射),学了反射我们可以更好的学习框架;
  2. 根据反射的特点,我们可以通过反射来了解类的构成,做出一系列比较通用的工具代码(也就是框架);
  3. 将许多代码变为自动化实现,以此达到减少开发周期的目的。

实例一、

JDBC查询数据库时,希望把数据库中的多条记录保存到java中的一个List中对象,如Mysql默认的User表

如Mysql数据库中的user表。

public class TestEmp {
public List getAllEmp() {
        List list = new ArrayList<>();
        Connection conn = DBUtil.getConnection();
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            String sql = "select * from user";
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();
            while (rs.next()) {
                // 创建一个User的对象
                User e = new User();
                //e.setEmpno(rs.getInt("empno"));
                e.setHost(rs.getString("Host"));
                e.setUser(rs.getString("User"));
               ......
                list.add(e);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(conn, ps, rs);
        }
        return list;
    }
}

红字都是“没有意义的体力活“,如果下次查询Dept表,还要创建Dept对象,所以我们可以利用反射将其封装成一个方法:


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

public class TestEmp {

    // 目的:将数据库中的一行记录转化为java中一个对象
    public List rows2beans(String sql, Class cls) { //将Mysql记录转换为Java 中Bean对象
        List list = new ArrayList();
        Connection conn = DBUtil.getConnection();
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = conn.prepareStatement(sql);
            rs = ps.executeQuery();

            // 每一个rs对象都对应一个ResultSetMetaData对象
            ResultSetMetaData rsmd = rs.getMetaData();

            // 获取查询的列数
            int count = rsmd.getColumnCount();

            while (rs.next()) {
                Object object = cls.newInstance(); //cls决定生成什么对象
                for (int i = 0; i < count; i++) {
                    // 获取第一列的名字
                    String fieldName = rsmd.getColumnName(i + 1).toLowerCase();

                    // 通过列名获取类中的属性的表述对象
                    Field field = cls.getDeclaredField(fieldName);

                    // 根据set方法名获取set方法对应的表述对象
                    Method m = cls.getDeclaredMethod(getSetMethodName(fieldName), field.getType());

                    Object objval = rs.getObject(fieldName);
                    if (objval != null) {
                        if (objval instanceof Number) {
                            if (field.getType().getName().equals("int")) {
                                m.invoke(object, rs.getInt(fieldName));
                            } else if (field.getType().getName().equals("long")) {
                                m.invoke(object, rs.getLong(fieldName));
                            } else if (field.getType().getName().equals("double")) {
                                m.invoke(object, rs.getDouble(fieldName));
                            } else if (field.getType().getName().equals("short")) {
                                m.invoke(object, rs.getShort(fieldName));
                            } else if (field.getType().getName().equals("byte")) {
                                m.invoke(object, rs.getByte(fieldName));
                            } else if (field.getType().getName().equals("float")) {
                                m.invoke(object, rs.getFloat(fieldName));
                            }
                        } else {
                            m.invoke(object, objval);
                        }
                    }
                }
                list.add(object);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(conn, ps, rs);
        }
        return list;
    }

   // 根据属性名获取该属性的set方法的名字
    public String getSetMethodName(String fieldName) {
        return "set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
    }

 我们就完成了对任意一条SQL语句的查询封装,

我们只需要给定sql语句以及要生成的类型即可得到一个有关一张表数据的List,一起来看main方法

public static void main(String[] args) {
    
    List list = obj.rows2beans("select * from user", User.class);
    System.out.println(list.size()) //数据为14条

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值