反射的定义

反射是指在程序运行期间,能够观察和修改类或者类的对象的属性和行为的特性

反射机制可以获取的功能

  • 在运行时获取类的修饰符,包名,类名,实现的接口,继承的父类
  • 在运行时获取类的所有属性名,修饰符,属性类型
  • 在运行时获取所有方法,方法的返回值类型,方法名,方法参数数量,方法参数类型
  • 在运行时调用加载类的方法

这里不多说直接看代码

//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类的实例可以用的方法

  1. 类名.class
  2. new 类名.getClass()
  3. 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)//获得方法的自定义注解

 

posted on 2019-06-19 16:47  灰色...天空  阅读(135)  评论(0编辑  收藏  举报