首页 > 其他 > 详细

笔记13(动态性:反射,动态编译,执行,操作)

时间:2017-01-06 07:54:57      阅读:252      评论:0      收藏:0      [点我收藏+]

1:动态语言:

    在运行时,能够改变程序结构和类型。(java不行,如:python,js,ruby)
    c,c++,java却可以通过反射,操作字节码获得类似动态的特性。

2.反射机制:

可以在运行时,加载,探索,使用编译期间未知的类型。
在运行时,加载一个只知道类名的类,便能知道这个类的属性和方法,可以用来生成对象,对于对象可以调用其方法和属性。
(加载类,其实就是在堆内存中生成一个Class类型的对象(jvm通过加载器),并且每个类型都只会有一个Class对象。所以Class对象是反射的根源)

3.获取Class:

Class string = Class.forName("com.me.test.reflect.User");//一般用类全名(即包括包名)(之所可以不用,是import了
Class string2 = "stirng".getClass();//通过对象获取
Class string3 = String.class;//通过类型获取

a.数组是不同的维度对应不同的Class
b.像class interface enu void type private等这些关键词代表的意义也是Class类型

4.功能作用:

特别注意对于一些方法对于可变参数(即数组)而言,数组参数要转成Object,如果参数本身就是数组,不转换会该参数的元素被误认为,是多个参数的封装到数组了。

Object object = f.invoke(null, (Object) new String[] { "a", "b" },(Object) new String[] { "aa", "ab" });

获取属性,方法 ,构造器的时候,带declared的方法名才能获取所有范围的否则只能获取public修饰的。比如:declaredField()和getField()。

        Class userClass =Class.forName("com.me.test.reflect.User");
      1.// 获取属性,只能是public修饰的
        Field field = userClass.getField("id");// 否则找不到,异常
        // 可以是任意范围
        Field declaredField = userClass.getDeclaredField("pId");
        // public int com.me.test.reflect.User.id----private int
        // com.me.test.reflect.User.pId
        System.out.println(field + "----" + declaredField);

        // 只能获取public属性
        Field[] fields = userClass.getFields();
        // 所有属性
        Field[] declaredF = userClass.getDeclaredFields();
        // [public int com.me.test.reflect.User.id]
        System.out.println(Arrays.toString(fields));
        // [private int com.me.test.reflect.User.pId,
        // public int com.me.test.reflect.User.id,
        // protected java.lang.String com.me.test.reflect.User.proName]
        System.out.println(Arrays.toString(declaredF));
        
      2.//获取无参方法可以不写参数类型
        Method getName = userClass.getMethod("getName");
        Method setName = userClass.getMethod("setName", String.class);
        Method declaredsetName = userClass.getDeclaredMethod("setName", String.class);
        Method[] methods = userClass.getMethods();
        Method[] declaredMethods = userClass.getDeclaredMethods();
        
      3.//获得构造器
        Constructor[] constructors = userClass.getConstructors();
        Constructor[] declaredconstructors2 = userClass.getDeclaredConstructors();
        Constructor<User> constructor = userClass.getConstructor(int.class,String.class);
        Constructor<User> declaredconstructor2 = userClass.getDeclaredConstructor(int.class,String.class);
        
      4.//创建有参数的对象需要先获得构造器
        User newInstance = userClass.newInstance();//无参的字节码对象直接创建
        User newInstance2 = constructor.newInstance(1,"大王");
        
      5.//设置用属性,首先获得属性对象,以及属性所属的对象
        field.setAccessible(true);//true表示不进行安全检查, 对于私有属性和方法才能操作
        field.set(newInstance,11 );
        
      6.//调用方法,首先获得方法对象,以及调用方法的对象
        declaredsetName.invoke(newInstance, "三王");

5.反射执行效率低于正常执行,比如执行10亿次getName()方法

普通大约:2258ms   1倍         
反射大约:62687ms     30倍
不安全检查的反射:14305ms  6倍

