夯实Java基础系列20:从IDE的实现原理聊起,谈谈那些年我们用过的Java命令
程序员文章站
2022-07-02 12:53:51
本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java Tutorial 喜欢的话麻烦点下Star哈 文章首发于我的个人博客: www.how2playlife.com
本系列文章将整理到我在github上的《java面试指南》仓库,更多精彩内容请到我的仓库里查看
https://github.com/h2pl/java-tutorial
喜欢的话麻烦点下star哈
文章首发于我的个人博客:
www.how2playlife.com
聊聊ide的实现原理
ide是把双刃剑,它可以什么都帮你做了,你只要敲几行代码,点几下鼠标,程序就跑起来了,用起来相当方便。
你不用去关心它后面做了些什么,执行了哪些命令,基于什么原理。然而也是这种过分的依赖往往让人散失了最基本的技能,当到了一个没有ide的地方,你便觉得无从下手,给你个代码都不知道怎么去跑。好比给你瓶水,你不知道怎么打开去喝,然后活活给渴死。
之前用惯了idea,java文件编译运行的命令基本忘得一干二净。
那好,不如咱们先来了解一下ide的实现原理,这样一来,即使离开ide,我们还是知道如何运行java程序了。
像eclipse等java ide是怎么编译和查找java源代码的呢?
源代码保存
这个无需多说,在编译器写入代码,并保存到文件。这个利用流来实现。
编译为class文件
java提供了javacompiler,我们可以通过它来编译java源文件为class文件。
查找class
可以通过class.forname(fullclasspath)或自定义类加载器来实现。
生成对象,并调用对象方法
通过上面一个查找class,得到class对象后,可以通过newinstance()或构造器的newinstance()得到对象。然后得到method,最后调用方法,传入相关参数即可。
示例代码:
public class myide { public static void main(string[] args) throws ioexception, classnotfoundexception, nosuchmethodexception, illegalaccessexception, invocationtargetexception, instantiationexception { // 定义java代码,并保存到文件(test.java) stringbuilder sb = new stringbuilder(); sb.append("package com.tommy.core.test.reflect;\n"); sb.append("public class test {\n"); sb.append(" private string name;\n"); sb.append(" public test(string name){\n"); sb.append(" this.name = name;\n"); sb.append(" system.out.println(\"hello,my name is \" + name);\n"); sb.append(" }\n"); sb.append(" public string sayhello(string name) {\n"); sb.append(" return \"hello,\" + name;\n"); sb.append(" }\n"); sb.append("}\n"); system.out.println(sb.tostring()); string baseoutputdir = "f:\\output\\classes\\"; string basedir = baseoutputdir + "com\\tommy\\core\\test\\reflect\\"; string targetjavaoutputpath = basedir + "test.java"; // 保存为java文件 filewriter filewriter = new filewriter(targetjavaoutputpath); filewriter.write(sb.tostring()); filewriter.flush(); filewriter.close(); // 编译为class文件 javacompiler compiler = toolprovider.getsystemjavacompiler(); standardjavafilemanager manager = compiler.getstandardfilemanager(null,null,null); list<file> files = new arraylist<>(); files.add(new file(targetjavaoutputpath)); iterable compilationunits = manager.getjavafileobjectsfromfiles(files); // 编译 // 设置编译选项,配置class文件输出路径 iterable<string> options = arrays.aslist("-d",baseoutputdir); javacompiler.compilationtask task = compiler.gettask(null, manager, null, options, null, compilationunits); // 执行编译任务 task.call(); // 通过反射得到对象 // class clazz = class.forname("com.tommy.core.test.reflect.test"); // 使用自定义的类加载器加载class class clazz = new myclassloader(baseoutputdir).loadclass("com.tommy.core.test.reflect.test"); // 得到构造器 constructor constructor = clazz.getconstructor(string.class); // 通过构造器new一个对象 object test = constructor.newinstance("jack.tsing"); // 得到sayhello方法 method method = clazz.getmethod("sayhello", string.class); // 调用sayhello方法 string result = (string) method.invoke(test, "jack.ma"); system.out.println(result); } }
自定义类加载器代码:
public class myclassloader extends classloader { private string basedir; public myclassloader(string basedir) { this.basedir = basedir; } @override protected class<?> findclass(string name) throws classnotfoundexception { string fullclassfilepath = this.basedir + name.replace("\\.","/") + ".class"; file classfilepath = new file(fullclassfilepath); if (classfilepath.exists()) { fileinputstream fileinputstream = null; bytearrayoutputstream bytearrayoutputstream = null; try { fileinputstream = new fileinputstream(classfilepath); byte[] data = new byte[1024]; int len = -1; bytearrayoutputstream = new bytearrayoutputstream(); while ((len = fileinputstream.read(data)) != -1) { bytearrayoutputstream.write(data,0,len); } return defineclass(name,bytearrayoutputstream.tobytearray(),0,bytearrayoutputstream.size()); } catch (filenotfoundexception e) { e.printstacktrace(); } catch (ioexception e) { e.printstacktrace(); } finally { if (null != fileinputstream) { try { fileinputstream.close(); } catch (ioexception e) { e.printstacktrace(); } } if (null != bytearrayoutputstream) { try { bytearrayoutputstream.close(); } catch (ioexception e) { e.printstacktrace(); } } } } return super.findclass(name); } }
javac命令初窥
注:以下红色标记的参数在下文中有所讲解。
本部分参考https://www.cnblogs.com/xiazdong/p/3216220.html
用法: javac