码迷,mamicode.com
首页 > 编程语言 > 详细

Java反射

时间:2015-05-17 21:59:30      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:getconstructor   newinstance   getdeclaredmethod   invoke   反射   


反射(reflective)是指能够分析类的能力的程序。

    反射库(reflection library)提供了一个非常丰富且精心设计的工具集,以便编写能够动态操作Java代码的程序。


    程序运行期间,Java运行时系统始终未所有的对象维护一个被称为运行时的类型标识。这个信息跟踪着每个对象所属的类。虚拟机利用运行时信息选择相应的方法执行。


概念叙述


    Class 反射对象描述类的语义结构,可以从Class对象中获取构造函数、成员变量、方法等元素的反射对象,并以编程的方式通过这些反射对象对目标类对象进行操作。这些反射对象类定义在java.reflect包中,包含Constructor,Method 和 Field。

  • Constructor类的构造函数反射类,通过Class#getConstructors() 方法可以获得类的所有构造函数反射对象数组。在JDK 5.0中,还可以通过getConstructor(Class ...parameterTypes) 获取拥有特定入参的构造函数反射对象。Constructor的一个主要方法是newInstance(Object[] initargs),通过该方法可以创建一个对象类的示例,相当于使用了new关键字。
  • Method类方法的反射类,通过Class#getDeclaredMethods() 方法可以获取类的所有方法反射类对象数组Method[]。在JDK5.0中可以通过 getDeclaredMethod(String name, Class ... parameterTypes)获取特定签名的方法,name为方法名;Class ... 为方法入参类型列表。Method 最主要的方法是invoke(Object obj, Object[] args),obj 标示操作的目标对象,args 为方法入参。此外,Method 方法还有很多用于获取类方法更多信息的方法:Class getReturnType() 获取方法的返回值类型;Class[] getParameterTypes() 获取方法的入参类型数组;Class getExceptionTypes() 获取方法的异常类型数组。
  • Field类的成员变量的反射类,通过Class#getDeclaredFields() 方法可以获取类的成员变量反射对象数组。通过Class#getDeclaredField(String name) 则可获取某个特定名称的成员变量反射对象。Field 类最主要的方法是set(Object obj, Object value) obj 标示操作的目标对象,通过value为目标对象的成员变量设置值。如果成员变量为基础类型,用户可以使用Field 类中提供的带类型名的值设置方法,如setBoolean(Object obj, boolean value)、setInt(Object obj, int value) 等。


代码示例


       部分反射功能在上一篇博文 证明接口interface中的方法访问权限为public 已经做过示例,这里就不再做叙述,这里只讲没有讲到的部分,不了解的朋友,可以先查看上一篇博文


package com.zhangqi.reflect;

public class Car {

	private String id;
	private String name;
	private int maxSpeed;
	
	public Car() {};
	
