## 反射知识##
什么是反射: 按照类的生命周期,先编译生成 .class(字节码)对象,然后JVM类加载器去加载 class对象,解析,实例化等一系列,然后 给调用者使用。 然而反射这一技术 是怎么体现: 通过字节码文件对象,去使用成员变量,构造方法,成员方法;大概就是 以前这些操作 要new xx();现在只要 class对象,就可以去操作;大概就是 反过来使用。
现在 提基本语法,然后等下再深入:
A:通过反射获取构造方法并使用
B:通过反射获取成员变量并使用
C:通过反射获取成员方法并使用
// ********A:通过反射获取构造方法并使用 ********
// 获取字节码对象
Class c = Class.forName("com.csmz.Person");
// 获取带参构造方法对象
// public Constructor<T> getConstructor(Class<?>... parameterTypes)
Constructor con = c.getConstructor(String.class, int.class,
String.class);
// 通过带参构造方法对象创建对象
// public T newInstance(Object... initargs)
Object obj = con.newInstance("林青霞", 27, "北京");
// 获取所有的成员变量
// Field[] fields = c.getFields();
// Field[] fields = c.getDeclaredFields();
// for (Field field : fields) {
// System.out.println(field);
// }
// ********B:通过反射获取成员变量并使用 ********
/*
* Person p = new Person(); p.address = "北京"; System.out.println(p);
*/
// 通过无参构造方法创建对象
Constructor con = c.getConstructor();
Object obj = con.newInstance();
System.out.println(obj);
// 获取单个的成员变量
// 获取address并对其赋值
Field addressField = c.getField("address");
// public void set(Object obj,Object value)
// 将指定对象变量上此 Field 对象表示的字段设置为指定的新值。
addressField.set(obj, "北京"); // 给obj对象的addressField字段设置值为"北京"
System.out.println(obj);
// ********C:通过反射获取成员方法并使用 ********
// 获取单个方法并使用
// public void show()
// public Method getMethod(String name,Class<?>... parameterTypes)
// 第一个参数表示的方法名,第二个参数表示的是方法的参数的class类型
Method m1 = c.getMethod("show");
// obj.m1(); // 错误
// public Object invoke(Object obj,Object... args)
// 返回值是Object接收,第一个参数表示对象是谁,第二参数表示调用该方法的实际参数
m1.invoke(obj); // 调用obj对象的m1方法
2. 基本 语法 就是这样了,但是 好多初学者 虽然知道知识点,但是不知道怎么去理解运用!
我现在 知识点水平到了 SSH 左右了,我来描述下,我在 学知识途中 怎么去理解运用:
– 在学 Servlet时 from 表单传递请求参数,我们要进行封装,
-解决一:servlet 我可以getPartmert(“xx”); 然后bean.setXX()这样去封装,假如参数传递过来参数多了,我们这样 去获取 不是很麻烦,于是我采取了方式二:利用反射知识点去解决.
-解决二: 利用反射知识点 但是表单的传递过来的name 必须先和bean的属性名相同,试着去写,真的好方便 ,我以前的代码:
<form action="/day_01Servlet/servlet2/MyServlet2" method="post">
姓名:<input id="name" type="text" name="name"/><br/>
密码:<input type="password" name="password"/><br/>
性别:<input type="radio" name="gender" value="1" checked="checked"/>男
<input type="radio" name="gender" value="0"/>女<br/>
<!-- 建议不写(选中true 不选false) value属性: true,on,1 -->
已婚:<input type="checkbox" name="married" value="true" /><br/>
故乡:<select name="city">
<option value="BJ">北京</option>
<option value="SD">山东</option>
<option value="HB">湖北</option>
</select><br/>
爱好:<input type="checkbox" name="hobby" value="eat"/>吃饭
<input type="checkbox" name="hobby" value="sleep"/>睡觉
<input type="checkbox" name="hobby" value="java"/>学Java<br/>
简介:<textarea name="description" rows="3" cols="38"></textarea><br/><input type="submit" value="注册"/>
</form>
/**
* 使用反射知识点,获取 请求参数,然后封装Bean author:renfuyi
*
* @throws IllegalAccessException
* @throws IllegalArgumentException
*
*/
public Object getBean(HttpServletRequest request,
HttpServletResponse response) throws IllegalArgumentException,
IllegalAccessException {
// 获得实体
Student student = new Student();
// 获取 请求参数
Enumeration<String> enumeration = request.getAttributeNames();
// 获得实体 字节码对象
Class stu_class = student.getClass();
// 获得 成员方法
Field[] fields = stu_class.getDeclaredFields();
int i = 0;
while (enumeration.hasMoreElements()) {
// 成员变量对象 进行赋值
fields[0].set(student,
request.getAttribute(enumeration.nextElement()));
i++;
}
return student;
}
正因为 用反射,方便,伟大先辈们 ,已经跟我们封装好了 BeanUtils.JAR,上面代码也就是 BeanUtils底层。
/**
* 使用Beanutils
* @throws Exception
* @throws IllegalAccessException
*/
private void testParamter03(HttpServletRequest request) throws IllegalAccessException, Exception{
Student student=new Student();
System.out.println("封装前"+student);
BeanUtils.populate(student,request.getParameterMap());
System.out.println("封装后"+student);
}
– 在配置spring 时,直接写上类的全路径比如 (”com.mchange.v2.c3p0.ComboPooledDataSource”)
该spring框架,就通过你配置的路径,用Class.forName(“全路径”),然后.newIntance(),跟你new 出来,假如修改 你只需要修改配置文件 就OK了.
<bean id="ds" class="com.mchange.v2.c3p0.ComboPooledDataSource">
– 项目练习:我用到反射+泛型知识点,去描述 通用类(父类),确实方便多了,然后 灵活应用也体现了。
public class UserDaoImpl extends BaseDaoImpl<User> implements IUserDao
public class RegionDaoImpl extends BaseDaoImpl<region> implements IRegionDao
**
* 持久层通用实现
*
* @author renfuyi
*
* @param <T>
*/
public class BaseDaoImpl<T> extends HibernateDaoSupport implements IBaseDao<T> {
// T 的 实体 class对象
private Class<T> entityClass;
@Resource
public void setMySessionFactory(SessionFactory sessionFactory) {
super.setSessionFactory(sessionFactory);
}
/**
* 构造方法中 获得 T 这个class 对象
*/
public BaseDaoImpl() {
// 1.0 获得 父类的泛型 对象
ParameterizedType type = (ParameterizedType) this.getClass()
.getGenericSuperclass();
// 2.0 获得泛型对象
Type[] types = type.getActualTypeArguments();
entityClass = (Class<T>) types[0];
}
@Override
public void save(T entity) {
this.getHibernateTemplate().save(entity);
}
@Override
public void delete(T entity) {
this.getHibernateTemplate().delete(entity);
}
大概总结:虽然懂了 反射知识点,但是 得去灵活运用,慢慢 去体会 其中的奥秘,我也希望 java初学者,学的知识 要去拓展。