zoukankan      html  css  js  c++  java
  • java反射机制详解

    一、java反射的含义:

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

    二、反射机制的作用:

                  1,反编译:.class-->.java;

                  2,通过反射机制访问java对象的属性,方法,构造方法等;

    三、类的类类型表示

    1 class Foo{
    2     
    3     void print(){
    4         System.out.println("foo");
    5     }
    6 }

      Foo的实例对象:
          Foo foo1 = new Foo();

      Foo这个类 也是一个实例对象,Class类的实例对象,如何表示呢
      任何一个类都是Class的实例对象,这个实例对象有三种表示方式

       1. 实际在告诉我们任何一个类都有一个隐含的静态成员变量class

         Class c1 = Foo.class;

       2. 已经知道该类的对象通过getClass方法
        Class c2 = foo1.getClass();  

      /*官网 c1 ,c2 表示了Foo类的类类型(class type)
      * 万事万物皆对象,
      * 类也是对象,是Class类的实例对象
      * 这个对象我们称为该类的类类型

      */

         3. 类的全称,需要捕获异常

        Class c3 = null;   

        c3 = Class.forName("com.guiqiu.reflect.Foo");


      /* 不管c1  or c2 or c3都代表了Foo类的类类型,一个类只可能是Class类的一个实例对象:(c1==c2) &&(c2==c3) true

     1 //我们完全可以通过类的类类型创建该类的对象实例---->通过c1 or c2 or c3创建Foo的实例对象
     2 try {
     3             Foo foo = (Foo)c1.newInstance();//需要有无参数的构造方法
     4             foo.print();
     5         } catch (InstantiationException e) {
     6             // TODO Auto-generated catch block
     7             e.printStackTrace();
     8         } catch (IllegalAccessException e) {
     9             // TODO Auto-generated catch block
    10             e.printStackTrace();
    11         }

    四、打印类的信息

      

     1 package com.guiqiu.reflect;
     2 
     3 import java.lang.reflect.Constructor;
     4 import java.lang.reflect.Field;
     5 import java.lang.reflect.Method;
     6 
     7 public class ClassUtil {
     8     /**
     9      * 打印类的信息,包括类的成员函数、成员变量(只获取成员函数)
    10      * @param obj 该对象所属类的信息
    11      */
    12     public static void printClassMethodMessage(Object obj){
    13         //要获取类的信息  首先要获取类的类类型
    14         Class c = obj.getClass();//传递的是哪个子类的对象  c就是该子类的类类型
    15         //获取类的名称
    16         System.out.println("类的名称是:"+c.getName());
    17         /*
    18          * Method类,方法对象
    19          * 一个成员方法就是一个Method对象
    20          * getMethods()方法获取的是所有的public的函数,包括父类继承而来的
    21          * getDeclaredMethods()获取的是所有该类自己声明的方法,不问访问权限
    22          */
    23         Method[] ms = c.getMethods();//c.getDeclaredMethods()
    24         for(int i = 0; i < ms.length;i++){
    25             //得到方法的返回值类型的类类型
    26             Class returnType = ms[i].getReturnType();
    27             System.out.print(returnType.getName()+" ");
    28             //得到方法的名称
    29             System.out.print(ms[i].getName()+"(");
    30             //获取参数类型--->得到的是参数列表的类型的类类型
    31             Class[] paramTypes = ms[i].getParameterTypes();
    32             for (Class class1 : paramTypes) {
    33                 System.out.print(class1.getName()+",");
    34             }
    35             System.out.println(")");
    36         }
    37     }
    38     /**
    39      * 获取成员变量的信息
    40      * @param obj
    41      */
    42     public static void printFieldMessage(Object obj) {
    43         Class c = obj.getClass();
    44         /*
    45          * 成员变量也是对象
    46          * java.lang.reflect.Field
    47          * Field类封装了关于成员变量的操作
    48          * getFields()方法获取的是所有的public的成员变量的信息
    49          * getDeclaredFields获取的是该类自己声明的成员变量的信息
    50          */
    51         //Field[] fs = c.getFields();
    52         Field[] fs = c.getDeclaredFields();
    53         for (Field field : fs) {
    54             //得到成员变量的类型的类类型
    55             Class fieldType = field.getType();
    56             String typeName = fieldType.getName();
    57             //得到成员变量的名称
    58             String fieldName = field.getName();
    59             System.out.println(typeName+" "+fieldName);
    60         }
    61     }
    62     /**
    63      * 打印对象的构造函数的信息
    64      * @param obj
    65      */
    66     public static void printConMessage(Object obj){
    67         Class c = obj.getClass();
    68         /*
    69          * 构造函数也是对象
    70          * java.lang. Constructor中封装了构造函数的信息
    71          * getConstructors获取所有的public的构造函数
    72          * getDeclaredConstructors得到所有的构造函数
    73          */
    74         //Constructor[] cs = c.getConstructors();
    75         Constructor[] cs = c.getDeclaredConstructors();
    76         for (Constructor constructor : cs) {
    77             System.out.print(constructor.getName()+"(");
    78             //获取构造函数的参数列表--->得到的是参数列表的类类型
    79             Class[] paramTypes = constructor.getParameterTypes();
    80             for (Class class1 : paramTypes) {
    81                 System.out.print(class1.getName()+",");
    82             }
    83             System.out.println(")");
    84         }
    85     }
    86 }

     1 package com.guiqiu.reflect;
     2 
     3 public class ClassDemo5 {
     4 
     5     /**
     6      * @param args
     7      */
     8     public static void main(String[] args) {
     9         // TODO Auto-generated method stub
    10         ClassUtil.printConMessage("hello");
    11         ClassUtil.printConMessage(new Integer(1));
    12         
    13 
    14     }
    15 
    16 }
    17 运行结果
    18 java.lang.String([B,)
    19 java.lang.String([B,int,int,)
    20 java.lang.String([B,java.nio.charset.Charset,)
    21 java.lang.String([B,java.lang.String,)
    22 java.lang.String([B,int,int,java.nio.charset.Charset,)
    23 java.lang.String(int,int,[C,)
    24 java.lang.String([C,boolean,)
    25 java.lang.String(java.lang.StringBuilder,)
    26 java.lang.String(java.lang.StringBuffer,)
    27 java.lang.String([I,int,int,)
    28 java.lang.String([C,int,int,)
    29 java.lang.String([C,)
    30 java.lang.String(java.lang.String,)
    31 java.lang.String()
    32 java.lang.String([B,int,int,java.lang.String,)
    33 java.lang.String([B,int,)
    34 java.lang.String([B,int,int,int,)
    35 java.lang.Integer(int,)
    36 java.lang.Integer(java.lang.String,)

    五、方法反射的基本操作

     1 package com.guiqiu.reflect;
     2 
     3 import java.lang.reflect.Method;
     4 
     5 public class MethodDemo1 {
     6     public static void main(String[] args) {
     7        //要获取print(int ,int )方法  1.要获取一个方法就是获取类的信息,获取类的信息首先要获取类的类类型
     8         A a1 = new A();
     9         Class c = a1.getClass();
    10         /*
    11          * 2.获取方法 名称和参数列表来决定  
    12          * getMethod获取的是public的方法
    13          * getDelcaredMethod自己声明的方法
    14          */
    15         try {
    16             //Method m =  c.getMethod("print", new Class[]{int.class,int.class});
    17             Method m = c.getMethod("print", int.class,int.class);
    18             
    19             //方法的反射操作  
    20             //a1.print(10, 20);方法的反射操作是用m对象来进行方法调用 和a1.print调用的效果完全相同
    21             //方法如果没有返回值返回null,有返回值返回具体的返回值
    22             //Object o = m.invoke(a1,new Object[]{10,20});
    23             Object o = m.invoke(a1, 10,20);
    24             System.out.println("==================");
    25             //获取方法print(String,String)
    26              Method m1 = c.getMethod("print",String.class,String.class);
    27              //用方法进行反射操作
    28              //a1.print("hello", "WORLD");
    29              o = m1.invoke(a1, "hello","WORLD");
    30              System.out.println("===================");
    31            //  Method m2 = c.getMethod("print", new Class[]{});
    32                 Method m2 = c.getMethod("print");
    33                // m2.invoke(a1, new Object[]{});
    34                 m2.invoke(a1);
    35         } catch (Exception e) {
    36             // TODO Auto-generated catch block
    37             e.printStackTrace();
    38         } 
    39      
    40     }
    41 }
    42 class A{
    43     public void print(){
    44         System.out.println("helloworld");
    45     }
    46     public void print(int a,int b){
    47         System.out.println(a+b);
    48     }
    49     public void print(String a,String b){
    50         System.out.println(a.toUpperCase()+","+b.toLowerCase());
    51     }
    52 }

    运行结果    

        30
        ==================
        HELLO,world
        ===================
        helloworld

     六、通过反射了解集合泛型的本质

      

     1 package com.guiqiu.reflect;
     2 
     3 import java.lang.reflect.Method;
     4 import java.util.ArrayList;
     5 
     6 public class MethodDemo4 {
     7     public static void main(String[] args) {
     8         ArrayList list = new ArrayList();
     9         
    10         ArrayList<String> list1 = new ArrayList<String>();
    11         list1.add("hello");
    12         //list1.add(20);错误的
    13         Class c1 = list.getClass();
    14         Class c2 = list1.getClass();
    15         System.out.println(c1 == c2);
    16         //反射的操作都是编译之后的操作
    17         
    18         /*
    19          * c1==c2结果返回true说明编译之后集合的泛型是去泛型化的
    20          * Java中集合的泛型,是防止错误输入的,只在编译阶段有效,
    21          * 绕过编译就无效了
    22          * 验证:我们可以通过方法的反射来操作,绕过编译
    23          */
    24         try {
    25             Method m = c2.getMethod("add", Object.class);
    26             m.invoke(list1, 20);//绕过编译操作就绕过了泛型
    27             System.out.println(list1.size());
    28             System.out.println(list1);
    29             /*for (String string : list1) {
    30                 System.out.println(string);
    31             }*///现在不能这样遍历
    32         } catch (Exception e) {
    33           e.printStackTrace();
    34         }
    35     }
    36 
    37 }

    运行结果:

    true
    2
    [hello, 20]

      

      

  • 相关阅读:
    Keras实例教程(2)
    Keras实例教程(1)
    tf.nn.l2_loss()的用法
    在tensorflow中使用batch normalization
    Tensorflow的LRN是怎么做的
    CNN卷积中多通道卷积的参数问题
    caffe学习网站
    交叉熵反向求导计算过程
    矩阵求导
    循环神经网络(RNN)模型与前向反向传播算法
  • 原文地址:https://www.cnblogs.com/guiqiu-Li/p/5872997.html
Copyright © 2011-2022 走看看