6.反射获取泛型:java的泛型只存在编译期,所以为了得到泛型,java提供了一些不属于Class的类型来获取泛型。下面类型和Class类型同属Type的子类型

技术分享

public void test1(Map<String, User> map, List<User> l) {}
public Map<String, User> test2() {return new HashMap<String, User>();}

Method test1 = ReflectTest.class.getMethod("test1", Map.class, List.class);
        // 获得方法的参数类型数组
        Type[] genericParameterTypes = test1.getGenericParameterTypes();
        // [java.util.Map<java.lang.String, com.me.test.reflect.User>,
        // java.util.List<com.me.test.reflect.User>]
        System.out.println(Arrays.toString(genericParameterTypes));
        for (Type gType : genericParameterTypes) {
            // 判断是否是泛型参数
            if (gType instanceof ParameterizedType) {
                // 获得泛型参数中的泛型类型
                Type[] actualTypeArguments = ((ParameterizedType) gType).getActualTypeArguments();
                // 第一次循环: [class java.lang.String, class com.me.test.reflect.User]
                // 第二次循环: [class com.me.test.reflect.User]
                System.out.println(Arrays.toString(actualTypeArguments));
            }

        }

        Method test2 = ReflectTest.class.getMethod("test2");
        // 获得返回类型
        Type genericReturnType = test2.getGenericReturnType();
        // [java.util.Map<java.lang.String, com.me.test.reflect.User>,
        // java.util.List<com.me.test.reflect.User>]
        System.out.println(genericReturnType);
        // 返回类型是否是泛型
        if (genericReturnType instanceof ParameterizedType) {
            // 获得泛型参数中的泛型类型
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            // 输出: [class java.lang.String, class com.me.test.reflect.User]
            System.out.println(Arrays.toString(actualTypeArguments));
        }

7.反射获取注解:

8.动态编译:动态的加载一些类文件进行编译。

java1.6引入了动态编译机制之前的类似效果的方式:

        Runtime runtime = Runtime.getRuntime();
        runtime.exec("javac -cp d:/mytest/ Hello.java");//编译
        Process process = runtime.exec("java -cp d:/mytest/ Hello");//运行
        //可以从输入流中读取到打印的信息
        InputStream inputStream = process.getInputStream();

java6引入了javaCompile类(如果想编译一个字符串的程序,可以考虑先弄成.java文件。)

        JavaCompiler systemJavaCompiler = ToolProvider.getSystemJavaCompiler();
        // 四个参数in, out, err, arguments,前三个默认是标准输入,输出,错误输出
        // 会在同位生成字节码文件,返回0表示成功
        int run = systemJavaCompiler.run(null, null, null, "d:/mytest/ Hello.java");

可以通过反射运行字节码:

        URL[] urls = new URL[] { new URL("file:/" + "d:/mytest/") };//url不仅可以封装链接,还可以是文件目录(感觉用的少)
        URLClassLoader classLoader = URLClassLoader.newInstance(urls);// 获得加载器
        Class<?> hello = classLoader.loadClass("Hello");// 加载字节码生成Class对象
        Method f = hello.getDeclaredMethod("f", String[].class);// void f(String[] s){..}
        // 对于静态方法可以所属对象可以是null
        // 特别注意为什么要转成Object,对于可变参数(即数组)而言,
        // 如果参数本身就是数组,不转换会该参数的元素被误认为,是多个参数的封装到数组了。
        Object object = f.invoke(null, (Object) new String[] { "a", "b" });

9.java脚步引擎(1.6引入),通过一套固定的接口,实现和脚步引擎交互,从而可以将一些复杂业务逻辑交给脚本语言处理。比如用js运行字符串“12+3-3*/5=”的计算。

  java6中将Rhino(由java语言编写可以实现js)引擎集成了

 

笔记13(动态性:反射,动态编译,执行,操作)

原文:http://www.cnblogs.com/straybirds/p/6254835.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!