Roronoa Zoro

无名小站,兴趣使然

Java 反射机制
一:反射的理解

    理解:Java 反射是可以让我们在运行时获取类的方法、属性、父类、接口等类的内部信息的机制。也就是说,反射本质上是一个“反着来”的过程。我们通过new创建一个类的实例时,实际上是由Java虚拟机根据这个类的Class对象在运行时构建出来的,而反射是通过一个类的Class对象来获取它的定义信息,从而我们可以访问到它的属性、方法,知道这个类的父类、实现了哪些接口等信息。

    对象——>类——>调用里面的成员

    反射的作用:假如我们有两个程序员,一个程序员在写程序的时候,需要使用第二个程序员所写的类,但第二个程序员并没完成他所写的类。那么第一个程序员的代码能否通过编译呢?这是不能通过编译的。利用Java反射的机制,就可以让第一个程序员在没有得到第二个程序员所写的类的时候,来完成自身代码的编译。


二:主要功能,常用方法
功能:
    * 在运行时判断任意一个对象所属的类;
    * 在运行时构造任意一个类的对象;
    * 在运行时判断任意一个类所具有的成员变量和方法;
    * 在运行时调用任意一个对象的方法;
    * 生成动态代理。

方法:
* Class类
*         getFields()
*         getDeclaredFields()
*         getMethods()
*         getDeclaredMethods()
*         getDeclaredConstructors()
*
*         getName()
*         getSimpleName()
特点:
    1.Class本身也是一个类
    2.Class 对象只能由系统建立对象
    3.一个类在 JVM 中只会有一个Class实例
    4.一个Class对象对应的是一个加载到JVM中的一个.class文件
    5.每个类的实例都会记得自己是由哪个 Class 实例所生成
    6.通过Class可以完整地得到一个类中的完整结构

* Field类
*         getModifiers():以int形式返回修饰符
*         getType():获取Class类型的属性类型
*         getName():获取属性名
*
* Method类
*         getModifiers():以int形式返回修饰符
*         getReturnType():获取Class类型的方法返回类型
*         getName():获取方法名
*         getParameterTypes():获取参数数组,类型Class[]
*
*
* Constructor类
*         getModifiers():以int形式返回修饰符
*         getName():获取构造器的全类名
*         getParameterTypes():获取参数数组,类型Class[]

* Class:
*         getField(String name):根据属性名获取属性对象(只能获取public修饰的,包含父类继承来的)
*         getDeclaredField(String name):根据属性名获取属性对象(可以获取本类定义的所有的,不问修饰符)
*         getMethod(String name,Class...class):根据方法名和参数列表获取方法对象(只能获取public修饰的,包含父类继承来的)
*         getDeclaredMethod(String name,Class...class):根据方法名和参数列表获取方法对象(可以获取本类定义的所有的,不问修饰符)
*
*
* Field:
*
*         set(对象,新值)
*         get(对象)
*         setAccessible(true)
*
*         注意:如果是静态属性,对象更改为null即可
*
* Method:
*         invoke(对象,Object...obj)
*         setAccessible(true)


getDeclaredFields 和 getFields 的区别:
getDeclaredFields()获得某个类的所有申明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
getFields()获得某个类的所有的公共(public)的字段,包括父类。


Annotation
三个基本的Annotation:
    –@Override:限定重写父类方法,该注释只能用于方法
    –@Deprecated:用于表示某个程序元素(类,方法等)已过时
    –@SuppressWarnings:抑制编译器警告.





三:反射的使用

    创建Class的三种方法
1. /**
2.  * 获取Class对象的三种方式
3.  * 1 Object ——> getClass();
4.  * 2 任何数据类型(包括基本数据类型)都有一个“静态”的class属性
5.  * 3 通过Class类的静态方法:forName(String  className)(常用)
6.  *
7.  */  
8. public class Fanshe {  
9.     public static void main(String[] args) {  
10.         //第一种方式获取Class对象    
11.         Student stu1 = new Student();//这一new 产生一个Student对象,一个Class对象。  
12.         Class stuClass = stu1.getClass();//获取Class对象  
13.         System.out.println(stuClass.getName());  
14.           
15.         //第二种方式获取Class对象  
16.         Class stuClass2 = Student.class;  
17.         System.out.println(stuClass == stuClass2);//判断第一种方式获取的Class对象和第二种方式获取的是否是同一个  
18.           
19.         //第三种方式获取Class对象  
20.         try {  
21.             Class stuClass3 = Class.forName("fanshe.Student");//注意此字符串必须是真实路径,就是带包名的类路径,包名.类名  
22.             System.out.println(stuClass3 == stuClass2);//判断三种方式是否获取的是同一个Class对象  
23.         } catch (ClassNotFoundException e) {  
24.             e.printStackTrace();  
25.         }  
26.           
27.     }  
28. }

    注意:在运行期间,一个类,只有一个Class对象产生。
    三种方式常用第三种,第一种对象都有了还要反射干什么。第二种需要导入类的包,依赖太强,不导包就抛编译错误。一般都第三种,一个字符串可以传入也可写在配置文件中等多种方法。



