我们都知道程序运行时可以改变程序结构或变量类型,在java中有个机制叫做:Reflection 。java程序中可以在运行时加载,探知,使用编译期间完全未知的class。

      术语概念:java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。对于任意一个对象,都能够调用它的任意方法和属性,这种动态获取信息,动态调方法的功能称为java的反射机制。

      个人通俗理解:java反射机制无非就是破坏了原有的封装,因此可以动态获取到里面的属性,方法等。

      总结如下:

  • 查看类内部信息

     具体步骤:

  1. 创建class对象;三种方法:Class.forName("全类名"); 类型.class; 对象.getClass();
  2. class对象.getXXX()方法查看信息
  • 创建对象

     方法一步骤:

  1. 创建class对象;三种方法:Class.forName("全类名"); 类型.class; 对象.getClass();
  2. class对象.newInstance();

     方法二步骤:

  1. 创建class对象;三种方法:Class.forName("全类名"); 类型.class; 对象.getClass();
  2. 创建构造对象(Constructor);class对象.getConstructor(参数);
  3. 构造对象.newInstance(参数);
  • 操作对象的方法

     具体步骤:

  1. 创建class对象;三种方法:Class.forName("全类名"); 类型.class; 对象.getClass();
  2. 创建对象;步骤参看上面
  3. 创建方法对象(Method);class对象.getDeclaredMethod("方法名",参数列表...);
  4. 设置访问权限;方法对象.setAccessible(true);//私有方法必须设置这个;
  5. 调用方法。方法对象.invoke(对象,实参);

   代码示例如下:

/**
 * 使用反射生成对象并操作对象
 * @author 山石
 *
 */
public class Test6 {
	//Map键值对
	private Map<String, Object> mapPool = new HashMap<String, Object>();
	//创建并实例化对象
	private Object creatObject(String className) throws Exception {
		Class<?> c = Class.forName(className);//className相当于限定全称
		return c.newInstance();//使用Class对象的newInstance()方法来创建该Class对象对应类的实例,这种方式要求该Class对象的对
		//应类有默认构造器,而执行newInstance()方法时实际上是利用默认构造器来创建该类实例。
	}
	public void initPool(String fileName) {
		// 读取文件
		FileInputStream fis = null;
		try {
			fis = new FileInputStream(fileName);
			Properties p = new Properties();// 针对Properties类型文件
			p.load(fis);// 加载读取文件
			for (String name : p.stringPropertyNames()) {//p.stringPropertyNames()获取所有的属性名:如 a b
				mapPool.put(name, creatObject(p.getProperty(name)));//p.getProperty(name)获取value
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			if(fis!=null){
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	public Object getObject(String name){
		return mapPool.get(name);//读取出对象池中指定name的对象
	}
	public static void main(String[] args) {
		Test6 t6=new Test6();
		t6.initPool("D:\\obj.txt");
		System.out.println(t6.getObject("a"));
	}
}

 

  • 操作对象的属性

      具体步骤: 

  1. 创建class对象;三种方法:Class.forName("全类名"); 类型.class; 对象.getClass();
  2. 创建对象;步骤参看上面
  3. 创建属性对象(Field);class对象.getDeclaredField("属性名");
  4. 设置访问权限;属性对象.setAccessible(true);//私有属性必须设置这个;
  5. 调用属性的get或set方法。

  代码示例如下:

public class Test8 {
	class Person {
		public String name;
		private int age;
		private void print() {
			System.out.println("姓名:" + name + "\n年龄:" + age);
		}
	}
	public static void main(String[] args) throws Exception {
		Class<Person> c = Person.class;
		Object obj = c.newInstance();
		Field fName = c.getField("name");
		fName.set(obj, "山石");
		Field fage = c.getDeclaredField("age");
		fage.setAccessible(true);
		fage.set(obj, 20);
		Method m = c.getDeclaredMethod("print");
		m.setAccessible(true);
		m.invoke(obj);
	}
	
}

 使用反射操作数组,利用反射创建数组并赋值:

   在java.lang.reflect包下提供了一个Array类,Array类可以代 表所有的数组。示例如下:

/**
 * 使用反射操作数组,利用反射创建数组并赋值。
 * 
 * @author 山石
 * 
 */
public class Test02 {
	public static void main(String[] args) {
		Object arr = Array.newInstance(String.class, 10);
		Array.set(arr, 5, "我是山石");
		Array.set(arr, 6, "我是小山石");
		Object ss = Array.get(arr, 5);
		Object xss = Array.get(arr, 6);
		System.out.println(ss);
		System.out.println(xss);
	}
}