参考:反射技术菜鸟从入门到精通(一)_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的反射机制是在编译并不确定是哪个类被加载了,而是在程序运行的时候才加载、操作。使用在编译期并不知道的类,这样的特点就是反射。
反射的作用?
- 由于众多框架都是用到了反射机制(例如Spring的IOC与AOP,Hibernate的对象实体关系映射),学了反射我们可以更好的学习框架;
- 根据反射的特点,我们可以通过反射来了解类的构成,做出一系列比较通用的工具代码(也就是框架);
- 将许多代码变为自动化实现,以此达到减少开发周期的目的。
实例一、
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条
}
1445

被折叠的 条评论
为什么被折叠?



