一、概念
反射就是把Java类中的各种成分映射成一个个的java对象。例如,一个类有:成员变量,方法,构造方法,包等等信息,利用反射技术可以对一个类进行解剖,把各个组成部分映射成一个个对象。即把.class文件解刨分析(用于框架的设计)。
二、获取内容
1、基本文件
package com.shen2;
public class Person {
public String name; //字段或成员变量
private int age;
public final String password = "123"; //字段或成员变量
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(){
//System.out.println("person!!!!!");
}
public Person(String name){
System.out.println(name);
}
private Person(int name){
System.out.println(name);
}
public void eat(){
System.out.println("eat!!!!");
}
public void run(String address){
System.out.println("跑到" + address);
}
public void run(String address,int num[],String ss[]){
System.out.println("跑到" + address + "," + num);
}
public String test(String str){
return str + "aaaa";
}
private String test2(String str){
return str + "aaaa";
}
public static String test3(String str){
return str + "aaaa";
}
public static void main(String[] args) {
System.out.println(args[0]);
}
}
注意:一个类的属性有多少看get和set方法而不是字段
2、获取类
// 方法1.该方法最长见
Class clazz1 = Class.forName("com.shen2.Person");
// 方法2
//Class clazz2 = Person.class;
// 方法3
// Class clazz3 = new Person().getClass();
//实例化
Person p = (Person) clazz1.newInstance();
3、获取构造函数
/**
* 利用Constructor创建对象
*
* @throws Exception
*/
// 反射类无参的构造方法
@Test
public void test1() throws ClassNotFoundException, NoSuchMethodException,
InstantiationException, IllegalAccessException,
InvocationTargetException {
Class clazz = Class.forName("com.shen2.Person");
Constructor c = clazz.getConstructor(null);//null表示无参构造函数
Object obj = c.newInstance(null);//创建实例
System.out.println(obj);
}
// 反射类有参的构造方法:public Person(String name)
@Test
public void test2() throws ClassNotFoundException, NoSuchMethodException,
InstantiationException, IllegalAccessException,
InvocationTargetException {
Class clazz = Class.forName("com.shen.Person");
Constructor c = clazz.getConstructor(String.class);//string.class表示参数类型为string的构造函数
Person p = (Person) c.newInstance("flx");//传递参数为"flx"
System.out.println(p);
}
// 反射类私有的、有参的构造方法:private Person(int name)
@Test
public void test3() throws ClassNotFoundException, NoSuchMethodException,
InstantiationException, IllegalAccessException,
InvocationTargetException {
Class clazz = Class.forName("com.shen.Person");
Constructor c = clazz.getDeclaredConstructor(int.class);
c.setAccessible(true);// 访问权限强制打开
Person p = (Person) c.newInstance(1);
System.out.println(p);
}
4、获取方法
package com.shen2.reflect;
import java.lang.reflect.Method;
import org.junit.Test;
public class Demo3 {
//反射方法
//反射:public void eat()(无参)
@Test
public void test1() throws Exception{
Person p = new Person(); //
Class clazz = Class.forName("com.shen2.Person"); //完整名称
Method method = clazz.getMethod("eat", null); //eat,获取方法
method.invoke(p, null); //eat,执行
}
//反射:run(String address){(带一个参数)
@Test
public void test2() throws Exception{
Person p = new Person(); //
Class clazz = Class.forName("com.shen2.Person"); //完整名称
Method method = clazz.getMethod("run", String.class);
method.invoke(p, "北京");
}
//反射:public void run(String address,int num[],String ss[]){(多个参数)
@Test
public void test3() throws Exception{
Person p = new Person(); //
Class clazz = Class.forName("com.shen2.Person"); //完整名称
Method method = clazz.getMethod("run", String.class,int[].class,String[].class);
method.invoke(p, "上海",new int[]{1,2},new String[]{"1","2"});
}
//反射:public String test(String str) (带返回值)
@Test
public void test4() throws Exception{
Person p = new Person(); //
Class clazz = Class.forName("com.shen2.Person"); //完整名称
Method method = clazz.getMethod("test", String.class);
String result = (String) method.invoke(p, "xxxx");
System.out.println(result);
}
//反射:private String test2(String str) 私有方法
@Test
public void test5() throws Exception{
Person p = new Person(); //
Class clazz = Class.forName("com.shen2.Person"); //完整名称
Method method = clazz.getDeclaredMethod("test2", String.class);
method.setAccessible(true);
method.invoke(p, "");
}
//反射:public static String test3(String str){ 静态方法
@Test
public void test6() throws Exception{
Class clazz = Class.forName("com.shen2.Person"); //完整名称
Method method = clazz.getMethod("test3", String.class);
String result = (String) method.invoke(null, "aaa");
System.out.println(result);
}
//反射:public static void main(String[] args) { 反射main方法
//通过反射调用带数组的方法,要注意处理
@Test
public void test7() throws Exception{
Class clazz = Class.forName("com.shen2.Person"); //完整名称
Method method = clazz.getMethod("main", String[].class);
method.invoke(null, (Object)new String[]{"1","2"});//main(String args[])
//method.invoke(null, new Object[]{new String[]{"1","2"}});//main(String args[])
//public Object invoke(Object obj, Object... args) //jdk1.5
//public Object invoke(Object obj, Object[] args) //jdk1.4
//public void run(String name,String password)
//method.invoke(p,new Object[]{"flx,123"})//1.4
//method.invoke(p,"flx","123")
}
}
5、获取字段
//反射:public String name;
@Test
public void test1() throws Exception{
Person p = new Person();
Class clazz = Class.forName("cn.itcast.reflect.Person");
Field f = clazz.getField("name"); //name
f.set(p, "flx");
System.out.println(p.getName());
}
//反射:public String name;
@Test
public void test2() throws Exception{
Person p = new Person();
p.setName("xxx");
Class clazz = Class.forName("cn.itcast.reflect.Person");
Field f = clazz.getField("name"); //name
String result = (String) f.get(p);
System.out.println(result);
}
//反射:public final String password = ""; //字段或成员变量
@Test
public void test3() throws Exception{
Person p = new Person();
Class clazz = Class.forName("cn.itcast.reflect.Person");
Field f = clazz.getField("password"); //name
String result = (String)f.get(p);
System.out.println(result);
}
//反射:private int age; 私有字段
@Test
public void test4() throws Exception{
Person p = new Person();
Class clazz = Class.forName("cn.itcast.reflect.Person");
Field f = clazz.getDeclaredField("age");
f.setAccessible(true);
f.set(p, 123);
int result = (Integer) f.get(p);
System.out.println(result);
}
}
三、内省机制
1、通过Introspector操作bean属性
//通过内省api操作bean的name属性
@Test
public void test1() throws Exception{
Person p = new Person();
PropertyDescriptor pd = new PropertyDescriptor("name",Person.class);//取出name
Method method = pd.getWriteMethod(); //setName()
method.invoke(p, "flx");
//System.out.println(s.getName());
method = pd.getReadMethod(); // getName
String result = (String) method.invoke(p, null);
System.out.println(result);
}
//操作bean的所有属性
@Test
public void test2() throws Exception{
BeanInfo info = Introspector.getBeanInfo(Person.class);
PropertyDescriptor pds[] = info.getPropertyDescriptors();//取出所有属性,所有函数继承Object故也会取出class(object中有getclass)
for(PropertyDescriptor pd : pds){
System.out.println(pd.getName());
}
}
2、通过beanutils工具包操作bean属性(常用)
需要导入jar包
1.操作对象
Student.java
package com.shen.beanutils;
import java.util.Date;
public class Student {
private String name;
private String xx;
private String password;
private String email;
private int age;
private Date birthday;
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getXx() {
return xx;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setXx(String xx){
this.xx = xx;
}
public void setYy(String yy){
}
}
2.操作
1.简单获取和设置
/**
* 用beanUtils操作bean
*/
public static void main(String[] args) throws IllegalAccessException, Exception {
Student s = new Student();
BeanUtils.setProperty(s, "name", "xiao");
System.out.println(s.getName());
}
2.运用例举
在客户端传入多个参数后设置参数
//传入的值
String name = "flx";
String password = "123";
String age = "23";
String email = "flx@sina.com";
Student s = new Student();
//设置多个属性
BeanUtils.setProperty(s, "name", name);
BeanUtils.setProperty(s, "password", password);
BeanUtils.setProperty(s, "age", age); //int(8种基本类型他会自动转换)
BeanUtils.setProperty(s, "email", email);
System.out.println(s.getAge());
3.复杂类型转换(时间转换)
//传入的值
String birthday = "1980-09-09"; //date
Student s = new Student();
//需要自己注册转换器
//ConvertUtils.register(new DateLocaleConverter(), Date.class);//别人定义的转换器
//自定义转换器
ConvertUtils.register(new Converter(){//接口也可以new,但要实现抽象方法
public Object convert(Class type, Object value) { //"1980-09-09"
if(value==null){
return null;
}
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
Date date = null;
try {
date = (Date) format.parse((String)value);
} catch (ParseException e) {
throw new ConversionException(e);
}
return date;
}
}, Date.class);
//设置多个属性
BeanUtils.setProperty(s, "birthday", birthday); //把string转换为date
System.out.println(s.getBirthday()); //date*/
}