通过反射获取类中的 三大主要成员:属性、方法、构造器

     /**
      * 功能:通过反射打印对应类中的所有属性
      *
      * @param c
      *            Class类的对象
      */
     public static void printFields(Class c) {
         // Field[] fields =
         // c.getFields();//只能获取所有public修饰的属性,包含从父类继承来和自身定义,不限于直接父类
         Field[] fields = c.getDeclaredFields();// 可以获取本类中定义的所有属性,不问修饰符
         for (Field field : fields) {
              // ①修饰符
              int mod = field.getModifiers();
              String modifier = Modifier.toString(mod);
              // ②属性类型
              String typeName = field.getType().getSimpleName();
              // ③属性名
              String name = field.getName();
              System.out.println(modifier + "\t" + typeName + "\t" + name);
         }
     }
     /**
      * 功能:通过反射打印所有 的构造器
      *
      * @param c
      */
     public static void printConstructors(Class c) {
         Constructor[] constructors = c.getDeclaredConstructors();
         for (Constructor constructor : constructors) {
              // ①修饰符
              String modifier = Modifier.toString(constructor.getModifiers());
              // ②方法名
              // String name = constructor.getName();//全类名
              String name = c.getSimpleName();// 简单类名&构造器名
              // ③参数列表
              Class[] parameterTypes = constructor.getParameterTypes();
              StringBuilder builder = new StringBuilder("(");
              for (int i = 0; i < parameterTypes.length; i++) {
                  String simpleName = parameterTypes[i].getSimpleName();
                  builder.append(simpleName);
                  if (i == parameterTypes.length - 1)
                       continue;
                  builder.append(',');
              }
              builder.append(")");
              System.out.println(modifier + "\t" + name + builder);
         }
     }
     /**
      * 功能:通过反射打印所有 的方法
      *
      * @param c
      */
     public static void printMethods(Class c) {
         // 步骤1:获取所有方法
         // Method[] methods =
         // c.getMethods();//只能获取所有public修饰的方法,包含从父类继承来的和自身定义的,不限于直接父类
         Method[] methods = c.getDeclaredMethods();// 可以获取本类中定义的所有方法,不问修饰符
         // 步骤2:遍历每个方法,打印每个方法签名的四要素
         for (Method method : methods) {
              // public void setAge(int,String)
              // ①修饰符
              String modifier = Modifier.toString(method.getModifiers());
              // ②返回类型
              String returnTypeName = method.getReturnType().getSimpleName();
              // ③方法名
              String name = method.getName();
              // ④参数列表
              Class[] parameterTypes = method.getParameterTypes();
              StringBuilder builder = new StringBuilder("(");
              for (int i = 0; i < parameterTypes.length; i++) {
                  String simpleName = parameterTypes[i].getSimpleName();
                  builder.append(simpleName);
                  if (i == parameterTypes.length - 1)
                       continue;
                  builder.append(',');
              }
              builder.append(")");
              System.out.println(modifier + "\t" + returnTypeName + "\t" + name
                       + builder);
         }
     }



    通过反射访问属性和方法

     // 访问方法
     /*
      * public void setAge(int age) { protected int getAge() {
      */
     @Test
     public void test2() throws Exception {
         // 1.根据方法名和参数列表获取方法对象
         // c.getMethod(name, parameterTypes) //只能获取public修饰的方法,包含从父类继承来的,不限于直接父类
         Method method = c.getDeclaredMethod("getAge");// 获取本类中定义的所有方法,不问修饰符
         method.setAccessible(true);
         // 2.创建对象
         // Object obj = c.newInstance();
         // 3.调用方法
         Object returnValue = method.invoke(null);
         System.out.println("返回值:" + returnValue);
     }
     // 访问属性
     @Test
     public void test1() throws Exception {
         // 1.根据属性名获取属性对象
         // Field filed = c.getField(name); //只能获取public修饰的属性,包含从父类继承来的,不限于直接父类
         Field field = c.getDeclaredField("name");
         field.setAccessible(true);
         // 2.获取对应类的对象
         Object obj = c.newInstance();
         // 3.为属性赋值
         field.set(obj, "慕容复");
         // 4.读取属性
         Object value = field.get(obj);
         System.out.println(value);
         // -----------------------练习------------------
          System.out.println(field.get(c.newInstance()));
     }
     // 访问静态属性
     @Test
     public void exec1() throws Exception {
         // 1.根据属性名获取属性对象
         Field field = c.getDeclaredField("SCHOOL");
         // 2.暴破
         field.setAccessible(true);
         // 3.为属性赋值
         // field.set(null, "北京大学");
         // 4.访问属性
         System.out.println(field.get(null));
     }





































阅读更多
版权声明:www.github.com/chinasonglei https://blog.csdn.net/china_songlei/article/details/79952636
个人分类: North drift
想对作者说点什么? 我来说一句

Java反射机制 Java反射机制

2008年12月28日 20KB 下载

Java反射机制

2011年10月10日 188KB 下载

java反射机制与动态代理

2010年03月28日 250KB 下载

Java反射机制课件ppt

2010年06月28日 268KB 下载

JAVA 反射机制应用

2008年10月17日 124KB 下载

java反射原理

2011年07月04日 450KB 下载

java反射机制教程

2009年07月24日 202KB 下载

没有更多推荐了,返回首页

不良信息举报

Java 反射机制

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