反射机制_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 反射机制

反射机制

 2013/8/9 18:19:57  剑晨java  程序员俱乐部  我要评论(0)
  • 摘要:反射,就是加载类,并解剖出类的各个组成部分,指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes,反射在做框架时会需要用到,比如给你个配置文件,需要你运行一个地址里的class的某个方法,此时就不能用传统方法去实例化和调用方法,就可以用反射来解决。(1)反射类的构造函数。有getConstructor(Class<?>...parameterTypes)和getDeclaredConstructor(Class<?>...parameterTypes
  • 标签:反射 反射机制
   反射,就是加载类,并解剖出类的各个组成部分,指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes,反射在做框架时会需要用到,比如给你个配置文件,需要你运行一个地址里的class的某个方法,此时就不能用传统方法去实例化和调用方法,就可以用反射来解决。
   (1)反射类的构造函数。有getConstructor(Class<?>... parameterTypes) 和getDeclaredConstructor(Class<?>... parameterTypes) 两个方法,前者得到的是public构造函数,而后者得到的是private构造函数。
//测试得到构造函数
	@Test
	public void test1(){
		try {
			//加载Person类
			Class class1=Class.forName("cn.itcast.reflect.Person");
			//反射Person类的无参构造 public Person(){}
			Constructor constuctor=class1.getConstructor(null);
			//根据无参构造函数实例化对象
			Person p=(Person) constuctor.newInstance(null);
			//得到私有构造函数 private Person(String name,int age){}
			Constructor constuctor1=class1.getDeclaredConstructor(String.class,int.class);
			constuctor1.setAccessible(true);//暴力反射,得到类的私有方法
			//不能访问,除非constuctor1.setAccessible(true)
			Person p1=(Person) constuctor1.newInstance("name",21);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

  (2)反射类的方法。有getMethod(String name, Class<?>... parameterTypes) 和getDeclaredMethod(String name, Class<?>... parameterTypes) 。
	@Test
	public void test2() throws Exception{
		Person p=new Person();
		Class class1=Class.forName("cn.itcast.reflect.Person");
		//得到方法 ,第一个参数传入方法名,后一个参数传入方法需要传入的参数类型public void test(){}
		Method method1=class1.getMethod("test", null);
		//执行方法,传入对象和参数
		method1.invoke(p, null);
		//得到方法 public void test(String name){}
		Method method2=class1.getMethod("test", String.class);
		//执行方法
		method2.invoke(p, "name");
		//得到方法 private void test(int num){}
		Method method3=class1.getDeclaredMethod("test", int.class);
		//获得权限
		method3.setAccessible(true);
		method3.invoke(p, 3);
	}

  (3)反射类的main方法。class1.getMethod("main", String[].class)。不过这里有个地方需要注意。就是调用invoke方法传参是如果method.invoke(null,new String[]{"1","2"}),这样写会报传参个数异常错误,因为JDK会把数组拆开,这样就会有多个String,就会报错。
	@Test
	public void test3() throws Exception{
		Class class1=Class.forName("cn.itcast.reflect.Person");
		Method method=class1.getMethod("main", String[].class);
		//将数组包装起来,两种方法
		method.invoke(null,new Object[]{new String[]{"1","2"}});
		method.invoke(null,(Object)new String[]{"1","2"});
	}

  (4)反射类的字段。方法getField(String name) 。
	@Test
	public void test4() throws Exception{
		Person p=new Person();
		Class class1=Class.forName("cn.itcast.reflect.Person");
		//得到name字段
		Field field1=class1.getField("name");
		//得到字段类型
		Class type=field1.getType();
		if(type.equals(String.class)){
			String name=(String) field1.get(p);
			System.out.println(name);
		}
		//设置字段值
		field1.set(p, "bbbb");
		System.out.println(p.name);
	}

   内省,内省是sun公司为了操作javabean属性而开发出来的,javabean就是将功能、处理、值、数据库访问和其他任何可以用java代码创造的对象进行打包,就是封装。为写成javabean,类必须是具体的和公共的,并且具有无参数的构造器。比如下面就是一个javabean。
public class Student {
	private String name;
	private int age;
	private int examid;
	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 int getExamid() {
		return examid;
	}
	public void setExamid(int examid) {
		this.examid = examid;
	}
	public void getGrade(){
		
	}
}

   这个javabean拥有5个属性,bean拥有属性有get或set方法决定,并且每个类都有继承父类的class属性。有两种方法javabean操作属性。
    (1)可以通过java.beans 类 Introspector的getBeanInfo(Class<?> beanClass)
得到对象的属性,并通过 java.beans接口 BeanInfo的getPropertyDescriptors()
得到属性描述器。
     (2)通过java.beans  类PropertyDescriptor。
//得到属性
	@Test
	public void test1() throws Exception{
		BeanInfo info1=Introspector.getBeanInfo(Person.class);
		//可以去除父类属性
		BeanInfo info2=Introspector.getBeanInfo(Person.class,Object.class);
		PropertyDescriptor[] pds1 =info1.getPropertyDescriptors();//得到属性描述器
		PropertyDescriptor[] pds2 =info2.getPropertyDescriptors();//得到属性描述器
		for(PropertyDescriptor pd: pds1){
			System.out.println(pd.getName());//得到属性名称
		}
		for(PropertyDescriptor pd: pds2){
			System.out.println(pd.getName());//得到属性名称
		}
	}
	//操纵属性
	@Test
	public void test2() throws Exception{
		Person p=new Person();
		PropertyDescriptor pd=new PropertyDescriptor("name",Person.class);
		System.out.println(pd.getPropertyType());//得到属性的类型
		Method method1=pd.getWriteMethod();//得到set方法
		method1.invoke(p, "aaa");//执行p的set方法
		System.out.println(p.getName());
		Method method2=pd.getReadMethod();//得到get方法
		System.out.println(method2.invoke(p, null));
	}

 
发表评论
用户名: 匿名