1、反射
1、反射是什么
能够分析类能力的程序称为反射。反射可以让用户编写动态操纵Java代码的程序,动态即程序运行时
2、反射是如何实现的
在JVM的组成中,有一个叫做方法区的地方,方法区中存放着类的信息,反射通过这里获取类信息。虚拟机为每个类管理一个唯一的Class对象
3、为什么需要反射
思考一下,很多时候,在编译期间,我们并不知道某一具体的类,而需要等到程序运行时才获取到类信息,将类加载到类加载器中,比如Dubbo的自适应拓展机制,利用Javassist生成代理类,用类加载器加载代理类后,用反射获取类信息,这提现了用反射在运行期间操纵程序
4、反射的常用场景
- JDK的动态代理
- 热加载机制
5、反射的缺点
- 反射通常慢于正常编写的代码
- 反射会让编译时类型检查失效
- 使用反射需要提前将类加载到方法区中,如果加载的类过多,可能造成方法区OOM
2、简单使用
假设有如下一个Test类
public class Test {
private int age = 24;
private String name = "朱";
public Test() {
}
public Test(int age, String name) {
this.age = age;
this.name = name;
}
public int test (String str) {
return 123;
}
}
1、Field
描述类的字段,通过它可以获取类中字段的信息,比如字段的名字、类型、修饰符等
打印类中的Field信息
public static void printFields(Class<?> cl) {
Field[] fields = cl.getDeclaredFields();
for (Field f : fields) {
Class<?> type = f.getType();
String name = f.getName();
String modifiers = Modifier.toString(f.getModifiers());
System.err.println(modifiers + " " + type.getName() + " " + name + ";");
}
}
最终输出为
private int age;
private java.lang.String name;
2、Method
描述类的方法,Method中包含着当前方法的所有信息,如修饰符,返回类型,方法参数类型
打印类中的方法信息
public static void printMethods(Class<?> cl) {
Method[] methods = cl.getDeclaredMethods();
for (Method m : methods) {
String name = m.getName();
Class<?> returnType = m.getReturnType();
String modifiers = Modifier.toString(m.getModifiers());
System.err.print(modifiers + " " + returnType.getName() + " " + name + " ");
Class<?>[] parameterTypes = m.getParameterTypes();
for (Class<?> c : parameterTypes) {
System.err.print(c.getName() + ",");
}
System.err.println();
}
}
最终输出为
public java.lang.String test java.lang.String,int,
3、Constructors
描述类的构造器,可以获取构造器的相关信息
打印类中构造器信息
public static void printConstructors(Class<?> cl) {
Constructor<?>[] constructors = cl.getConstructors();
for (Constructor<?> c : constructors) {
String name = c.getName();
System.err.print(Modifier.toString(c.getModifiers()) + " " + name + " ");
Class<?>[] parameterTypes = c.getParameterTypes();
for (Class<?> parameter : parameterTypes) {
System.err.print(parameter.getName() + ",");
}
System.err.println();
}
}
最终输出为
public com.example.demo.Test
public com.example.demo.Test int,java.lang.String,