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);
        
        
        
        
        
    }

}
原文地址:https://www.cnblogs.com/jentary/p/6216622.html