• java中的反射机制(一)


    0. 概念

    反射库:工具集合,能够用来编写动态操作Java代码的程序。

    反射:能够分析类的能力的程序,可以用来

    1. 在运行的时候分析类的能力
    2. 在运行的时候检查对象
    3. 实现泛型数组操作代码
    4. 利用Method对象

    1. class类

     1.1概念

    运行时类型标识:java运行时系统始终为所有对象维护一个运行时类型标识,这个信息会跟踪每个对象所属的类

    Class: 使用一个特殊的java类可以访问这些信息(运行时类型标识),保存这些信息的类名为Class

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

    a. Object.getClass方法:该方法会返回一个Class类型的实例

    Employee e;
    Class c1 = e.getClass();

     Class对象会描述一个特定类的属性 ,如上c1可以描述类Employee的属性,最常用的方法是getName(),这个方法将返回类的名字

    e.getClass().getName()

    b.静态方法forName: 获取类型对应的Class对象

    String className = "java.util.Random";
    Class c1 = Class.forName();

    只有className是一个类名或者是接口名,该方法才能正常执行,而且无论何时使用,都需要提供一个异常处理器

    c.如果T是任意的Java类型,T.class将代表匹配的类对象

    例如:

    Class cl1  = Random.class;
    Class cl2 = int.class;
    Class cl3  = Double[].class;

     注意:一个Class对象实际上表示的是一个类型,这可能是类,也可能不是类,如int不是类,int.class是一个Class类型的对象

    1.3 利用==运算实现两个类的对象的比较

     虚拟机为每个类型管理一个唯一的Class对象 

    例如:

    if (e.getClass == Employee.class)

     1.4 构造描述类的实例

     如果有一个Class类型的对像,可以用它构造类的实例

    try {
                String className = "java.util.Random";
                Class c1 = Class.forName(className);
                Object obj = c1.getConstructor().newInstance();
                System.out.println(obj);
            } catch (Exception e) {
                e.printStackTrace();
      }

    输出:

    2.利用反射分析类的能力

    可以检查类的结构。

    java.lang.reflect中有三个类Filed、Method和Constructor分别用于描述类的字段、方法和构造器

    这三个类共有一个getName()的方法,用来返回字段、方法、或者构造器的名称。

    下面的代码就利用Class的api实现了打印一个类的全部信息

    public class ReflectionTest {
        public static void main(String[] args) throws ClassNotFoundException {
            //从命令终端或者用户输入读取类名
            String name;
            if (args.length>0) {
                name = args[0];
            }else {
                Scanner in = new Scanner(System.in);
                System.out.println("Enter class name (e.g. java.util.Date):");
                name = in.next();
            }
    
            //打印该类名和父类名(不是Object的情况下)
            Class cl = Class.forName(name);
            Class superclass = cl.getSuperclass();
            //getModifiers返回一个整数,描述所使用的修饰符,利用Modifier.toString方法将修饰符打印出来
            String modifier = Modifier.toString(cl.getModifiers());
            if (modifier.length()>0) {
                System.out.print(modifier+" ");
            }
            System.out.print("class "+name);
            if (superclass !=null && superclass != Object.class) {
                System.out.print(" extends "+superclass.getName());
            }
            System.out.print("\n{\n");
    
            //打印构造器
            printConstructors(cl);
            System.out.println("");
            printMethods(cl);
            System.out.println("");
            printFiled(cl);
            System.out.println("}");
    
        }
    
        //打印该类的所有构造器
        public static void printConstructors(Class cl){
            //getDeclaredConstructors:获取所有构造器
            Constructor[] constructors = cl.getDeclaredConstructors();
            for (Constructor c : constructors) {
                //获取构造器的名字
                String name = c.getName();
                System.out.print("   ");
                //获取构造器的修饰符
                String modifier = Modifier.toString(c.getModifiers());
                if (modifier.length()>0) {
                    System.out.print(modifier+" ");
                }
                System.out.print(name+"(");
    
                //打印参数类型
                Class[] parameterTypes = c.getParameterTypes();
                for (int i = 0; i <parameterTypes.length ; i++) {
                    if (i>0) {
                        System.out.print(", ");
                    }
                    System.out.print(parameterTypes[i].getName());
                }
                System.out.println(");");
    
            }
        }
    
    
        //打印所有方法
        public static void printMethods(Class c1){
            Method[] methods = c1.getMethods();
            for (Method m : methods) {
                //返回类型
                Class retType = m.getReturnType();
                String name = m.getName();
                System.out.print("   ");
                String modifier = Modifier.toString(m.getModifiers());
                if (modifier.length()>0) {
                    System.out.print(modifier+" ");
                }
                System.out.print(retType.getName()+" "+name+"(");
    
                //打印所有参数类型
                Class[] parameterTypes = m.getParameterTypes();
                for (int i = 0; i <parameterTypes.length ; i++) {
                    if (i>0) {
                        System.out.print(", ");
                    }
                    System.out.print(parameterTypes[i].getName());
                }
                System.out.println(");");
    
            }
        }
    
    
        public static void printFiled(Class cl){
            Field[] fields = cl.getDeclaredFields();
            for (Field f : fields) {
                Class type = f.getType();
                String name = f.getName();
                System.out.print("   ");
                String modifiers = Modifier.toString(f.getModifiers());
                if (modifiers.length() > 0) {
                    System.out.print(modifiers+" ");
                }
                System.out.println(type.getName()+" "+name+";");
            }
        }
    }

    3.使用反射在运行时分析对象

    • 利用反射机制可以查看在编译期间还不知道的对象字段
    • 对于字段的访问,受到Java安全控制的影响,反射机制的默认行为受限于Java的访问控制,但是可以调用Field等的setAccessible方法覆盖掉Java的访问控制,例如: 
    f.setAccessible(true);

    4. 使用反射编写泛型数组代码

     java.lang.reflect包中的Array类允许动态的创建数组

    如CopyOf的实现:

     public static Object goodCopyOf(Object a,int newlength){
            //获取a数组的类对象
            Class cl = a.getClass();
            if(!cl.isArray()) return  null;
            //确定数组的正确类型
            Class componentType = cl.getComponentType();
            int length = Array.getLength(a);
            Object newArray = Array.newInstance(componentType, newlength);
            System.arraycopy(a,0,newArray,0,Math.min(length,newlength));
            return newArray;
        }

    5.利用反射调用方法和构造器

    反射机制中允许你调用任意的方法,Method类中有一个invoke方法,允许你调用当前Method对象的方法

     Method m1 = Math.class.getMethod("sqrt", double.class);
     double d =(Double) m1.invoke(null, 4);
     System.out.println(d);

    输出:

  • 相关阅读:
    第二周作业
    第一周作业
    抓老鼠啊~亏了还是赚了?
    打印沙漏
    寒假作业2
    我与老师
    自我介绍
    第九周课程总结&实验报告(七)
    第八周课程总结&实验报告(六)
    第七周实验报告(五)&周总结
  • 原文地址:https://www.cnblogs.com/xiangshigang/p/15736363.html
Copyright © 2020-2023  润新知