博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java反射
阅读量:4609 次
发布时间:2019-06-09

本文共 6946 字,大约阅读时间需要 23 分钟。

       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
userClass = (Class
) 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
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); }}

 

转载于:https://www.cnblogs.com/jentary/p/6216622.html

你可能感兴趣的文章
[zz]GDB调试精粹及使用实例
查看>>
数据库的创建和删除
查看>>
最简单的三层实例【插入据
查看>>
设计模式学习笔记——Prototype原型模式
查看>>
pom.xml里有红叉报错的解决办法
查看>>
Perl last和next的用法区别
查看>>
Selenium 管理 Cookies
查看>>
exceptionfunction[LeetCode]Permutations
查看>>
Linux(2)_常用命令2
查看>>
自定义分页
查看>>
[转]DELPHI——调试(1)
查看>>
JS秒数转成分秒时间格式
查看>>
xp_cmdshell 命令的开启与关闭,和状态查询
查看>>
Linux sudoers
查看>>
MySQL详解(18)-----------分页方法总结
查看>>
bzoj 4595 激光发生器
查看>>
multi cookie & read bug
查看>>
js时间转换
查看>>
(转载) Android Studio你不知道的调试技巧
查看>>
队列实现霍夫曼树
查看>>