zoukankan      html  css  js  c++  java
  • java基础--反射

           Java程序在运行时,Java运行时系统一直对所有的对象进行所谓的运行时类型标识。这项信息纪录了每个对象所属的类。虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些类型信息的类是Class类。Class类封装一个对象和接口运行时的状态,当装载类时,Class类型的对象自动创建。
           Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的,因此不能显式地声明一个Class对象。
    虚拟机为每种类型管理一个独一无二的Class对象。也就是说,每个类(型)都有一个Class对象。运行程序时,Java虚拟机(JVM)首先检查是否所要加载的类对应的Class对象是否已经加载。如果没有加载,JVM就会根据类名查找.class文件,并将其Class对象载入。
          基本的 Java 类型(boolean、byte、char、short、int、long、float 和 double)和关键字 void 也都对应一个 Class 对象。
    每个数组属于被映射为 Class 对象的一个类,所有具有相同元素类型和维数的数组都共享该 Class 对象。
    一般某个类的Class对象被载入内存,它就用来创建这个类的所有对象。


    String s = "aaa"; //1获取字节码对象 Class cla1 = s.getClass(); //2 根据类获取 Class cla2 = String.class; //3 常用 根据字符名 Class cla3 = Class.forName("java.lang.String");

    一个类只对应一个Class对象:包括   基本数据类型,对象和接口,数组,void,枚举,注解            真对维度而不是长度

    例如  int[] arr1 = new int[4];   int[] arr2 = new int[10];   class相同

           int[] arr1 = new int[4];   int[][] arr2 = new int[10][2];   class不相同

    @SuppressWarnings("all")
    public class ClassTest {
    
        public static void main(String[] args) throws Exception {
            
            Class<User> userClass = (Class<User>) Class.forName("reflex.User");
            
            System.out.println(userClass.getName());//包名加类名
            
            System.out.println(userClass.getSimpleName());
            Field[] fields1 = userClass.getFields();//获取public的属性
            Field field = userClass.getDeclaredField("name");
            
            Field[] fields = userClass.getDeclaredFields();//获取所有属性包括private
            
            for (Field temp : fields) {
                System.out.println(temp);
            }
            
            Method []method = userClass.getDeclaredMethods();//获取所有方法
            
            Method method1 = userClass.getDeclaredMethod("getName", null);
            
            Method method2 = userClass.getDeclaredMethod("setName", String.class);
            System.out.println(method1);
            
            Constructor[] constructors = userClass.getDeclaredConstructors();//获取所有构造器
            
            //利用反射创建对象
            User u = userClass.newInstance();//调用的是user的无参构造器
            
            Constructor<User> c = userClass.getConstructor(int.class,String.class);
            
            User u2 = c.newInstance(100,"张三");
            //利用反射调用方法
            Method method3 = userClass.getDeclaredMethod("setName", String.class);
            method3.invoke(u2,"张三");
            //利用反射操作属性
            Field field1 = userClass.getDeclaredField("name");
            field1.setAccessible(true);//如果是私有变量,允许访问,不做安全检查
            field1.set(u2, "张三");
            
            
            
        }
    }



     /**
     * 动态编译
     * @author Administrator
     *
     */
    public class DynamicComplieTest {
    
        
        public static void main(String[] args) {
            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            
            int result = compiler.run(null, null, null, ".java文件的路径");
            
            System.out.println(result==0?"编译成功":"编译失败");
    
     
    
            //通过反射调用main
            URL [] urls = new URL[]{ new URL(".java文件路径")};
            URLClassLoader loader = new URLClassLoader(urls);
            Class c = loader.loadClass("myjava");
            
            Method m = c.getMethod("main",String[].class );
            
            m.invoke(null, (Object)new String[]{});
            
            
        }
        
    }
    /**
     * java执行js   第三方实现rhino
     * @author Administrator
     *
     */
    public class JavaScriptTest {
        
        
        public static void main(String[] args) throws Exception {
            //获取脚本引擎对象
            ScriptEngineManager sem = new ScriptEngineManager();
            
            ScriptEngine engine = sem.getEngineByName("javascript");
            
            //在java js中都能获取到
            engine.put("msg", "hello word");
            engine.get("msg");
            engine.eval("javascript代码");
            //定义函数  
            engine.eval("function add(a,b){var sum = a+b;return sum;}");
            
            Invocable invocable = (Invocable)engine;
            
            Object sum = invocable.invokeFunction("add", new Object[]{13,20});
            System.out.println(sum);
            
            //执行一个js文件放到src下
            
            URL url = JavaScriptTest.class.getClassLoader().getResource("a.js");
            FileReader reader = new FileReader(url.getPath());
            engine.eval(reader);
            reader.close();
        }
    
    }

     类加载器层次结构

      引导类加载器 (最上层)C++,用来加载java的核心库

      扩展类加载器   用来加载java的扩展库

      应用程序类加载器

      自定义类加载器

    类加载器的代理模式

     代理模式    交给其他加载器加载指定的类

     双亲委托机制   委托给父类加载器

    自定义类加载器

    /**
     * 自定义文件系统类加载器
     * @author Administrator
     *
     */
    public class FileSystemClassLoader extends ClassLoader{
    
        
        private String rootDir;
    
        public FileSystemClassLoader(String rootDir) {
            this.rootDir = rootDir;
        }
        
        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {
    
            Class c= findLoadedClass(name);
            
            if(c!=null){
                return c;
            }else{
                ClassLoader parent = this.getParent();
                c = parent.loadClass(name);//为派给父类加载
                if(c!=null){
                    return c;
                }else{
                    byte [] classData = getClassData(name);
                    if(classData==null){
                        throw new ClassNotFoundException();
                    }else{
                        
                        c = defineClass(name,classData, 0,classData.length);
                        
                    }
                    
                }
                
                
            }
            
            return c;
        }
        
        
        private byte[] getClassData(String name) {
            String path = rootDir = "/"+name.replace(".", "/");//com.aa转成d:/aa.class
            
            InputStream is = null;
            
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            
            try {
                is = new FileInputStream(path);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            
            byte [] buffer = new byte[1024];
            int temp =0;
            try {
                while((temp=is.read(buffer))!=-1){
                    os.write(buffer, 0, temp);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            return os.toByteArray();
            
            
        }
        
        
    }

    不同类加载器加载的类不相同

    线程类加载器为了抛弃双亲委托机制

    Thread.currentThread().setContextClassLoader(class);

    OSGI   面向java的动态模块系统,谁定义就由谁加载

    eclipse基于OSGI构建的,Equinox    OSGI的实现

    public class Fs1 {
        
        
        public static void main(String[] args) throws Exception {
            
            Class<?> c = Class.forName("fanshe.User");
            System.out.println(c.getName());//获取类的全称
            System.out.println(c.getSimpleName());//获取类的简称
            
            
            User u1 = (User) c.newInstance();//通过反射创建对象
            System.out.println(u1.getId());
            
            
            Constructor con = c.getConstructor();//无参构造方法
            User u2 = (User) con.newInstance();//通过反射构造方法创建对象
            System.out.println(u2.getId());
            
            
            Field f = c.getDeclaredField("name");//获取字段    DeclaredField包括私有
            f.setAccessible(true);//设置可以调用私有属性
            System.out.println(f.get(u2));
            
            
            Method m = c.getDeclaredMethod("setName", String.class);
            Object o = m.invoke(u2, "张三");//调用方法
            
            System.out.println(u2.getName());
            System.out.println(o);
            
            
            
            
            
        }
    
    }
  • 相关阅读:
    C++高级程序员(廊坊+高薪)欢迎各种漂回家!(该职位已截止)
    utf8_unicode_ci和utf8_general_ci区别
    Percentencoding
    libiconv GNU Project Free Software Foundation (FSF)
    2013年1月6日北京交流会:当当网如何打造个性化推荐&精准营销生态系统
    COM Vs .NET (Qt ActiveQt)
    新一篇: Unicode字符编码规范 实例详细介绍各种字符集编码转换问题
    甩开外包,雄踞榜首:揭开“宫爆老奶奶”成功的秘密
    awk使用命令
    API SOCKET基础(三)网络字节序与主机字节序的转换
  • 原文地址:https://www.cnblogs.com/jentary/p/6216622.html
Copyright © 2011-2022 走看看