一、反射机制
反射:将类的各个组成部分(成员变量、构造方法、成员方法)封装成其他对象(Field对象、Construction对象、Method对象),这就是反射机制。
反射的用途:
可以在程序的运行过程中去操作这些对象(Field对象、Construction对象、Method对象)。
还可以解耦,提高程序的可扩展性。
1.在运行时判断任意一个对象所属的类
2.在运行时构造任意一个类的对象
3.在运行时得到任意一个类所具有的成员变量和成员函数
4.在运行时调用任意一个对象的成员变量和方法
5.生成动态代理
下图是反射原理图(来源于网络)
反射相关的主要类:(看上图理解)
1.java.lang.Class:代表一个类,Class对象表示某个类加载在堆中的对象
2.java.lang.reflect.Method:Method的对象代表某个类的方法
3.java.lang.reflect.Field:Field对象代表某个类的成员变量
4.java.lang.reflect.Constructor:Constructor对象代表某个类的构造方法
java.lang.reflect包提供了用于获取类和对象的反射信息的类和接口。
详细介绍:
1)Class
获取class对象的方式
1).Class.forName("全类名") 将字节码文件加载进内存,返回Class对象(tipd:全类名是包名.类名)
2).类名.class 通过类名的属性class获取
3).对象.getClass() 该方法在object类中有定义。
package reflect;
import domain.Person;
public class reflectDemo {
/*
获取class的三种方式
*/
public static void main(String[] args) throws ClassNotFoundException {
Class cls1 = Class.forName("domain.Person");
Class cls2 = Person.class;
Person p = new Person(null, 0);
Class cls3 = p.getClass();
System.out.println(cls1);
System.out.println(cls2);
System.out.println(cls3);
//这三个都是Person字节码文件在内存中生成的class对象
System.out.println(cls1 == cls2);
System.out.println(cls2 == cls3);
}
}
/*Person是定义的一个有构造函数、get函数、set函数、toString函数的一个类。tips:这些基本的类都可以右击然后选source自动生成。
运行输出如下:
class domain.Person
class domain.Person
true
true
*/
class对象的功能:
1).获取
获取成员变量、构造方法、成员方法,获取类名。
Class cls = Class.forName("classfullpath") ;//类全名
获取类自身的信息:
1. 包路径
cls.getPackage();
2. 类名
cls.getName();
cls.getSimpleName();
3. 类修饰符
cls.getModifiers();
4. 类属性
cls.getFields();
注意getFields方法不能获取私有的属性,一般获取对象的属性传统的写法是:对象.成员变量,而在反射这里是反的,是:成员变量对象.get(对象)。代码示例:
Field nameField = cls.getField("name")
name = nameField.get(object)
cls.getDeclaredFields();
5. 类方法
cls.getMethods();
cls.getDeclaredMethods();
6. 类构造器
cls.getConstructors();
7. 标注信息
cls.getAnnotations();
8. 是否为基本类型数据
cls.isPrimitive();
9. 获得系统类的
getClassLoader();
这个也较为常用,加载类的时候
2)Method :
1.返回类型 method.getReturnType();
2.参数类型 method.getParameterTypes();
3.名字 method.getName();
4.修饰符 method.getModifiers();
5.标注 method.getAnnotations();
6.反射调用方法 method.invoke(obj, args);也是最为关键的一个方法
tips:1.eclipse里,public static void main(String[] args)这种固定话术可以之间打main然后alt+/即可自动补全。2. 同一个字节码文件(.class)在一次程序运行过程中,只会被加载一次,不论通过哪种方法(以上共三种)获取的class对象,都是同一个,共用同样内存单元。