详解java反射机制

定义:

  1. 在java反射过程中给定一个类对象(Class对象),通过反射可以获取该对象的所有成员结构和类结构。
  2. 给定一个对象,通过反射可以动态调用他的方法以及任意属性值得获取和赋值。静态成员变量和方法不需要给定对象。
  3. 这种动态获取类的内容、创建对象以及动态调用对象的方法及操作属性的机制称为反射。

优势:

  1. 增加程序的灵活性,避免将程序逻辑写死在代码里面。
  2. 代码简洁,可读性,提高代码复用率。

劣势:

  1. 比直接调用性能要低。
  2. 存在一些内部暴露和安全隐患。

与反射有关的主要的类:

  1. java.lang.Class //java的类字节码对象,java的每个类都有一个该对象。是对java类的描述。
  2. java.lang.reflect.Constructor。//java对类构造器的描述。
  3. java.lang.reflect.Method。 //对java方法的描述。
  4. java.lang.reflect.Field。 //对java成员的描述。
获取Class实例的4种方法:
  1. 已经知道具体的类:比如:String.class;
  2. 使用类的某个对象获取:object.getClass();
  3. 使用Class类的静态方法:Class.forName(“java.lang.String”);
    该方法有重载:Class.forName(String name//类的全路径,boolean initialize//是否初始化,ClassLoader loader//类加载器)。
  4. 通过类加载器加载类:classLoad.loadClass(String name//类全路径);
Class类的方法:
//判断cls对象的类是不是clazz对象的类的子类,是就返回true,复制返回false。
boolean isAssignableFrom = clazz.isAssignableFrom(Class cls); 

boolean isInstance = clazz.isInstance(Class cls) ;

//获取类的修饰符返回是一个int类型,具体每种修饰符的int值请查看java.lang.reflect.Modifier类。
//比如public是0x00000001 也就是1。static 是0x00000008 也就是8。
//组合就要相加 比如 public static  是9。
int Modifiers = clazz.getModifiers(); 

//判断该类是不是接口。
boolean isInterface = clazz.isInterface(); 

//判断是不是数组
boolean isArray = clazz.isArray();

//判断是不是八大基本类型的Class对象,比如int.class就为true,Integer.class就为false。
boolean isPrimitive = clazz.isPrimitive();

//获取他的父类的Class对象。接口类对象和八大基本类型类对象还有Object类对象调用返回null值。
Class superclass = clazz.getSuperclass();

//获取该类的全限定名称。
String name = clazz.getName();

//获取类或者父类上的指定注解,参数是指定获得注解的class类对象。如果不存在就返回null。
Annotation annotation = clazz.getAnnotation(Class clazz);

//获取该类上所有的注解。包括父类(父类的父类...以此类推)的注解(该注解要可以继承,也就是该注解要被@Inherited元注解修饰)
Annotation[] annotations = clazz.getAnnotations();

//获取该类上的指定注解,不包括父类。
Annotation annotation = clazz.getDeclaredAnnotation(Class clazz);

//获取该类上的所有注解,不包括父类。
Annotation[] annotations = clazz.getDeclaredAnnotations();

//获取全限定名称
String canonicalName = clazz.getCanonicalName();

//获取加载该类的类加载器。
ClassLoader classLoader = clazz.getClassLoader();

//获取这个类的公有的内部类,包括父类(父类的父类...以此类推)的公有内部类
Class[] clazzs = clazz.getClasses();

//获取该类所有的内部类,不包括父类。
Class[] clazzs = clazz.getDeclaredClasses();


//获取该类的指定公有构造器,根据参数列表指定。
Constructor constructor = clazz.getConstructor(Class[] clazzs//参数列表);

//获取该类所有公有构造器。因为构造器不能继承,所以获取不到父类的构造器。
Constructor[] constructors = clazz.getConstructors(); 

//获取该类的指定构造器,根据参数列表指定。
Constructor constructor = clazz.getDeclaredConstructor(Class[] clazzs//参数列表);

//获取该类的所有构造器
Constructor[] constructors = clazz.getDeclaredConstructors(); 

//获取该类的成员指定成员变量,参数是变量名。不包括父类。
Field field = clazz.getDeclaredField(String name);

//获取该类的所有成员变量。不包括父类
Field fields = clazz.getDeclaredFields();

//获取指定的公有成员变量,包括父类(父类的父类...以此类推)的。
Field field = clazz.getField(String name);

//获取该类所有的公有成员变量,包括父类(父类的父类...以此类推)的。
Field fields = clazz.getFields();

//获取该类的指定方法,name是方法名,clazzs是参数列表。不包括父类。
Method method = clazz.getDeclaredMethod(String name,Class[] clazzs);

//获取该类的所有方法,不包括父类。
Method[] methods = clazz.getDeclaredMethods();

//获取该类的指定公有方法,name是方法名,clazzs是参数列表。包括父类(父类的父类..,以此类推)。
Method method = clazz.getMethod(String name,Class[] clazzs);

//获取该类的所有公有方法,包括父类(父类的父类..,以此类推)。
Method[] methods = clazz.getMethods();

//获取该内部类的外部类,如果不是内部类,就返回null。
Class cla = clazz.getEnclosingClass();

//获取该枚举类的全部实例。如果不是枚举返回空数组。
Object[] enums = clazz.getEnumConstants();

//获取该类实现的所有接口。仅仅是该类。
Class[] interfaces = clazz.getInterfaces();

//获取定义改类的包。
Package package = clazz.getPackage();

//动态获取文件的全路径URL,这个要写一篇新的来讲。
URL url = clazz.getResource(String name);

//获取文件的全路径并生成输入流。
InputStream in = clazz.getResourceAsStream(String name);

//该类是不是注解
boolean isAnnotation = clazz.isAnnotation(); 

//该类上是否有注解clazz
boolean isAnnotationPresent= clazz.isAnnotationPresent(Class clazz); 

//该类是不是枚举类
boolean isEnum= clazz.isEnum(); 

//创建对象 使用的是默认构造器创建。
Object obj = clazz.newInstance();
构造器类方法:
//获取该构造器的修饰符。
int Modifiers = constructor.getModifiers(); 

//获取该构造器的全限定名。
String name = constructor.getName();

//获取该构造器上指定的注解,因为构造器不能继承,所以不包括父类的。
Annotation annotation = constructor.getAnnotation(Class clazz);

//获取该构造器的所有注解,因为构造器不能继承,所以不包括父类的。
Annotation[] annotations = constructor.getDeclaredAnnotations();

//获取定义该构造器的类。
Class clazz = constructor.getDeclaringClass();

//获取该构造器的参数列表
Class[] clazz = constructor.getParameterTypes();

//创建对象。参数objs是要传到构造器的参数。
Object obj = constructor(Object[] objs);

//获取构造器的全名称,比如 public com.fanshe.demo.A(int,String)
String genericStringName = constructor.toGenericString();

//获取构造器的参数上的注解,这是一个二维数组,一维是参数,二维是参数上的注解。
Annotation[][] annotations = constructor.getParameterAnnotations();

//获取该构造器的参数个数。
int paramCount = constructor.getParameterCount();

//判断该构造器是否具有可变参数。
boolean isVarArgs = constructor.isVarArgs();

//获取该构造器抛出的异常。
Class[] exceptions = constructor.getExceptionTypes();

//获取该构造器上指定的注解。
Annotation[] annotation = constructor.getAnnotationsByType(Class clazz);

//获取该构造器上的所有注解,因为构造器不能继承,所有不包括父类。
Annotation[] annotations = constructor.getAnnotations();

//获取该构造器上指定注解。
Annotation annotation = constructor.getDeclaredAnnotation(Class clazz);

//获取该构造器上是否有指定注解
boolean isAnnotationPresent = constructor.isAnnotationPresent(Class clazz);

//判断该构造器是否关闭了安全访问检查,而不是是否可以访问。
//如果返回false则表示该构造器开启了安全访问检查,返回true则表示关闭了安全访问检查,
//关闭安全访问检查可以提高一定的反射效率。
boolean isAccessible = constructor.isAccessible();

//是否关闭安全访问检查,而不是设置是否可以访问,flag为true时就关闭安全访问检查,为false时就开启。默认开启。
constructor.setAccessible(boolean flag);
Field相关的方法:
//获取该成员变量的值,参数obj1是这个成员变量值所属的对象。
//如果该字段是静态成员变量,则obj1可以等于null。
Object obj = field.get(Object obj1)

//获取该成员变量的修饰符
int modifiers = field.getModifiers();

//获取成员变量的变量名称。
String name = field.getName();

//获取该成员变量上指定的注解。如果父类的成员变量被子类重写了,父类该成员变量上的注解不会继承到子类上。
Annotation annotation = field.getAnnotation(Class clazz);

//获取该成员变量上的所有注解。
Annotation[] annotations = field.getDeclaredAnnotations();

//获取该成员变量定义的类。
Class clazz = field.getDeclaringClass();

//获取该成员变量的详细名称:比如 public java.lang.String fanshe.entries.Person.email
String genericString = field.toGenericString();

//获取成员变量的类型。
Class clazz =  field.getType();

//判断该成员变量是不是枚举类型。
boolean isEnumConstant = field.isEnumConstant();

//为该成员变量设置值,obj是成员变量所属的对象,value是要设置的值。
//如果该成员变量是静态变量,则obj可以为null。
field.set(Object obj,Object value);

//获取该成员变量上的所有注解。
Annotation[] annotation = field.getAnnotations();

//获取该成员变量上的指定注解
Annnotation annotation = field.getDeclaredAnnotation(Class clazz);

//判断该成员变量上是否存在注解annotationClass.
boolean isAnnotationPresent = field.isAnnotationPresent(Class annotationClass);

//判断该成员变量是否关闭了安全访问检查,而不是是否可以访问。
//如果返回false则表示该成员变量开启了安全访问检查,返回true则表示关闭了安全访问检查,
//关闭安全访问检查可以提高一定的反射效率。
boolean isAccessible = field.isAccessible();

//设置是否关闭安全检查,true就关闭,false就开启。
field.setAccessible(boolean flag);
Method相关方法:
//调用该方法,obj1是该方法的对象,如果是静态方法,则obj1可以为null,params是调用该方法的参数。
Object obj = method.invoke(Object obj1,Object[] params);

//获取该方法的修饰符。
int modifiers = method.getModifiers();

//获取该方法的名字,仅仅是名字,比如 getName。
String name = method.getName();

//获取该方法上的指定注解。方法上的注解不能在父子类之间继承。
Annotation annotation = method.getAnnotation(Class clazz);

//获取该方法上的所有注解
Annotation[] annotations = method.getDeclaredAnnotations();

//获取该方法定义的类。
Class clazz = method.getDeclaringClass();

//获取该方法的参数类型列表
Class[] clazzs = method.getParameterTypes();

//获取该方法的返回值类型。
Class clazz = method.getReturnType();

//判断该方法是不是被default修饰的方法,jdk1.8以后可以在接口中定义实现用default关键字修饰的方法。
boolean isDefault = method.isDefault();

//获取该方法的详细签名。比如:public void fanshe.entries.Teacher.sayHello(java.lang.String)
String genericString = method.toGenericString();

//获取该方法的参数上的注解,是一个二维数组,一维是参数,二维是参数上的注解。
Annotation[][] annotations = method.getParameterAnnotations();

//获取该方法的参数个数。
int paramCount = method.getParameterCount();

//判断该方式是否有可变参数。
boolean isVarArgs = method.isVarArgs();

//获取该方法抛出的异常类型列表,异常不会在父子类之间继承
Class[] clazzs = method.getExceptionTypes();

//获取该方法上的指定注解。
Annotation annotation = method.getDeclaredAnnotation(Class clazz);

//获取该方法上的所有注解
Annotation[] annotations = method.getAnnotations();

//判断该方法上是否存在注解annotationClass.
boolean isAnnotationPresent = method.isAnnotationPresent(Class annotationClass);

//判断该方法是否关闭了安全访问检查,而不是是否可以访问。
//如果返回false则表示该方法开启了安全访问检查,返回true则表示关闭了安全访问检查,
//关闭安全访问检查可以提高一定的反射效率。
boolean isAccessible = method.isAccessible();

//设置是否关闭安全检查,true就关闭,false就开启。
method.setAccessible(boolean flag);
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Java反射机制是指在运行时动态地获取一个类的信息,并可以操作类的属性、方法和构造器等。Java反射机制可以使程序员在运行时动态地调用类的方法和属性,扩展类的功能,并可以实现注解、工厂模式以及框架开发等。 Java反射机制的原理如下:首先,Java编译器将Java源代码编译为字节码文件,字节码文件中包含着类的信息,这些信息包括类的名称、方法、属性和构造器等等。接着,Java虚拟机将字节码文件加载到内存中,然后通过类加载器将类加载到内存中形成一个类对象,这个类对象可以操作字节码文件中的信息。 使用Java反射机制的过程如下:首先获取类对象,通过类对象来获取类的构造器、属性、方法等信息,然后调用构造器来创建对象,通过属性获取和设置类的成员属性,通过方法调用类的方法等。 Java反射机制的优点是可以在运行时动态地得到类的信息,使得程序员在程序运行时能够对类进行更加灵活的操作,并可以使得程序更加通用化,同时也存在着一定的性能问题,因为Java反射机制需要Java虚拟机进行一定的额外处理,所以在程序运行时需要进行额外的时间和资源消耗。 总之,Java反射机制Java语言的一项重要特性,在Java开发中广泛应用,在代码编写、框架开发以及API开发中具有重要作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值