反射的定义
反射是指在程序运行期间,能够观察和修改类或者类的对象的属性和行为的特性
反射机制可以获取的功能
- 在运行时获取类的修饰符,包名,类名,实现的接口,继承的父类
- 在运行时获取类的所有属性名,修饰符,属性类型
- 在运行时获取所有方法,方法的返回值类型,方法名,方法参数数量,方法参数类型
- 在运行时调用加载类的方法
这里不多说直接看代码
//class类:不同的字节码信息,我们发现有共同的特点,所以可以看做是同一个类下的不同对象。我们将它进行向上抽取的类:Class类 //获取Class类的对象(一共三种方式), 获取字节码信息 //方式1:getClass() Student s1=new Student(); Class c1 = s1.getClass();//方式2 Class c3=Student.class; //方式1、2两种方式很少调用 //方式3 Class c5=Class.forName("Lx1.Student");
//已经可以获取类的字节码信息 System.out.println("类的全称:"+c5.getName()); System.out.println("类的简称:"+c5.getSimpleName()); System.out.println("类的修饰符:"+c5.getModifiers()); //类的修饰符:17对应的数字 去Modifier类中查找 将16进制转为十进制 System.out.println("显示看修饰符"+Modifier.toString(c5.getModifiers())); //查看父类 System.out.println(c5.getSuperclass().getName());
System.out.println("该类实现的接口有:");
Class[] classes = clazz.getInterfaces();
for (Class class1 : classes) { //Class:数组元素的类型 class1:数组中的每个元素 : classes要遍历的数组
System.out.print(class1.getSimpleName()+",");
Class c1=Class.forName("Lx2.Student"); //c1 Student字节码信息 //可以创建对象 newInstance() 调用的是public修饰的空构造器 c1.newInstance(); //没有空构造器 会有异常 //构造器私有 也会报异常 //获取构造器 private修饰的构造器这种方式获取不到
//获取指定的构造器 //获取指定的空构造器 Constructor con2=c1.getConstructor(); System.out.println(con2); //获取四个参数的构造器 注意参数类型是class System.out.println("***************"); Constructor con3=c1.getConstructor(double.class,double.class,int.class,char.class);
con3.setAccessible(true);//解除private障碍
Object o3 = con4.newInstance(1.6,2.8,19,'女');
System.out.println(o3);
//获取所有方法 包括父类 Method[] ms = c1.getMethods(); for (Method m : ms) { System.out.println(m); } System.out.println("方法的个数:"+ms.length); //获取Student全部方法 System.out.println("----------"); Method[] ds = c1.getDeclaredMethods(); for (Method m : ds) { System.out.println(m); } System.out.println("方法的个数:"+ds.length); //获取指定的方法 Method m1=c1.getMethod("toString"); System.out.println(m1); System.out.println("方法的名字:"+m1.getName()); System.out.println("方法的修饰符:"+Modifier.toString(m1.getModifiers())); System.out.println("方法的返回值类型:"+m1.getReturnType().getSimpleName()); System.out.println("方法的参数:"+Arrays.toString(m1.getParameterTypes())); System.out.println("-------------------------"); Method m2=c1.getMethod("setClassid",int.class); System.out.println(m2); System.out.println("方法的名字:"+m2.getName()); System.out.println("方法的修饰符:"+Modifier.toString(m2.getModifiers())); System.out.println("方法的返回值类型:"+m2.getReturnType().getSimpleName()); System.out.println("方法的参数:"+Arrays.toString(m2.getParameterTypes())); //执行方法 Student s=(Student)c1.newInstance(); System.out.println(m1.invoke(s));
//获取所有成员变量 public static void getFields(Class clazz) throws Exception{ //单数和复数形式的方法 getField getDeclaredField(单个) 加s获取所有 // getField获取非私有字段 getDecalredField操作私有 Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { System.out.println(Modifier.toString(field.getModifiers())+" " +field.getType().getSimpleName()+" "+field.getName()); } Field field = clazz.getDeclaredField("age"); //与通过new关键字创建的实例对象一样 Object obj = clazz.newInstance(); //屏蔽字段的私有特性 field.setAccessible(true); field.set(obj, 16); Student stu=(Student)obj; System.out.println(stu.getAge()); }
//反射获得注解 public static void getAnnotation(Class clazz) throws Exception{ StudentAnnotation annotation =(StudentAnnotation)clazz.getAnnotation(StudentAnnotation.class); System.out.println("学生类:"+annotation.studentname()+",学号:"+annotation.studentNo()); StudentAnnotation annotation2 = clazz.getDeclaredField("stuname").getAnnotation(StudentAnnotation.class); System.out.println("学生姓名字段:"+annotation2.studentname()+",学号:"+annotation2.studentNo()); StudentAnnotation annotation3=clazz.getDeclaredMethod("talk").getAnnotation(StudentAnnotation.class); System.out.println("自我介绍方法:"+annotation3.studentname()+",学号:"+annotation3.studentNo()); }
//自定义注解
//在Java中的任何一个注解都离不开JDK的四个原注解
//1.@Target(当前注解的使用范围) 2.@Documented(API的帮助文档) 3.@Retention(注解类型) 4.@inherited(继承)
@Target({ElementType.METHOD,ElementType.FIELD,ElementType.TYPE}) @Documented @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface StudentAnnotation { String studentname(); String studentNo(); }
//可以这样使用
@StudentAnnotation(studentname="张三",studentNo="00001")
总结:
将类结构转换为Class类的实例可以用的方法
- 类名.class
- new 类名.getClass()
- Class.forName(String className)
获取指定类继承的父类包括实现的接口
变量名.getSuperclass().getSimpleName()//获取父类的简单名称
变量名.getInterfaces()//获取所有接口
获取访问修饰符
Modifier.toString(变量名.getModifiers())
获取所有成员变量
getField(String name)//获取单个成员变量(只能获取到非私有的)
getFields()//获取所有成员变量(只能获取到非私有的)
getDeclaredFields()//获取所有成员变量(都可以获取包括private)
getDeclaredField()//获取单个成员变量(都可以获取包括private)
newInstance()//与通过new关键字创建的实例对象一样
setAccessible(true)//屏蔽字段私有性
getType().getSimpleName()//获取简单的变量类型
获取所有成员方法
getMethods()//所有的方法,包括父类
getMethods()//获取单个方法,括号里面传的是不定长参数
getDeclaredMethods()//获取当前类的所有方法,不包含父类
getDeclaredMethod()//获取当前类的单个方法,括号里面传的是不定长参数
getParameterTypes()//获取方法的参数
getReturnType()//返回值类型
invoke()//执行方法
获取构造函数
getConstructor()//获取指定参数的构造函数,括号里传的是不定长参数,类型后面不要忘记加class
constructor.newInstance()//给获取到的单个构造函数赋值
getConstructors()//获取所有的构造函数
获取自定义注解
getAnnotation(自定义注解.class)//获得class注解,括号里面传的是自定义注解,注意不要忘记加class
getDeclaredField(成员变量).getAnnotation(自定义注解.class)//获得成员变量的自定义注解
getDeclaredMethod(成员方法).getAnnotation(自定义注解.class)//获得方法的自定义注解