我们都知道程序运行时可以改变程序结构或变量类型,在java中有个机制叫做:Reflection 。java程序中可以在运行时加载,探知,使用编译期间完全未知的class。
术语概念:java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法。对于任意一个对象,都能够调用它的任意方法和属性,这种动态获取信息,动态调方法的功能称为java的反射机制。
个人通俗理解:java反射机制无非就是破坏了原有的封装,因此可以动态获取到里面的属性,方法等。
总结如下:
- 查看类内部信息
具体步骤:
- 创建class对象;三种方法:Class.forName("全类名"); 类型.class; 对象.getClass();
- class对象.getXXX()方法查看信息
- 创建对象
方法一步骤:
- 创建class对象;三种方法:Class.forName("全类名"); 类型.class; 对象.getClass();
- class对象.newInstance();
方法二步骤:
- 创建class对象;三种方法:Class.forName("全类名"); 类型.class; 对象.getClass();
- 创建构造对象(Constructor);class对象.getConstructor(参数);
- 构造对象.newInstance(参数);
- 操作对象的方法
具体步骤:
- 创建class对象;三种方法:Class.forName("全类名"); 类型.class; 对象.getClass();
- 创建对象;步骤参看上面
- 创建方法对象(Method);class对象.getDeclaredMethod("方法名",参数列表...);
- 设置访问权限;方法对象.setAccessible(true);//私有方法必须设置这个;
- 调用方法。方法对象.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"));
}
}
- 操作对象的属性
具体步骤:
- 创建class对象;三种方法:Class.forName("全类名"); 类型.class; 对象.getClass();
- 创建对象;步骤参看上面
- 创建属性对象(Field);class对象.getDeclaredField("属性名");
- 设置访问权限;属性对象.setAccessible(true);//私有属性必须设置这个;
- 调用属性的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);
}
}