本系列文章将整理到我在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 ba