反射与内省
一、反射
1、反射的概念与应用
概念:动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制。
作用:动态获取类的信息,进一步实现需要的功能 eg:Spring框架通过XML文件描述类的基本信息,使用反射机制动态装配对象。
2、Class类
public static void main(String[] args) throws ClassNotFoundException {
//获取Class类 方式一
// Class class1 = String.class;
Class class1 = Person.class;
//获取Class类 方式二
// Class class2 = Class.forName(“java.lang.String”);
// Class class2 = Class.forName(“com.icss.javaseday17.threads.Person”);
//获取Class类 方式三
String str = "tec";
Person person = new Person();
Class class3 = person.getClass();
//获取所有方法并且遍历
Method[] methods = class3.getMethods(); //获取所有公有方法
for (Method method : methods) {
System.out.println(method.getName()); //获取方法名字
}
// Field[] fields = class3.getFields(); //获取所有的公有属性
// for (Field field : fields) {
// System.out.println(field);
// }
// Field[] fields = class3.getDeclaredFields(); //获取所有属性
// for (Field field : fields) {
// System.out.println(field);
// }
//获取所有公有的构造方法
// Constructor[] constructors = class3.getConstructors();
// for (Constructor constructor : constructors) {
// System.out.println(constructor.getName()); //获得类的完整名字
// }
System.out.println(class3.getPackage().getName()); //获取包名
}
3、Constructor类
getName:返回构造方法的名字
getParameterTypes:返回构造方法的参数类型
Constructor getConstructor(Class… parameterTypes) :通过指定参数类型,返回构造方法实例。
Constructor[] getConstructors() :返回该类的所有构造方法实例。newInstance(Object… initargs) :创建实例。
//获取Class类对象
Class class1 = Class.forName(“com.icss.javaseday17.threads.Person”);
//获得Person类的构造方法实例
Constructor constructor = class1.getConstructor(String.class);
//使用构造方法的实例创建Person对象
Person person = (Person)constructor.newInstance(“gx”);
System.out.println(person);
4、Method类
getReturnType:获得方法返回值类型
getName:获得方法名字
getParameterTypes:获得方法参数类型
invoke(Object obj, Object… args) :使用obj调用该方法,参数为args
Method getMethod(String name, Class… parameterTypes) :通过指定方法名,参数类型,返回一个Method实例。
Method[] getMethods() :返回该类中所有方法的Method实例。
public static void main(String[] args) throws Exception {
// 获取Class类对象
Class class1 = Class.forName(“com.icss.javaseday17.threads.Person”);
// 通过Class实例获得无参构造方法实例
Constructor constructor = class1.getConstructor(null);
//通过无参构造方法实例,创建对象
Person person = (Person)constructor.newInstance(null);
//通过Class实例获得方法实例
Method[] methods = class1.getMethods();
//遍历方法
for (Method method : methods) {
//判断方法名是以setName开头的
if (method.getName().startsWith("setName")) {
method.invoke(person, "alice"); //调用方法
}
//判断方法名是以setAge开头的
if (method.getName().startsWith("setAge")) {
method.invoke(person, 18); //调用方法
}
}
System.out.println(person);
}
5、Field类
getName:返回属性的名字
getXXX:例如,getFloat返回该属性float类型的值
setXXX:例如,setFloat为属性赋值float类型的值
public Field getField(String name):通过指定Field名字,返回Field实例
6、class类加载器
(1)什么是类加载器
类加载器负责加载 Java 类的字节代码到 Java 虚拟机中(加载到内存并且生成字节码对象Class);
Java 虚拟机使用 Java 类的方式:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class 文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例;反射的用武之地是对Class对象在运行结果之前进行动态的修改。
(2)在哪个环节可以修改运行结果?
1.直接修改源文件
2.通过反射来操作Class字节码对象
(3)类加载器分为两种:一种是系统的,一种是开发人员编写的
系统提供三类:
bootstrap class loader:引导类加载器,它用来加载 Java 的核心库,jre/lib/rt.jar
extensions class loader:扩展类加载器,它用来加载 Java 的扩展库。jre/lib/ext/*.jar
system class loader:系统类加载器,它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。三方jar包和自己编写的java文件。
(4)委托机制
类加载器在尝试去查找某个类的字节代码并定义它时,会先委托给其父类加载器,由父类加载器先去尝试加载这个类,依次类推,称为委托机制,也称为代理模式;
注意:委托并不是加载器之间存在继承关系,只是进行委托;
(5)怎么获得类加载器
ClassLoader 字节码对象.getClassLoader();
二、内省