反射是Java中至关重要的一个概念,我们必须要对它进行掌握。
1. 反射概念
反射指的是对对象的反向处理操作。所谓反向指的是根据对象来获得对象的来源信息(对象类的来源信息 包名.类名)。
为了区分正向和反向,我们看下面这个正向例子。
// 1. 我们想要创建Date类的对象实例化,首先要引入定义Data类的包
import java.util.Date;
public class Test {
public static void main(String[] args) {
// 2. 然后再创建Date实例化
Date date = new Date();
}
}
而反向操作就是通过一个对象,得到这个对象类的信息。
import java.lang.reflect.Field;
class Person {
public String name;
public int age;
}
public class Test {
public static void main(String[] args) {
// 1. 创建一个类的实例化
Person person = new Person();
// 2. 拿到这个对象的Class对象
Class<?> cls = person.getClass();
// 3. 获取对象所在类所有的属性信息(暂时不用管原理,后面会讲)
Field[] fields = cls.getDeclaredFields();
// 4. 打印
for(Field tmp : fields) {
System.out.println(tmp);
}
}
}
运行结果:
由运行结果我们可以看出,通过反向操作我们成功的通过一个对象拿到了对象所在类的信息(不单单是属性,还有普通方法,构造方法等信息),这就叫反射。
即反射研究的不再是一个对象,而是对象身后的组成(类,构造,成员等)。
接下来,我们来讲一讲反射。首先第一步,使用反射我们要先拿到对象的 Class类 对象。
2 Class类对象
Class类是由JVM产生的,描述类的信息。
当类装载时,JVM会对每种类产生一个唯一对应的Class对象(每个类不论装载多少次,只会产生一个该类的Class对象)。
有三种实例化Class类对象的方式。
2.1 Object类的getClass()方法
任何类的实例化对象可以通过Object类中的getClass()方法取得Class类对象。
public final native Class<?> getClass();
上面的例子,就是通过这种方法产生对象的Class类实例化。
class Person {
}
public class Test {
public static void main(String[] args) {
Person person = new Person();
// Object.getClass拿到对象Class类实例化
Class<?> cls = person.getClass();
// 打印类的信息
System.out.println(cls);
}
}
2.2 类.class
”类.class”:直接根据某个具体的类来取得Class类的实例化对象。
class Person {
}
public class Test {
public static void main(String[] args) {
Class<?> cls = Person.class;
System.out.println(cls);
}
}
2.3 Class类的forName()方法
调用 Class类 的静态方法 forName(类的全名称(包名.类名)) 取得满足条件的对象:
public static Class<?> forName(String className)
class Person {
}
public class Test {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> cls = Class.forName("class13.Person");
System.out.println(cls);
}
}
运行结果:
除了第一种方法会产生类的实例化对象之外,其他两种都不会产生类实例化对象
3. 反射实例化对象
取得了类的Class对象之后,我们就可以使用反射了,反射可以做很多事情。
- 实例化对象
- 取得类中属性
- 取得类中普通方法
- 取得类中构造方法
- 修改类中属性(甚至是private属性)
- ……
在这里,介绍通过反射实例化对象
public T newInstance()
throws InstantiationException, IllegalAccessException
class Person {
public void print() {
System.out.println("hello");
}
}
public class Test {
public static void main(String[] args) throws Exception {
Class<?> cls = Class.forName("class13.Person");
Object object = cls.newInstance();
// 因为使用 Object 接收 Person类,所以这里要向下转型,这里只是演示用,实际中,不会出现这种操作
((Person) object).print();
}
}
所以,通过反射我们又学到了一种创建对象实例化的方式。
- 正向创建:通过构造方法
Demo demo = new Demo();
- 反向创建:通过反射
Class<?> cls = Class.forName(类完整名称);
// 通过Class对象实例化对象,等价于 new 类完整名();
Object obj = cls.newInstance();
// 实例化对象时必须进行向下转型
((Demo)obj).method();
通过反向创建取得了Class对象就意味着取得了一个指定类的操作权。