ClassUtils 反射实现 笔记一文尽知

来源:互联网 发布:excel2007数据库 编辑:程序博客网 时间:2024/06/03 08:47

Class 反射核心知识及动态代理一文尽知

一、反射的基本理解

1、概念:

       从对象  找  类(获取类类型)

2、好处

静态加载和动态加载    静态加载:           编译加载。 编译时 加载所有 出现的类,不管用得到还是用不到            如:通过new 创建对象方式  实现    动态加载(反射实现):          运行加载。运行时 才去加载 用到的类实现了动态加载,          比较适合  底层开发,在web,servlet中也用到

3、为什么用反射

场景1:       甲和乙  共同完成项目       甲  用到了 乙  写的类,但  乙没写完可以反射获取场景2: 代理模式之一个代理 用反射执执行多个被代理对象的代理操作       的是 静态加载

二、Class类的特点

1 Class本身也是一个类  java.lang.Class2 Class 对象只能由系统建立对象(通过三种方式创建Class类型的对象)3 一个类在 JVM 中只会有一个Class实例 4 一个Class对象对应的是一个加载到JVM中的一个.class文件5 每个类的实例都会记得自己是由哪个 Class 实例所生成6 通过Class可以完整地得到一个类中的完整结构 

三、[了解] 类的加载过程

一个类的完整加载过程:

  装载——链接——初始化——使用——卸载

1类的加载:

功能:     通过 类加载器 将.class文件 加载到内存中     对应生成一个Class类的对象问题:从哪里得到 .class文件?     <1> 本地系统     <2> 网络上     <3> zip中     <4> 特定数据库     <5> 动态编译什么时候会加载?★     <1> 使用new关键字,创建对象     <2> 调用静态的成员的时候     <3> 创建子类对象时,会随之加载 父类     <4> 使用反射,创建类的类类型      ☆  注意:只加载一次!!!

2、链接:

    校验    准备    解析

3、初始化:

  对类的静态成员或静态初始化块及静态方法进行初始化

四、反射用到的核心API

1.java.lang包下的Class类

Class    1、创建Class类的对象:                      方式一:类名.class                      方式二:Class.forName(全类名);                      方式三:对象.getClass()

三种方法获取类类型exa:

  `@Test   public void testGerClass() throws Exception{    //方式一 通过 类名.class 获取person的类类型/反射类    Class<Person> clazz=Person.class;    System.out.println("方式一   "+clazz);    //方式二 通过 对象.getclass() 获取Person类的类类型/反射类     Class clazz1=new Person().getClass();     System.out.println("方式二   "+clazz1);    //方式三  通过Class.forname(全类名) 获取Person类的类类型/反射类     Class clazz2=Class.forName("com.refelect.Person");     System.out.println("方式三   "+clazz2);}`   2、获取类的结构信息:       <1>方法信息            getMethods所有公共的方法,包含从父类继承的            getDeclaredMethods自定义的所有方法,不问修饰符            getMethod(方法名,参数列表) 获取所有公共方法的指定的方法            getDeclaredMethod(方法名,参数列表)获取指定方法(自定义的方法,不问修饰符)                              getFields所有公共的成员变量,包含从父类继承的            getDeclaredFields自定义的所有成员变量,不问修饰符            getField(属性名)            getDeclaredField(属性名)      <2>构造方法信息                getDeclaredConstructors()获取所有的构造方法,不问修饰符                getDeclaredConstructor(参数列表) 获取指定的构造方法            包                getPackage            类名称                getSimpleName            全类名                getName            所实现的接口                getInterfaces            父类                getSuperclass            注解                getAnnotations            父类的泛型                getGenericSuperclass                getGenericInterfaces

2、java.lang.reflect包下的一系列类

   Method  ……   Field   ……   Constructor ……   Modifier   Modifier.toString() 返回此修饰符的小写名称。

五反射的使用

1、创建对象        类中有无参            通过调用Class对象的 newInstance方法        类中没有无参            1. 获取指定构造方法            2. 通过调用构造方法对象的 newInstance2、调用非静态方法        步骤1: 获取类类型        步骤2.创建对象        步骤3:获取指定方法        步骤4:通过method.invoke()   调用该方法3、访问非静态成员变量        步骤1: 获取类类型        步骤2.创建对象        步骤3:获取指定成员变量        步骤4:通过field.set(对象,值)设置 成员变量值,通过field.get(对象)获取该属性值

六附代码解析

(一)提供封装了私有;公有构造;私有公有属性;私有公有方法;静态属性;静态方法……的Person类

