Java基础(十一)——反射

     Java反射最大的好处就是能在运行期间,获得某个类的结构、成员变量,用来实例化,而不是仅仅靠new来实现。

     

     一、获得Class对象


     在Java中,每个类被加载之后,系统就会为类生成一个对象的Class对象,通过该Class对象就可以访问JVM中的这个类了。在Java程序中,获得Class对象通常有如下三种方式。


     1.使用Class类的forName(String clazzName)静态方法。该方法需要传入字符串参数,该字符串参数的值是某个类的全限定类名(必须添加完整包名);

     2.调用某个类的class属性,如Person.class将会返回Person类对象的Class对象;

     3.调用某个对象的getClass()方法。该方法时java.lang.Object类中的一个方法,所有的Java对象都可以调用。


     有了Class对象,我们就可以通过Class对象来获取其所对应类的详细信息,我们可以获取Class对应类所包含的构造器、方法、成员变量、注释、修饰符、所在包、类名等基本信息。


     二、创建对象

     

     通过反射来生成对象有如下两种方式:

     1.使用Class对象的newInstance()方法来创建该Class对象对应类的实例,这种方式要求该Class对象的对应类有默认构造器,而执行newInstance()方法实际上是利用默认构造器来创建该类的实例。

package cn.gome.d_generic;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

public class ObjectPoolFactory {
	
	//定义一个对象池,签名是对象名,后面是实际对象
	private Map<String, Object> objectPool = new HashMap<String, Object>();
	
	//方法一:定义一个创建对象的方法,只要传入字符串类名,程序可以根据该类名生成Java对象
	private Object createObject (String clazzname) throws ClassNotFoundException, InstantiationException, IllegalAccessException{
		//根据字符串类获取对应的对象
		Class<?> clazz = Class.forName(clazzname);
		//使用clazz对象对应类的默认构造器创建实例
		return clazz.newInstance();
	}
	
	//方法二:此方法根据指定文件来初始化对象池,根据配置文件来创建对象
	public void initPool(String fileName) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException{
		FileInputStream fis = new FileInputStream(fileName);
		
		Properties props = new Properties();
		props.load(fis);
		for (String name : props.stringPropertyNames()) {
			//key-value键值对,根据name获取对应的值
			objectPool.put(name, createObject(props.getProperty(name)));
		}
	}
	
	//方法三:从ObjectPool中取出指定name对应的对象
	public Object getObject(String name){
		return objectPool.get(name);
	}
	
	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {
		ObjectPoolFactory pFactory = new ObjectPoolFactory();
		pFactory.initPool("obj.txt");
		System.out.println(pFactory.getObject("a"));
		System.out.println(pFactory.getObject("b"));
	}	
}


     2.先使用Class对象获取指定的Constructor对象,在调用Constructor对象的newInstance()方法来创建该Class对象对应类的实例。通过这种方式可以选择使用指定的构造器来创建实例。

package cn.gome.d_generic;

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

import javax.swing.JFrame;

public class CreateJFrame {
	public static void main(String[] args) throws NoSuchMethodException,
			SecurityException, InstantiationException, IllegalAccessException,
			IllegalArgumentException, InvocationTargetException {
		// 获取JFrame对应的Class对象
		Class<?> clazz = JFrame.class;
		// 获取JFrame中带一个字符串参数的构造器
		Constructor cor = clazz.getConstructor(String.class);
		// 调用Constructor的newInstance方法创建对象
		Object object = cor.newInstance("测试窗口");
		//输出JFrame对象
		System.out.println(object);
	}
}


     三、操作对象


     1.调用方法

     当获得某个类对应的Class对象后,就可以通过该Class对象的getMethods()方法或者getMethod()方法来获取全部方法或指定方法,每当Method对象对应一个方法,获得Method对象后,程序就可以通过Method的invoke()方法来调用它。

     Object invoke(Object obj,Object... args):该方法中的obj是执行该方法的主调(方法所在类的实例),后面的args是执行该方法时传入方法的实参。


     2.访问成员变量

     通过Class对象的getFields()或者getField()方法可以获取该类所包括的全部成员变量或指定成员变量。Field对象提供了如下两组方法来读取或设置成员变量值。

     getXxx(Object obj):获取obj对象的该成员变量的值。

     setXxx(Object obj,Xxx val):将obj对象的该成员变量设置成val值。


     四、操作数组


     在java.lang.reflect包下还提供了一个Array类,Array对象可以代表所有的数组。程序可以通过使用Array来动态地创建数组,操作数组元素。

package cn.gome.d_generic;

import java.lang.reflect.Array;
public class ArrayTest {
	public static void main(String[] args) {
		//创建一个元素类型为String,长度为10的数组
		Object arrObject = Array.newInstance(String.class,10);
		//依次为arrObject数组中index为5、6、7的元素赋值
		Array.set(arrObject, 5, "周周");
		Array.set(arrObject, 6, "江江");
		Array.set(arrObject, 7, "霄霄");
		//依次取出arrObject数组中index为5、6、7的元素的值
		Object o1 = Array.get(arrObject, 5);
		Object o2 = Array.get(arrObject, 6);
		Object o3 = Array.get(arrObject, 7);
		//输出arrObject数组中index为5、6、7的元素的值
		System.out.println(o1);
		System.out.println(o2);
		System.out.println(o3);
	}
}


     以上就是对就java中反射的简单介绍,反射在我们日程的开发工作中用到的情况很频繁,了解反射机制的原理能帮助我们在使用反射机制的时候更加容易理解反射的原理。



    

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值