java中的反射机制及Demo

一、反射

反射机制是java在实际开发中最常用到的,比如三大框架中都用到了反射机制。JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法,对于任意一个对象,都能够调用它的任意方法和属性。

反射机制看似将java中常用的一条语句拆成许多语句,但是大大的提高了其灵活性。具体例子见如下代码:

首先定义一个javaBean用来封装数据:重写toString方法方便以后将类输出。

public class Bean implements Serializable{
	
	private String id;
	private String className;
	public String description;
	
	
	public Bean(String id) {
		super();
		this.id = id;
		System.out.println("一个参数构造");
	}
	 private Bean(String id, String className) {
		super();
		this.id = id;
		this.className = className;
		System.out.println("两个参数构造");
	}
	 private int show(int age){
		 return age;
	 }
	 
	 public static void main(String[] args){
		 System.out.println(Arrays.toString(args));
	 }
	 
	public Bean() {
		System.out.println("无参构造");
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getClassName() {
		return className;
	}
	public void setClassName(String className) {
		this.className = className;
	}
	@Override
	public String toString() {
		return "Bean [id=" + id + ", className=" + className + ",des=" + description + "]";
	}

}

下面通过三种方式获取此javaBean的class对象:

public class ClassDemo {
	
	@Test
	public void Demo1() throws ClassNotFoundException {
           //1,在开发中便于从配置文件中获取全限定类名
		Class clazz = Class.forName("cn.ahut.gbl.Bean"); 
		System.out.println(clazz);
	}

	@Test
	public void Demo2() throws ClassNotFoundException {
             //2,确定构造方法,不同方法形参列表时,需要通过类型获得
		Class clazz = Bean.class; 
		System.out.println(clazz);
	}
	
	@Test
	public void Demo3() throws ClassNotFoundException {
              //3,方法内部使用获取
		Bean bean = new Bean();
		Class clazz = bean.getClass();
		System.out.println(clazz);
	}
}

二、通过反射机制获取javaBean中的公共和私有构造方法,具体代码如下:

public class ClassDemo2 {
	
	@Test
	public void Demo1() throws Exception {
         //获取无参构造方法
		Class clazz = Class.forName("cn.ahut.gbl.Bean");
	    Constructor con = clazz.getConstructor();
	    Object object = con.newInstance();  //对象进行实例化
		
	}

	@Test
	public void Demo2() throws Exception {
            //获取有参构造方法
		//获取class对象
		Class clazz = Class.forName("cn.ahut.gbl.Bean");
	     //有一个参数的构造
	    Constructor con = clazz.getConstructor(String.class);
	    Object object = con.newInstance("abc123");
	    System.out.println(object);
	    
		
	}
	
	@Test
	//无参构造的简写
	public void Demo3() throws Exception {
		Class clazz = Class.forName("cn.ahut.gbl.Bean");
		//通过clazz直接创造
	    Object object = clazz.newInstance();	
	}
	
	@Test
	public void Demo4() throws Exception {
           //获取指定类中的私有构造方法
		//获取class对象
		Class clazz = Class.forName("cn.ahut.gbl.Bean");
		//获取构造
		/*clazz.getConstructor(....);指定类中公共的构造方法
		 * clazz.getDeclaredConstructor(....);指定类中任意的构造方法
		 */
	Constructor cons = clazz.getDeclaredConstructor(String.class,String.class);
		//通知JVM运行私有构造参数 (默认不允许)
		cons.setAccessible(true);
		Object object = cons.newInstance("adf123","姓名");
		System.out.println(object);
	}
	
	
}

三、通过反射获取制定类中公共、私有和静态方法以及公共和私有的字段。具体代码如下:

public class ClassDemo3 {
	
	@Test
	//通过反射获取公共普通的方法
	public void Demo1() throws Exception {
		//获取类对象
		Class clazz = Class.forName("cn.ahut.gbl.Bean");
		//实例化
		Object object = clazz.newInstance();
		//通过setId获取数据
		Method method  = clazz.getMethod("setId", String.class);
		//设置数据,并执行方法
		method.invoke(object, "ab001");
		//打印数据
		Method method1  = clazz.getMethod("getId");
		String string = (String) method1.invoke(object);
		System.out.println(string);
		
	}
	

	@Test
	//通过反射获取私有普通的方法
	public void Demo2() throws Exception {
		//获取类对象
		Class clazz = Class.forName("cn.ahut.gbl.Bean");
		//实例化
		Object object = clazz.newInstance();
		//通过setId获取数据
		Method method  = clazz.getDeclaredMethod("show", int.class);
		method.setAccessible(true);
		//设置数据
		Object object2 = method.invoke(object, 18);
		//打印数据
		
		System.out.println(object2);
		
	}
	
	@Test
	//通过反射获取静态主方法
	public void Demo3() throws Exception {
		//获取类对象,主方法是静态的,不需要实例化
		Class clazz = Class.forName("cn.ahut.gbl.Bean");
		
		//获取方法
	    Method method  = clazz.getMethod("main", String[].class);
		
		//执行main方法
	    /*第一个参数为实例对象(变量名),main方法是静态的,不需要
	     * 第二个参数为字符串数组,是实际参数
	     * 可变参数再执行的时候,JVM将里面的额参数打乱,变成多个参数,所以会报错
	     * 所以这里可以将数组强制转换成Object类型
	     */
	    String[] args= {"张三","男","abc121"};
		method.invoke(null, (Object)args);	
	}
	