`class Person{ private String name; public int age; private char sex; public double height; public Person() { } private Person(char sex){this.sex=sex;}public  Person(String name) {this.name = name;}public  Person(char sex,String name) {this.sex=sex;this.name = name; }public String getName() {return name;}public void setName(String name) {this.name = name; }  public void hello(){System.out.println("hello nice to meet you!!");}public void hello1(int age){System.out.println("my age is:"+age);}private void hello2(){System.out.println("我是私有空参方法hello3");}private void hello3(String name,int age ){System.out.println("我是:"+name+"私有有参方法age:"+age);}private static String helloWorld(int age){return "我是静态方法!年龄:"+age; }private static String helloWorld1(int age){return "我是非静态方法!年龄:"+age;} @Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + ", sex=" + sex        + ", height=" + height + "]";}}`

(二)、三种方法获取类类型

  `@Test   public void testGerClass() throws Exception{    //方式一 通过 类名.class 获取person的类类型/反射类    Class<Person> clazz=Person.class;    System.out.println("方式一   "+clazz);    //方式二 通过 对象.getclass() 获取Person类的类类型/反射类     Class clazz1=new Person().getClass();     System.out.println("方式二   "+clazz1);    //方式三  通过Class.forname(全类名) 获取Person类的类类型/反射类     Class clazz2=Class.forName("com.refelect.Person");     System.out.println("方式三   "+clazz2);}`

(三)、获取Person的类类型 并且获取所有方法信息

`@Testpublic void testGetMethods() {    // 通过方式三获取Person的类类型    Class clazz = null;    try {        clazz = Class.forName("com.refelect.Person");    } catch (ClassNotFoundException e) {        e.printStackTrace();    }    // 得到了Person的类类型以后进一步获取其所有的方法    // 获取其所有公共的方法,包含从父类继承过来的    Method[] methods = clazz.getMethods();    // 获取的是 本类中所有自定义的方法,不受权限修饰符限制    Method[] methods1 = clazz.getDeclaredMethods();    // 增强for循环遍历获取对应方法的权限修饰符    // 可以将methods换methods1测试获取的不同权限的方法    for (Method method : methods1) {        // 调用getModifiers获取其代表其对应修饰符的一个返回值为int 的值        int modifiers = method.getModifiers();        // 调用Modifier.toString()方法对获取的int值解码为对应String型修饰符        String modifier = Modifier.toString(modifiers);        // 获取对应方法的返回类型对象的类类型        Class<?> returntype = method.getReturnType();        String type = returntype.getSimpleName();        // 获取对应方法的方法名        String name = method.getName();        // 获取对应方法的参数(可能有多个)        Class<?>[] paramerterTypes = method.getParameterTypes();        // 定义paramertertype作为返回类型的拼接;        String paramertertype = "";        // 如果没有参数则返回为()否则遍历参数        if (paramerterTypes.length == 0) {            paramertertype += "()";        } else {            paramertertype += "(";            // 普通for循环遍历其参数列表便于通过角标判断拼接括号            for (int i = 0; i < paramerterTypes.length; i++) {                // 如果遍历的参数不是最后一个则进if 否则拼接 ")";                if (i < paramerterTypes.length - 1) {                    paramertertype += paramerterTypes[i].getSimpleName()                            + ",";                } else {                    paramertertype += paramerterTypes[i].getSimpleName()                            + ")";                }            }        }        // 最后拼接打印所有的方法        System.out.println(modifier + " " + type + " " + name + " "                + paramertertype);    }}`

(四)、获取所有成员变量

`@Testpublic void getprintFieldInfo(){    Class<Person> clazz=Person.class;    //获取 所有公共的成员变量,包含从父类继承过来的    Field[] fields = clazz.getFields();    //获取自定义的所有成员变量,不问修饰符    Field[] fields1=clazz.getDeclaredFields();    //增强for循环遍历所有成员    //可以将下面fields换为fields1测试获取不同修饰权限的属性    for (Field field : fields1) {        //1获取修饰符        //直接调用Modifier.toString()将field.getModifiers()获取得到的int解码为String类型的修饰符         String modifier= Modifier.toString(field.getModifiers());        //获取类型         Class type=field.getType();        //2获取属性名         String name=field.getName();        //3打印该属性 然后循环遍历下一个属性         System.out.println(modifier+" "+type.getName()+" "+name);    }}`

