定义
反射就是根据类的字节码文件,反射类的基本信息,类的成员(字段、方法、构造方法)等内容,动态的创建对象,调用方法的技术。即在运行状态中,对于任意一个类都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性。
反射依赖于class对象。
作用
通过反射,Java代码可以发现有关已知加载类的字段、方法和构造函数的信息,并可以在安全限制内对这些字段、方法和构造函数进行操作。
优缺点
优点
使用反射机制,代码可以在运行时装配,提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需硬编码目标类
缺点
性能问题:使用反射基本上是一种解释操作,JVM无法对这些代码进行优化,因此,反射操作的效率要比那些非反射操作低得多。反射机制主要应用在对灵活性和扩展性要求很高的系统框架上,对性能要求高的程序中不建议使用
安全限制:使用反射技术要求程序必须在一个没有安全限制的环境中运行
内部暴露:由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用——代码有功能上的错误,降低可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化。
反射机制的相关类
与Java反射相关的类如下:
类名 | 用途 |
---|---|
Class类 | 代表类的实体,在运行的Java应用程序中表示类和接口 |
Field类 | 代表类的成员变量(成员变量也称为类的属性) |
Method类 | 代表类的方法 |
Constructor类 | 代表类的构造方法 |
Class类
Class代表类的实体,在运行的Java应用程序中表示类和接口。在这个类中提供了很多有用的方法,这里对他们简单的分类介绍。
获得类相关的方法
方法 | 用途 |
---|---|
asSubclass(Class clazz) | 把传递的类的对象转换成代表其子类的对象 |
Cast | 把对象转换成代表类或是接口的对象 |
getClassLoader() | 获得类的加载器 |
getClasses() | 返回一个数组,数组中包含该类中所有公共类和接口类的对象 |
getDeclaredClasses() | 返回一个数组,数组中包含该类中所有类和接口类的对象 |
forName(String className) | 根据类名返回类的对象 |
getName() | 获得类的完整路径名字 |
newInstance() | 创建类的实例 |
getPackage() | 获得类的包 |
getSimpleName() | 获得类的名字 |
getSuperclass() | 获得当前类继承的父类的名字 |
getInterfaces() | 获得当前类实现的类或是接口 |
获得类中属性相关的方法
方法 | 用途 |
---|---|
getField(String name) | 返回该类中与参数类型匹配的公有注解对象 |
getFields() | 获得所有公有的属性对象 |
getDeclaredField(String name) | 获得某个属性对象 |
getDeclaredFields() | 获得所有属性对象 |
获得类中注解相关的方法
方法 | 用途 |
---|---|
getAnnotation(Class annotationClass) | 返回该类中与参数类型匹配的公有注解对象 |
getAnnotations() | 返回该类所有的公有注解对象 |
getDeclaredAnnotation(Class annotationClass) | 返回该类中与参数类型匹配的所有注解对象 |
getDeclaredAnnotations() | 返回该类所有的注解对象 |
获得类中构造器相关的方法
方法 | 用途 |
---|---|
getConstructor(Class…<?> parameterTypes) | 获得该类中与参数类型匹配的公有构造方法 |
getConstructors() | 获得该类的所有公有构造方法 |
getDeclaredConstructor(Class…<?> parameterTypes) | 设获得该类中与参数类型匹配的构造方法 |
getDeclaredConstructors() | 获得该类所有构造方法 |
获得类中方法相关的方法
方法 | 用途 |
---|---|
getMethod(String name, Class…<?> parameterTypes) | 获得该类某个公有的方法 |
getMethods() | 获得该类所有公有的方法 |
getDeclaredMethod(String name, Class…<?> parameterTypes) | 获得该类某个方法 |
getDeclaredMethods() | 获得该类所有方法 |
类中其他重要的方法
方法 | 用途 |
---|---|
isAnnotation() | 如果是注解类型则返回true |
isAnnotationPresent(Class<? extends Annotation> annotationClass) | 如果是指定类型注解类型则返回true |
isAnonymousClass() | 如果是匿名类则返回true |
isArray() | 如果是一个数组类则返回true |
isEnum() | 如果是枚举类则返回true |
isInstance(Object obj) | 如果obj是该类的实例则返回true |
isInterface() | 如果是接口类则返回true |
isLocalClass() | 如果是局部类则返回true |
isMemberClass() | 如果是内部类则返回true |
Field类
Field代表类的成员变量(成员变量也称为类的属性)。
方法 | 用途 |
---|---|
equals(Object obj) | 属性与obj相等则返回true |
get(Object obj) | 获得obj中对应的属性值 |
set(Object obj, Object value) | 设置obj中对应属性值 |
Method类
Method代表类的方法。
方法 | 用途 |
---|---|
invoke(Object obj, Object… args)) | 传递object对象及参数调用该对象对应的方法 |
Constructor类
Constructor代表类的构造方法。
方法 | 用途 |
---|---|
newInstance(Object… initargs) | 根据传递的参数创建类的对象 |
示例
如何获得类的class对象?
1)从Object类继承的getClass()方法,返回对象的运行时类对象;
2)每个类都有一个class属性,代表当前类的运行时类对象;
3)Class类静态方法forName(完整类名)返回指定类名的运行时类对象。public class lesson1 { public static void main(String[] args) throws ClassNotFoundException { //1)gerClass() Person p1 = new Person(); Class<?> class1 = p1.getClass(); //2)class属性 Class<?> class2 = Person.class; //3)Class.forName() Class<?> class3 = Class.forName("sdasds"); //4)基本类型 Class<?> class4 = int.class; Class<?> class5 = Integer.class; //5)Class.forName()会把类加载到内存中 Class<?> class6 = Dog.class;//没有执行Dog类的静态代码块,说明Dog没有加载内存 Class<?> class7 = Class.forName("dads");//执行了静态代码块说明Dog加载内存 } } class Person{} class Dog{ static { System.out.println("静态代码块,类加载内存后,在使用前要进行类的初始化操作,这时执行静态代码块"); } }
反射类的信息
public class lesson2 {
public static void main(String[] args) {
Class<?> class1 = String.class;
//反射类的信息
//类的修饰符
int mod = class1.getModifiers();
String moString = Modifier.toString(mod);
System.out.println(moString);
//类名
System.out.println("class");
System.out.println(class1.getName());//完整类名
System.out.println(class1.getSimpleName());//简易类名
//父类
Class<?> superClass = class1.getSuperclass();
if(superClass != Object.class) {
System.out.println("extends");
System.out.println(superClass.getSimpleName());
}
//接口
Class<?>[] interfacesClass = class1.getInterfaces();
if (interfacesClass.length > 0) {
System.out.println("implements");
for (int i = 0; i < interfacesClass.length; i++) {
System.out.println(interfacesClass[i].getSimpleName());
if(i < interfacesClass.length - 1) {
System.out.println(",");
}
}
}
}
}
反射类的成员
字段:
Class<?> class1 = String.class;
StringBuilder sb = new StringBuilder();
//返回所有字段
Field[] decFields = class1.getDeclaredFields();
for (Field field : decFields) {
//字段修饰符
int mod = field.getModifiers();
sb.append(Modifier.toString(mod));
sb.append("");
//类型
Class<?> typeClass = field.getType();
sb.append(typeClass.getSimpleName());
sb.append("");
//名称
sb.append(field.getName());
sb.append("\n");
}
System.out.println(sb.toString());
方法:
Class<?> class1 = String.class;
StringBuilder sb = new StringBuilder();
Method[] declareMethods = class1.getDeclaredMethods();
for (Method method : declareMethods) {
//方法修饰符
int mod = method.getModifiers();
sb.append(Modifier.toString(mod));
sb.append("");
//方法返回值类型
Class<?> returnType = method.getReturnType();
sb.append(returnType.getSimpleName());
sb.append("");
//方法名
sb.append(method.getName());
//方法参数
sb.append("(");
Class<?>[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
sb.append(parameterTypes[i].getSimpleName());
if (i < parameterTypes.length - 1) {
sb.append(",");
}
}
sb.append(")\n");
}
System.out.println(sb.toString());
构造方法:
Class<?> class1 = String.class;
StringBuilder sb = new StringBuilder();
Constructor<?>[] declaredConstructors = class1.getDeclaredConstructors();
for (Constructor<?> constructor : declaredConstructors) {
//修饰符
sb.append(Modifier.toString(constructor.getModifiers()));
sb .append(" ");
//方法名
//sb.append(constructor.getName());//完整类名
sb.append(class1.getSimpleName());
//参数
sb.append("(");
Class<?>[] parameterTypes = constructor.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
sb.append(parameterTypes[i].getSimpleName());
if (i < parameterTypes.length - 1) {
sb.append(",");
}
}
sb.append(")\n");
}
System.out.println(sb.toString());