1 参考资料
- https://how2j.cn/k/reflection/reflection-class/108.html 一个比较全面的Java学习教程(这里用下人家的代码)
- Java编程思想
2 反射的由来
假设自己从磁盘文件或者网络获取了一串字节,且被告知这串字节代表了一个类。然后,我们如何去使用这样的一个类?
解决办法----反射(Class类和java.lang.reflect类对反射概念进行了描述)
3 反射和RTTI的区别
很简单,RTTI是在编译时打开和检查.class文件,反射是在运行时打开和检查.class文件。
4 反射能干嘛
4.1 获取Class对象
这个就是三种方法获取Class对象。
点它进去看详细介绍
不点这也有图( ̄▽ ̄)
4.2 创建对象
首先我们这里得现有一个定义好的Hero类。
public class Hero {
public String name;
public float hp;
public int damage;
public int id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Hero(){
}
public Hero(String string) {
name =string;
}
@Override
public String toString() {
return "Hero [name=" + name + "]";
}
public boolean isDead() {
// TODO Auto-generated method stub
return false;
}
public void attackHero(Hero h2) {
System.out.println(this.name+ " 正在攻击 " + h2.getName());
}
}
然后我们来测试下,用反射方法创建新的Hero对象
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class ReflectDemo {
public static void main(String[] args) throws IllegalAccessException,
InstantiationException,
NoSuchMethodException,
InvocationTargetException {
// Class 直接创建实例,但是该类必须要有一个无参的默认构造函数
//只能反射无参的构造器,需要构造器可见;
Class<Hero> heroClass = Hero.class;
Hero hero = heroClass.newInstance();
// 通过类的构造器创建实例,可以反射任何构造器,可以反射私有构造器
Constructor<Hero> heroConstructor = heroClass.getConstructor(String.class);
Hero hero1 = heroConstructor.newInstance("CC");
System.out.println(hero.toString());
System.out.println(hero1.toString());
}
}
瞅瞅结果
4.3 修改属性值
Class<Hero> heroClass = Hero.class;
Hero hero = heroClass.newInstance();
hero.setName("CC");
System.out.println("hero's Name is "+hero.getName());
Field field = heroClass.getField("name");
field.set(hero,"GG");
System.out.println("hero's Name is "+hero.getName());
结果,
PS:getField 只能获取public的,包括从父类继承来的字段。
getDeclaredField 可以获取本类所有的字段,包括private的,但是不能获取继承来的字段。
(注: 这里只能获取到private的字段,但并不能访问该private字段的值,除非加上setAccessible(true))
4.4 调用方法
同理,这边也很简单了
Class<Hero> heroClass = Hero.class;
Hero h = heroClass.newInstance();
// 获取这个名字叫做setName,参数类型是String的方法
Method m = heroClass.getMethod("setName", String.class);
// 对h对象,调用这个方法
m.invoke(h, "盖伦");
// 使用传统的方式,调用getName方法
System.out.println("hero's name is "+h.getName());
结果