zoukankan      html  css  js  c++  java
  • java开发--反射技术

    学习目标:

    1.什么是反射:即反射的定义,

    2.反射有什么作用,能解决什么问题, 

    3.反射的知识点是什么,

    4.反射的利弊

    5.反射的例子

     

    1.什么是反射:反射的定义:

    a) 能够分析类能力的程序被称为反射(reflective

     

    2.反射的作用,能解决什么问题:

    1.在运行中分析类的能力

    2.在运行中查看对象

    3.实现数组的操作代码

    4.利用Method对象,这个对象很像c++中的函数指针

    使用反射的主要人员是工具构造者,而不是应用程序员。

     

    反射机制最重要的内容:检查类的结构。

     

    3.反射的知识点:

    a) Class类:

    所有对象都有一个运行时的类型标识,它保存着每个对象所属的类足迹,保存这些信息的类被称为ClassObject类中的getClass()方法会返回一个Class类型实例。

    获取Class类对象的三种方法:

    1. Class c = objectName.getClass();

    Employee e;

           Class c = e.getClass();

    2. 调用静态方法forName获得类名对应的Class对象

    String className = "java.util.Date";

      Class c = Class.forName(className);

    3. java类型.class

    Class c = Date.class;

      Class c1 = int.class;

      Class c2 = Double[].class;

    Class类的方法:

    最常用的Class方法是getName()方法,将返回类的名字;getFieldsgetMethodsgetConstructors方法将返回类提供的public域、方法、构造器数组,其中包括超类的共有成员;getDeclareFieldsgetDeclareMethodsgetDeclareConstructors方法将分别返回类中声明的全部域、方法、构造器,包括私有和受保护成员,但不包括超类的成员。

    b) 在java.lang.reflect包中有一些类FieldMethodConstructorModifierArray

    i. Field用于描述类的域:getType方法,返回域所属类型的Class对象;

    ii. Method用于描述类的方法:有报告返回类型的方法;

    iii. Constructor用于描述类的构造器

    类的共性:三个类都有getName方法,返回项目名称;三个类都有getModifiers的方法,它将返回一个整数值,用不同的位开关描述publicstatic这样的修饰符使用状况;Method类和Constructor类有报告参数类型的方法;

    iv. Modifier类:可用其中的静态方法分析getModifiers返回的整数值,如使用其中的isPublicisPrivateisFinal判断方法或构造器是否是publicprivatefinaltoString方法将修饰词法打印出来。

    v. Array类:允许动态的创建数组。其中的静态方法newInstance,它能构建新数组,必须提供两个参数:数组的元素类型、数组的长度。静态方法getLength能获得数组的长度。获得新数组元素类型有三步:1.首先获得a数组的类对象,2.确认它是一个数组,3.使用Class类的getComponentType方法确定数组对应的类型。

    c) 在运行时查看数据域的实际内容

    利用反射机制可以查看在编译期间还不清楚的对象域。查看对象域的关键方法是Field类中的get方法,例如f是一个field类型的对象,obj是某个包含f域的类的对象,f.get(obj)将返回一个对象,其值为obj对象f域的当前值。

    Employee harry = new Employee("Harry Hacker", 3500, 10, 1, 1989);

    Class c = harry.getClass();

    Field f = c.getDeclaredField("name");

    f.setAccessible(true);

    Object v = f.get(harry);

    注意:因为name是一个私有域,直接用get方法会抛出异常,只有先用setAccessible方法,使其先不受安全管理器的控制,才可以访问。setAccessible方法是AccessibleObject类中的一个静态方法,它是FieldMethodConstructor类的公共超类。

    当然,可以获得就可以设置,调用f.set(obj, value);可以将obj对象的f域设为新值。

    d)  使用反射编写泛型数组代码

    能编写一个用于扩展数组的通用方法。

    用到java.lang.reflect包中的Array类,如下:

    static Object arrayGrow(Object a) //Object,不是Object[]

    {

    Class c1 = a.getClass();

    if(!c1.isArray()) return null;

    Class componentType = c1.getComponentType();

    int length = Array.getLength(a);

    int newLength = length*11/10+10;

    Object newArray = Array.newInstance(componentType,newLength);

    System.arraycopy(a,0,newArray,0,length);

    return newArray;

    }

    注:int[] 可以被转换成Object,但不能转换成对象数组。可以将一个对象数组临时转换成Object[]数组,然后再把它转换回来是可以的,但一个从一开始就是Object[]的数组却不能转换成非Object对象数组;

    e)  方法指针:

    方法指针是指将一个方法的存储地址传给另外一个方法,以便第二个方法能够随后调用它。从表面上看,java没有提供方法指针,事实上,java设计者说过方法指针很危险,但是在java1.1中,方法指针以作为反射包的副产品出现了。

    Method类中有一个invoke方法,它允许调用包装在当前Method对象中的方法。

     

    4.反射的利弊:

    a) 反射机制可以使人们可以在运行时查看方法和域,让人编写出更具通用性的程序。这种功能对编写系统程序来说极为有用,但通常不适用于编写应用程序。

    b) 反射很脆弱,编译器很难帮助人发现程序中的错误,任何错误只能在运行时发现,并导致异常。

    5.反射的例子:

    利用反射打印一个类的构造函数、方法、域

    点击(此处)折叠或打开

    1. public class ReflectTest {
    2.     
    3.     public static void main(String[] args){
    4.         String name;
    5.         if(args.length > 0){
    6.             name = args[0];
    7.         }else{
    8.             Scanner in = new Scanner(System.in);
    9.             System.out.println("Enter class name (e.g. java.util.Date): ");
    10.             name = in.next();
    11.         }
    12.         
    13.         try{
    14.             //print class name and superclass name(if != Object)
    15.             Class c1 = Class.forName(name);
    16.             Class superc1 = c1.getSuperclass();
    17.             String modifiers = Modifier.toString(c1.getModifiers());
    18.             if(modifiers.length() > 0)    System.out.print(modifiers+" ");
    19.             System.out.print("class "+name);
    20.             if(superc1 != null && superc1 != Object.class)    System.out.println(
    21.                     " extends"+superc1.getName());
    22.             
    23.             System.out.print(" { ");
    24.             printConstructors(c1);
    25.             printMethods(c1);
    26.             printFields(c1);
    27.             System.out.println("}");
    28.         }catch(ClassNotFoundException e){
    29.             e.printStackTrace();
    30.         }
    31.         System.exit(0);
    32.     }
    33.     
    34.     
    35.     /*
    36.      * prints all constructors of a class
    37.      */
    38.     public static void printConstructors(Class c1){
    39.         Constructor[] constructors = c1.getConstructors();
    40.         
    41.         for(Constructor c:constructors){
    42.             String name = c.getName();
    43.             System.out.print(" ");
    44.             String modifiers = Modifier.toString(c1.getModifiers());
    45.             if(modifiers.length() > 0) System.out.print(modifiers+" ");
    46.             System.out.print(name+"( ");
    47.             
    48.             //print parameter types
    49.             Class[] paramTypes = c.getParameterTypes();
    50.             for(int j=0; j<paramTypes.length; j++){
    51.                 if(j>0) System.out.print(", ");
    52.                 System.out.print(paramTypes[j].getName());
    53.             }
    54.             System.out.println("); ");
    55.         }
    56.     }
    57.     
    58.     /**
    59.      * prints all methods of a class
    60.      */
    61.     public static void printMethods(Class c1){
    62.         Method[] methods = c1.getMethods();
    63.         
    64.         for(Method m : methods){
    65.             Class retType = m.getReturnType();
    66.             String name = c1.getName();
    67.             
    68.             System.out.print(" ");
    69.             //print modifiers,return type and method name
    70.             String modifiers = Modifier.toString(m.getModifiers());
    71.             if(modifiers.length() > 0) System.out.print(modifiers + " ");
    72.             System.out.print(retType.getName() + " "+name+"(");
    73.             
    74.             //print parameter types
    75.             Class[] paramTypes = m.getParameterTypes();
    76.             for(int j = 0; j<paramTypes.length; j++){
    77.                 if(j>0) System.out.print(", ");
    78.                 System.out.print(paramTypes[j].getName());
    79.             }
    80.             System.out.println(");");
    81.         }
    82.     }
    83.     
    84.     /**
    85.      * print all fields of a class
    86.      */
    87.     public static void printFields(Class c1){
    88.         Field[] fields = c1.getDeclaredFields();
    89.         
    90.         for(Field f : fields){
    91.             Class type = f.getType();
    92.             String name = f.getName();
    93.             System.out.print(" ");
    94.             String modifiers = Modifier.toString(f.getModifiers());
    95.             if(modifiers.length() > 0) System.out.print(modifiers+" ");
    96.             System.out.println(type+" "+name+";");
    97.         }
    98.     }
    99. }
  • 相关阅读:
    再说LZ77压缩算法
    关于LZ77压缩算法
    Qt 简易设置透明按钮
    MFC edit 控件 自动将光标置于想要输入内容的位置
    事件和委托
    2016/06/07
    2016/04/28
    2016/4/27
    2016/04/26
    重载和重写(Overload, Override)
  • 原文地址:https://www.cnblogs.com/wanghuaijun/p/5268321.html
Copyright © 2011-2022 走看看