	@Test
	//通过反射获取public字段
	public void Demo4() throws Exception {
		//获取类对象,
		Class clazz = Class.forName("cn.ahut.gbl.Bean");
		Object obj = clazz.newInstance();
		//获取方法
	    Field field  = clazz.getField("description");
	    //给字段赋值
	    field.set(obj, "描述");
	    //取出字段的值
	    String string = (String) field.get(obj);
	   
	    System.out.println(string);
			
	}
	
	@Test
	//通过反射获取private字段
	public void Demo5() throws Exception {
		//获取类对象,
		Class clazz = Class.forName("cn.ahut.gbl.Bean");
		Object obj = clazz.newInstance();
		//获取方法
	    Field field  = clazz.getDeclaredField("className");
	    field.setAccessible(true);
	    
	    //给字段赋值
	    field.set(obj, "javaBean");
	    //取出字段的值
	    String string = (String) field.get(obj);
	   
	    System.out.println(string);
			
	}

}

四、properties是java中以键值对存储的,以.properties结尾,在开发中用作配置文件。在框架的开发中需要读取配置文件,进行动态的编码。下面展示如何写入和读取properties文件。

public class PropsDemo {
	
	@Test
	public void Demo1() throws IOException {
		//properties的操作:写入文件
		Properties properties = new Properties();
		properties.setProperty("name", "老张");
		properties.setProperty("sex", "男");
		properties.setProperty("age", "65");
		//将properties写入硬盘
Writer writer = new OutputStreamWriter(new FileOutputStream("1.properties"), "UTF-8");
		properties.store(writer, "描述");
		writer.close();
		
	}
	
	@Test
	public void Demo2() throws IOException {
		////properties的操作:读文件
		//获得properties对象
		Properties properties = new Properties();
		//获得流资源
		Reader reader = new InputStreamReader(new FileInputStream("1.properties"), "UTF-8");
		//通过properties对象下载资源
		properties.load(reader);
		//遍历内容
		for (String name : properties.stringPropertyNames()) {
			String value = properties.getProperty(name);
			System.out.println(name+":"+value);
		}
		
	}

}

五,下面编写一个Demo,看一下如何动态的获取配置文件中的内容来调用javaBean。

在这里我们分别编写beanConfig,bean和book三个javaBean文件,以及bean.properties和data.properties文件。bean.properties中存储的是data.properties文件的id和jabaBean的类对象,data.properties文件中存储的是对应javaBean中的具体数据。

如下所示:

public class BeanConfig {
	private String id;
	private String className;
	Properties properties = new Properties();
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getClassName() {
		return className;
	}
	public void setClassName(String className) {
		this.className = className;
	}
	public Properties getProperties() {
		return properties;
	}
	public void setProperties(Properties properties) {
		this.properties = properties;
	}
	@Override
	public String toString() {
		return "BeanConfig [id=" + id + ", className=" + className
				+ ", properties=" + properties + "]";
	}

	
}
public class Book {
	private String bid;
	private String title;
	private String price;
	public String getBid() {
		return bid;
	}
	public void setBid(String bid) {
		this.bid = bid;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getPrice() {
		return price;
	}
	public void setPrice(String price) {
		this.price = price;
	}
	@Override
	public String toString() {
		return "Book [bid=" + bid + ", title=" + title + ", price=" + price
				+ "]";
	}
	
	

}
public class UserBean {
	private String uid;
	private String userName;
	private String passWord;
	public String getUid() {
		return uid;
	}
	public void setUid(String uid) {
		this.uid = uid;
	}
	public String getUserName() {
		return userName;
	}
	public void setUserName(String userName) {
		this.userName = userName;
	}
	public String getPassWord() {
		return passWord;
	}
	public void setPassWord(String passWord) {
		this.passWord = passWord;
	}
	@Override
	public String toString() {
		return "UserBean [uid=" + uid + ", userName=" + userName
				+ ", passWord=" + passWord + "]";
	}
	
	
	

}

下面通过读取properties中的内容为beanConfig添加字段信息:

public class DemoTest {
	public BeanConfig getConfig() throws  Exception {
		//读取配置文件
		BeanConfig beanConfig = new BeanConfig();
		//读取bean.properties文件内容,获取ID和className
		Properties properties = new Properties();
		properties.load(new InputStreamReader(new FileInputStream("bean.properties"),"UTF-8"));
		beanConfig.setId(properties.getProperty("id"));
		beanConfig.setClassName(properties.getProperty("className"));
		//System.out.println(beanConfig);
		
		//读取data.properties文件内容
		Properties dataProperties = new Properties();
		dataProperties.load(new InputStreamReader(new FileInputStream("data.properties"),"UTF-8"));
		for(String name : dataProperties.stringPropertyNames()){
			System.out.println(name);
			String value = dataProperties.getProperty(name);
			beanConfig.getProperties().setProperty(name, value);	
		}
		return beanConfig;
	}
	
	
	@Test
	public void method1() throws Exception {
		
		
		
		
		//真实数据
				BeanConfig beanConfig = getConfig();
				
				//使用数据创建javaBean实例,并为javaBean封装具体数据
				Class clazz = Class.forName(beanConfig.getClassName());
				Object object = clazz.newInstance();
				
				//调用javaBean中的set方法进行封装
	for(String  name : beanConfig.getProperties().stringPropertyNames()){
	String value = beanConfig.getProperties().getProperty(name);
					//获得方法名
	String methodName = "set" + name.substring(0,1).toUpperCase() + name.substring(1);
					//调用set方法
					Method method = clazz.getMethod(methodName, String.class);
					method.invoke(object, value);
				}
				
				System.out.println(object);
		
		
	}
发布了27 篇原创文章 · 获赞 6 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/LOLUN9/article/details/104391162