(五)、获取所有构造方法

 `@Test    public void getConstructorInfo(){        Class clazz1=new Person().getClass();        //获取所有本类构造器        Constructor[] constructors = clazz1.getDeclaredConstructors();        Constructor[] constructors1 = clazz1.getConstructors();        //增强for循环遍历所有构造器        for (Constructor constructor : constructors) {            //1获取对应构造器的修饰符            String modifier=Modifier.toString(constructor.getModifiers());            //2获取构造方法名            String name=constructor.getName();            //3获取对应参数类型            Class[] parameterTypes = constructor.getParameterTypes();            //定义字符串拼接所有参数类型            String pTypes="";            if(parameterTypes.length==0){                pTypes+="()";            }else{                pTypes+="(";                 //普通for循环遍历其参数列表便于通过角标判断拼接括号                for (int i = 0; i < parameterTypes.length; i++){                    if(i<parameterTypes.length-1){                        pTypes+=parameterTypes[i].getSimpleName()+",";                    }else {                        pTypes+=parameterTypes[i].getSimpleName()+")";                    }                  }                }            //打印遍历到的一个构造方法            System.out.println(modifier+" "+name+" "+pTypes);            }        }    `

(六)、利用方式一获取Person类类型 并且创建对象

`@Testpublic void testnewInstance() {    // 1.得到某个类的 类类型(Class类的对象)    Class clazz = Person.class;    // 2.通过反射创建Person类的对象    // 情况一 调用无参构造器clazz.newInstance()创建对象    try {        Person p = (Person) clazz.newInstance();        System.out.println(p);    } catch (Exception e) {        e.printStackTrace();    }    // 情况二: 调用有参构造创建对象    // 1得到指定的公有构造方法    try {        Constructor constructor = clazz.getConstructor(char.class,                String.class);        // 2调用该构造方法        Person p = (Person) constructor.newInstance('男', "李四");        // 3打印Person对象的信息        System.out.println(p);    } catch (Exception e) {        e.printStackTrace();    }    // 情况三: 调用私有的有参构造创建对象    // 1得到指定的私有构造方法    try {        Constructor constructor = clazz.getDeclaredConstructor(char.class);        // //如果是调用私有的就行访问 的 暴力破解 访问私有权限类型如下        constructor.setAccessible(true);        // 2调用该构造方法        Person p = (Person) constructor.newInstance('女');        // 3打印Person对象的信息        System.out.println(p);    } catch (Exception e) {        e.printStackTrace();    }}`

(七)、通过反射 ,为属性赋值

`public void testField() {    // 1.获取指定类的 类类型    Class clazz = Person.class;    // 2.获取指定属性    // 获取自定义的属性,不问修饰符    try {        Field field = clazz.getDeclaredField("name");        // //如果是调用私有的就行访问 的 暴力破解 也可以访问私有权限类型        field.setAccessible(true);        // 3.反射通过获取 Person类的对象        Person person = (Person) clazz.newInstance();        field.set(person, "hello");        System.out.println(field.get(person));    } catch (Exception e) {        e.printStackTrace();    }}`

(八)、通过反射 ,调用非静态方法

`@Test public void testGetMethod() {    // 1.获取某个指定类的类类型    Class clazz = Person.class;    try {        // 2获取自定义的方法,不问修饰符        Method method = clazz.getDeclaredMethod("helloWorld1", int.class);        method.setAccessible(true);// 暴力破解        // 3.获取对象        Person person = (Person) clazz.newInstance();        // 4. 调用方法定义Object类型的invoke接收返回值        Object invoke = method.invoke(person, 18);        System.out.println("返回值:" + invoke);    } catch (Exception e) {        e.printStackTrace();    }}

`


(九)、通过反射,调用静态方法

`@Testpublic void testGetStaticMethod1() {    // 1.获取某个指定类的类类型    Class clazz = Person.class;    // 2. 获取指定的方法    try {        Method method = clazz.getDeclaredMethod("helloWorld", int.class);        // 暴力破解        method.setAccessible(true);        // 3.不用创建对象直接调用方法        System.out.println(method.invoke(null, 88));    } catch (Exception e) {        e.printStackTrace();    }}`

(十)、通过Class类调用其他结构信息

`1、包名System.out.println("包名:"+c.getPackage().getName());

2、父类

System.out.println("父类:"+c.getSuperclass().getSimpleName());

3、接口

Class[] interfaces = c.getInterfaces();    for (Class class1 : interfaces) {        System.out.print(class1.getSimpleName()+"  ");    }

4、注解

Annotation[] annotations = c.getAnnotations();    for (Annotation annotation : annotations) {        System.out.println(annotation.annotationType().getSimpleName());    }

5、父类的泛型

Type[] interfaces = c.getGenericInterfaces();    for (Type type : interfaces) {        if (type instanceof ParameterizedType) {            ParameterizedType  pt = (ParameterizedType) type;//List<Person>、Serriliazalbe            Class clazz = (Class) pt.getActualTypeArguments()[0];            System.out.println(clazz.getSimpleName());        }    }`
0 0