1.反射概念
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
理解Reflect
-
反射
-
反转
理解为控制反转,权力的反转:
每一个人都有活着的权力,行动和自由的权力;每一个类都有创建对象,调用属性和方法的权力。现在将类的这些权力转交给Class对象,让它来帮助某个类去完成这些操作。 -
理解Class
每一个实体类都会被编译成字节码文件,java眼中万事万物都是对象,那么天下所有的字节码文件都可以看成是对象,谁的对象呢? 当然得有一个类,来代表所有的字节码文件,这个类就是Class类。
即:所有类文件被编译成字节码文件后,都可以看成是Class类的对象。
例如:
Class c=Dog.class; //Dog.class就表示Dog类文件被编译后的字节码文件
2.反射功能
- 三种方式获取Class对象
//获取Class --范围:所有的字节码文件
public void test1() throws ClassNotFoundException {
//方式1--通过类名
Class c=Dog.class;//Dog.java编译后的字节码文件
Class c1=Book.class;//Book.java编译后的字节码文件
//方式2--通过对象
Class c3 = new Dog().getClass();
//方式3--通过类路径
Class c4 = Class.forName("reflect1.Book");
}
- 管理无参构造
//1.管理无参构造
public void test2() throws Exception {
//1.获取到某个类的字节码文件对象,即Class的对象
Class<Dog> c = Dog.class;
//2.帮Dog调用无参构造
Dog dog = c.newInstance();
System.out.println(dog);
}
- 管理有参构造
//2.管理有参构造
public void test3() throws Exception {
//1.获取到某个类的字节码文件对象,即Class的对象
Class<Dog> c = Dog.class;
//2.获取有参构造的管理对象--2个参数的那个
Constructor<Dog> con = c.getDeclaredConstructor(String.class,int.class);
//3.帮助Dog类调用有参构造
Dog dog = con.newInstance("旺财",2);
System.out.println(dog);
}
- 管理属性
//3.管理属性
public void test4() throws Exception {
//1.获取到某个类的字节码文件对象,即Class的对象
Class<Dog> c = Dog.class;
//2.获取某个属性的管理对象
Field f = c.getDeclaredField("name");
//先创建一个狗狗对象
Dog dog = c.newInstance();
f.setAccessible(true);//开启私有属性操作权限
//3.帮助dog给name属性赋值
f.set(dog,"来福");
System.out.println(dog);
}
- 管理方法
//4.管理方法
public void test5() throws Exception {
//1.获取到某个类的字节码文件对象,即Class的对象
Class<Dog> c = Dog.class;
//2.获取某个方法setAge(int age)的管理对象
Method m = c.getDeclaredMethod("setAge", int.class);
//先创建一个狗狗对象
Dog dog = c.newInstance();
//3.帮助dog给调用setAge方法
m.invoke(dog,3);
//System.out.println(dog);
//管理toString方法
Method m2 = c.getDeclaredMethod("toString");
System.out.println(m2.invoke(dog));
}
3.案例
反射结合泛型案例
将一个map中的数据转存到一个实体类对象中。
//案例一:将一个map中的数据转存到一个实体类对象中。
public void test5() throws Exception {
HashMap<String, Object> map = new HashMap<>();
map.put("name","旺财");
map.put("age",3);
Dog dog = getObject(map, Dog.class);
System.out.println(dog);
}
public <T>T getObject(Map<String,Object> map, Class<T> c) throws Exception {
T t = c.newInstance();
//1.拆开map
Set<Map.Entry<String, Object>> entries = map.entrySet();
for (Map.Entry<String, Object> entry : entries) {
String key = entry.getKey();
//2.将map中的值存入T这个类的对象属性中
Field f = c.getDeclaredField(key);
f.setAccessible(true);
f.set(t,entry.getValue());
}
return t;
}
xml和反射综合案例
- 宠物管理系统
1.预先定义好父类:动物类,子类:狗狗类,企鹅类,大象类,
2.在xml文件中配置各个宠物类的全路径名
3.编写一个宠物领养方法,根据用户输入的宠物名称,从xml读取相应的类路径,使用反射构建宠物对象,并返回。
注意:使用父类作为方法返回值,字符串作为参数。
<?xml version="1.0" encoding="UTF-8" ?>
<animal>
<狗狗>
<name>旺财</name>
<class>reflect.pet.Dog</class>
</狗狗>
<企鹅>
<name>皮皮</name>
<class>reflect.pet.Penguin</class>
</企鹅>
<大象>
<name>肉肉</name>
<class>reflect.pet.Elephant</class>
</大象>
</animal>
public void test1() throws Exception {
Scanner sc=new Scanner(System.in);
System.out.println("请选择您要领养的宠物:狗狗,企鹅,大象");
String name = sc.next();
Animal animal = getAnimal(name);
System.out.println(animal);
}
public Animal getAnimal(String name) throws Exception {
// 1.创建解析器
SAXReader reader = new SAXReader();
// 解析xml文档,得到document对象
Document document = reader.read("src/reflect1/pet/pet.xml");
// 根据document对象获取根节点
Element root = document.getRootElement();
// 查找根节点下的子节点 element() elements()
Element animal = root.element(name);
String className = animal.element("class").getText();
//2.使用反射创建对象
return (Animal) Class.forName(className).newInstance();
}