Java基础——003反射(中)eval函数的实现

     Js中有eval函数,可以执行字符串。具体思路是这样的

首先生成源代码,然后进行编译,最后通过反射的方式加载类文件,创建实例,执行方法。

方法1:

public class EvalSuccess extends ClassLoader {

    public static void main(String[] args) {
        EvalSuccess escs = new EvalSuccess();
        try {
            escs.eval();

        }catch (Exception e){
            e.printStackTrace();

        }
    }

    public void eval()throws Exception{
        //生成源代码
        String str = "public class Temp{public void test(){System.out.println(\"Hello\");}}";
        System.out.println(this.getResource("").getPath());
        File f = new File(this.getResource("").getPath() + "Temp.java");
        PrintWriter pw = new PrintWriter(new FileOutputStream(f));
        pw.println(str);
        pw.close();
        //编译
        this.compile(f.getPath());
//        通过反射的方式获取类的Class
        Class<?> clazz = this.loadClass("Temp");
        Method main = clazz.getMethod("test");
        //生成实例,执行方法
        Object m = clazz.newInstance();
        main.invoke(m);
    }
    
    
     /**编译源代码
     *@author  -武刚鹏-2018/2/12
     * @param   -文件路径
     * @return  
     **/
    public boolean compile(String filename)throws Exception{


            Process p = Runtime.getRuntime().exec("javac " + filename);
            try{
                p.waitFor();
            }catch (Exception e){
                System.out.println(e);
            }
            int ret = p.exitValue();
            return ret ==0;

    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        Class clazz = null;

        String fileStub = name.replace(".","/");
        String javaFilename = fileStub + ".java";
        String classFilename = fileStub + ".class";

        File javaFile = new File(javaFilename);
        File classFile = new File(classFilename);
        if(javaFile.exists() && (!classFile.exists() || classFile.lastModified() > javaFile.lastModified())){
            try{
                if(!compile(javaFilename) || !classFile.exists()){
                  throw new ClassNotFoundException("ClassNotFoundException:" + javaFilename);
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        if(classFile.exists()){
            try{
                byte[] raw = getBytes(classFilename);
                clazz  = defineClass(name,raw,0,raw.length);
            }catch (IOException e){
                e.printStackTrace();
            }
        }
        if(clazz == null){
            throw new ClassNotFoundException(name);
        }
        return clazz;
    }

    private byte[] getBytes(String filename)throws IOException{
        File file = new File(filename);
        long len = file.length();
        byte[] raw = new byte[(int)len];
        try(FileInputStream fin = new FileInputStream(file);){
            int r = fin.read(raw);
            if(r!= len){
                throw new IOException("无法读取全部文件!" + r + "!=" + len);
            }
            return raw;
        }
    }
}

方法二:

public class EvalOnline {

    public static void main(String[] args) throws  Exception{
       EvalOnline evalOnline = new EvalOnline();
       evalOnline.eval();
//        evalOnline.getPath();
    }

    /**
     * eval函数的实现
     * @throws Exception
     */
    public  void eval() throws Exception{
        //1、生成源代码
        String sourceStr = "public class Hello{public String sayHello(String name){return \"Hello, \"+name;}}";
        String clsName = "Hello";
        //2、设置编译的一些条件,以及生成编译到 文件单元
        String methodName = "sayHello";
        JavaCompiler cmp = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fm = cmp.getStandardFileManager(null,null,null);
        JavaFileObject jfo = new StringJavaObject(clsName,sourceStr);
        List<String> optionsList = new ArrayList<>();
      String path = this.getClass().getResource("/").getPath();
        System.out.println(path);
        optionsList.addAll(Arrays.asList(new String[]{"-d",path}));
        List<JavaFileObject> jfos = Arrays.asList(new JavaFileObject[]{jfo});
        JavaCompiler.CompilationTask task = cmp.getTask(null,fm,null,
                optionsList,null,jfos);
        //3、task.call进行编译,编译成功
        if(task.call()){
            //4、生成实例
            Object obj = Class.forName( clsName).newInstance();
            //
            Class<? extends Object> cls = obj.getClass();
            //5、执行方法 调用sayHello方法
            Method m = cls.getMethod(methodName,String.class);
            String str = (String)m.invoke(obj,"武刚鹏");
            System.out.println(str);
        }
    }

    //获取一些路径的方法
    public void getPath(){
        // 第一种:获取类加载的根路径   D:\git\daotie\daotie\target\classes
        File f = new File(this.getClass().getResource("/").getPath());
        System.out.println("类加载的根路径:" + f);

        // 获取当前类的所在工程路径; 如果不加“/”  获取当前类的加载目录  D:\git\daotie\daotie\target\classes\my
        File f2 = new File(this.getClass().getResource("").getPath());
        System.out.println("当前类的加载目录"+  f2);

        // 第二种:获取项目路径    D:\git\daotie\daotie
        File directory = new File("");// 参数为空
        try{

            String courseFile = directory.getCanonicalPath();
            System.out.println("项目路径:" +  courseFile);
        }catch (Exception e){
            e.printStackTrace();
        }



        // 第三种:  file:/D:/git/daotie/daotie/target/classes/
        URL xmlpath = this.getClass().getClassLoader().getResource("");
        System.out.println(xmlpath);

        System.out.println( "当前类的包名:" + this.getClass().getPackage().getName());
        // 第四种: D:\git\daotie\daotie
//        System.out.println(System.getProperty("user.dir"));
         /*
          * 结果: C:\Documents and Settings\Administrator\workspace\projectName
          * 获取当前工程路径
          */

        // 第五种:  获取所有的类路径 包括jar包的路径
//        System.out.println(System.getProperty("java.class.path"));

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 21
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值