	public Car(String id, String name, int maxSpeed) {
		this.id = id;
		this.name = name;
		this.maxSpeed = maxSpeed;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getMaxSpeed() {
		return maxSpeed;
	}

	public void setMaxSpeed(int maxSpeed) {
		this.maxSpeed = maxSpeed;
	}
	
	// 重写toString方法,输出可读的对象属性数据
	public String toString() {
		return "id=" + this.id + ",name=" + this.name + ",maxSpeed=" + this.maxSpeed;
	}
}

测试代码

package com.zhangqi.reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class CarReflect {

	public static void main(String[] args) throws ClassNotFoundException, 
		NoSuchMethodException, SecurityException, InstantiationException, 
		IllegalAccessException, IllegalArgumentException, InvocationTargetException, 
		NoSuchFieldException {
		
		Class<?> clazz = Class.forName("com.zhangqi.reflect.Car");
		
		// 获取构造函数数组
		Constructor<?>[] cons = clazz.getConstructors();
		
		System.out.println("分割线-- 下面的为构造函数--");
		
		// 遍历构造函数数组
		for (Constructor<?> con : cons) {
			System.out.println(con);
		}
		
		System.out.println("分割线-- 下面为有参的构造函数--");
		
		// 获取指定参数类型的构造方法
		Constructor<?> conInArgs = clazz.getConstructor(String.class, String.class, int.class);
		System.out.println(conInArgs);
		
		// 调用newInstance 方法构造对象
		Car car1 = (Car) conInArgs.newInstance("001", "Audi", 210);
		
		System.out.println("分割线-- 下面打印car1 对象");
		
		System.out.println(car1);
		
		// 获取无参的构造方法
		Constructor<?> conNoArgs = clazz.getConstructor((Class<?>[])null);
		Car car2 = (Car) conNoArgs.newInstance((Object[])null);
		
		// 获取特定签名的方法
		// 依次获取setId方法、setName方法、setMaxSpeed方法
		Method setId = clazz.getDeclaredMethod("setId", String.class);
		
		System.out.println("分割线-- 下面输出的是setId方法");
		
		System.out.println(setId);
		
		Method setName = clazz.getDeclaredMethod("setName", String.class);
		Method setMaxSpeed = clazz.getDeclaredMethod("setMaxSpeed", int.class);
		
		// 通过调用invoke方法,给car2 赋属性值
		setId.invoke(car2, "002");
		setName.invoke(car2, "Volvo");
		setMaxSpeed.invoke(car2, 240);
		
		System.out.println("分割线 -- 下面打印通过方法赋值后的car2对象");
		
		System.out.println(car2);
		
		// 获取getId方法
		Method getId = clazz.getDeclaredMethod("getId", (Class<?>[])null);
		
		System.out.println("分割线 -- 下面输出getId方法的返回值类型");
		
		// 获取方法的返回值类型
		System.out.println(getId.getReturnType());
		
		System.out.println("分割线-- 下面输出有参构造函数的参数类型");
		
		// 获取方法的入参类型数组
		Class<?>[] parameterTypes = conInArgs.getParameterTypes();
		for (Class<?> cla : parameterTypes) {
			System.out.println(cla);
		}

		System.out.println("分割线-- 下面输出成员变量id");
		
		// 获取某个特定名称的成员变量反射对象
		Field id = clazz.getDeclaredField("id");
		System.out.println(id);
		
		id.setAccessible(true);
		// Exception in thread "main" java.lang.IllegalAccessException: Class com.zhangqi.reflect.CarReflect can not access a member of class com.zhangqi.reflect.Car with modifiers "private"
		id.set(car2, "id002");
		
		System.out.println("分割线-- 下面输出通过成员变量赋值方式修改过的对象");
		
		System.out.println(car2);
	}
}

输出结果

分割线-- 下面的为构造函数--
public com.zhangqi.reflect.Car()
public com.zhangqi.reflect.Car(java.lang.String,java.lang.String,int)
分割线-- 下面为有参的构造函数--
public com.zhangqi.reflect.Car(java.lang.String,java.lang.String,int)
分割线-- 下面打印car1 对象
id=001,name=Audi,maxSpeed=210
分割线-- 下面输出的是setId方法
public void com.zhangqi.reflect.Car.setId(java.lang.String)
分割线 -- 下面打印通过方法赋值后的car2对象
id=002,name=Volvo,maxSpeed=240
分割线 -- 下面输出getId方法的返回值类型
class java.lang.String
分割线-- 下面输出有参构造函数的参数类型
class java.lang.String
class java.lang.String
int
分割线-- 下面输出成员变量id
private java.lang.String com.zhangqi.reflect.Car.id
分割线-- 下面输出通过成员变量赋值方式修改过的对象
id=id002,name=Volvo,maxSpeed=240


代码讲解


Car car1 = (Car) conInArgs.newInstance("001", "Audi", 210);
构造一个Car 对象出来,这里使用newInstance 方法,相当于new 关键字,同时传递相应入参进去。


		// 获取方法的入参类型数组
		Class<?>[] parameterTypes = conInArgs.getParameterTypes();
		for (Class<?> cla : parameterTypes) {
			System.out.println(cla);
		}

这里的输出结果中

class java.lang.String
class java.lang.String
int
前面两个String 对应的是id 和 name的类型,最后的int 是基础类型,所以是单的int


id.setAccessible(true);
id.set(car2, "id002");
这里必须要id.setAccessible(true); 因为id为private类型,必须先将其设置为可访问,否则抛出异常

Exception in thread "main" java.lang.IllegalAccessException: Class com.zhangqi.reflect.CarReflect can not access a member of class com.zhangqi.reflect.Car with modifiers "private"



Java反射

标签:getconstructor   newinstance   getdeclaredmethod   invoke   反射   

原文地址:http://blog.csdn.net/magi1201/article/details/45788715

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!