Java进阶:SE6调用编译器的两种方法[1]

作者&投稿:郑待 (若有异议请与网页底部的电邮联系)
~

  在很多Java应用中需要在程序中调用Java编译器来编译和运行 但在早期的版本中(Java SE 及以前版本)中只能通过tools jar中的 sun tools javac包来调用Java编译器 但由于tools jar不是标准的Java库 在使用时必须要设置这个jar的路径 而在Java SE 中为我们提供了标准的包来操作Java编译器 这就是javax tools包 使用这个包 我们可以不用将jar文件路径添加到classpath中了

  一 使用JavaCompiler接口来编译Java源程序

  使用Java API来编译Java源程序有很多方法 现在让我们来看一种最简单的方法 通过JavaCompiler进行编译

  我们可以通过ToolProvider类的静态方法getSystemJavaCompiler来得到一个JavaCompiler接口的实例

  JavaCompiler piler = ToolProvider getSystemJavaCompiler();

  JavaCompiler中最核心的方法是run 通过这个方法可以编译java源程序 这个方法有 个固定参数和 个可变参数(可变参数是从Jave SE 开始提供的一个新的参数类型 用type… argu表示) 前 个参数分别用来为java编译器提供参数 得到Java编译器的输出信息以及接收编译器的错误信息 后面的可变参数可以传入一个或多个Java源程序文件 如果run编译成功 返回

  int run(InputStream in OutputStream out OutputStream err String arguments)

  如果前 个参数传入的是null 那么run方法将以标准的输入 输出代替 即System in System out和System err 如果我们要编译一个test java文件 并将使用标准输入输出 run的使用方法如下

  int results = tool run(null null null test java );

  下面是使用JavaCompiler的完整代码

  import java io *;  import javax tools *;  public class test_pilerapi  {   public static void main(String args[]) throws IOException   {    JavaCompiler piler = ToolProvider getSystemJavaCompiler();    int results = piler run(null null null test java );    System out println((results == )? 编译成功 : 编译失败 );    // 在程序中运行test    Runtime run = Runtime getRuntime();    Process p = run exec( java test );    BufferedInputStream in = new BufferedInputStream(p getInputStream());    BufferedReader br = new BufferedReader(new InputStreamReader(in));    String s;    while ((s = br readLine()) != null)    System out println(s);   }  }  public class test  {   public static void main(String[] args) throws Exception   {    System out println( JavaCompiler测试成功! );   }  }

  编译成功的输出结果

  编译成功

  JavaCompiler测试成功

  编译失败的输出结果

  test java: : 找不到符号

  符号 方法 printlnln(java lang String)

  位置 类 java io PrintStream

  System out printlnln( JavaCompiler测试成功! );

  ^

   错误

  编译失败

  二 使用StandardJavaFileManager编译Java源程序

  在第一部分我们讨论调用java编译器的最容易的方法 这种方法可以很好地工作 但它确不能更有效地得到我们所需要的信息 如标准的输入 输出信息 而在Java SE 中最好的方法是使用StandardJavaFileManager类 这个类可以很好地控制输入 输出 并且可以通过DiagnosticListener得到诊断信息 而DiagnosticCollector类就是listener的实现

  使用StandardJavaFileManager需要两步 首先建立一个DiagnosticCollector实例以及通过JavaCompiler的getStandardFileManager()方法得到一个StandardFileManager对象 最后通过CompilationTask中的call方法编译源程序

  在使用这种方法调用Java编译时最复杂的方法就是getTask 下面让我们讨论一下getTask方法 这个方法有如下所示的 个参数

  getTask(Writer out JavaFileManager fileManager   DiagnosticListener diagnosticListener   Iterable options   Iterable classes   Iterable pilationUnits)

  这些参数大多数都可为null 它们的含义所下

  ·out: 用于输出错误的流 默认是System err

  ·fileManager: 标准的文件管理

  ·diagnosticListener: 编译器的默认行为

  ·options: 编译器的选项

  ·classes 参与编译的class

  最后一个参数pilationUnits不能为null 因为这个对象保存了你想编译的Java文件

  在使用完getTask后 需要通过StandardJavaFileManager的getJavaFileObjectsFromFiles或getJavaFileObjectsFromStrings方法得到pilationUnits对象 调用这两个方法的方式如下

  Iterable getJavaFileObjectsFromFiles(  Iterable files)  Iterable getJavaFileObjectsFromStrings(  Iterable names)  String[] filenames = …;  Iterable pilationUnits =  fileManager getJavaFileObjectsFromFiles(Arrays asList(filenames));  JavaCompiler CompilationTask task = piler getTask(null fileManager   diagnostics options null pilationUnits);  最后需要关闭fileManager close();

  下面是一个完整的演示程序

  import java io *;  import java util *;  import javax tools *;  public class test_pilerapi  {   private static void pilejava() throws Exception   {    JavaCompiler piler = ToolProvider getSystemJavaCompiler();    // 建立DiagnosticCollector对象    DiagnosticCollector diagnostics = new DiagnosticCollector();    StandardJavaFileManager fileManager = piler getStandardFileManager(diagnostics null null);    // 建立用于保存被编译文件名的对象    // 每个文件被保存在一个从JavaFileObject继承的类中    Iterable pilationUnits = fileManager     getJavaFileObjectsFromStrings(Arrays asList( test java ));    JavaCompiler CompilationTask task = piler getTask(null fileManager     diagnostics null null pilationUnits);    // 编译源程序    boolean success = task call();    fileManager close();    System out println((success)? 编译成功 : 编译失败 );   }   public static void main(String args[]) throws Exception   {    pilejava();   }  }

  如果想得到具体的编译错误 可以对Diagnostics进行扫描 代码如下

  for (Diagnostic diagnostic : diagnostics getDiagnostics())  System out printf(   Code: %s%n +   Kind: %s%n +   Position: %s%n +   Start Position: %s%n +   End Position: %s%n +   Source: %s%n +   Message: %s%n   diagnostic getCode() diagnostic getKind()   diagnostic getPosition() diagnostic getStartPosition()   diagnostic getEndPosition() diagnostic getSource()   diagnostic getMessage(null));  被编译的test java代码如下   public class test  {   public static void main(String[] args) throws Exception   {    aa; //错误语句    System out println( JavaCompiler测试成功! );   }  }

  在这段代码中多写了个aa 得到的编译错误为

  Code: piler err not stmt  Kind: ERROR  Position:   Start Position:   End Position:   Source: test java  Message: test java: : 不是语句  Success: false

  通过JavaCompiler进行编译都是在当前目录下生成 class文件 而使用编译选项可以改变这个默认目录 编译选项是一个元素为String类型的Iterable集合 如我们可以使用如下代码在D盘根目录下生成 class文件

  Iterable options = Arrays asList( d d:\\ );  JavaCompiler CompilationTask task = piler getTask(null fileManager   diagnostics options null pilationUnits);

  在上面的例子中options处的参数为null 而要传递编译器的参数 就需要将options传入

  有时我们编译一个Java源程序文件 而这个源程序文件需要另几个Java文件 而这些Java文件又在另外一个目录 那么这就需要为编译器指定这些文件所在的目录

  Iterable options = Arrays asList( sourcepath d:\\src );

  上面的代码指定的被编译Java文件所依赖的源文件所在的目录

lishixinzhi/Article/program/Java/hx/201311/27239




AVA到底要多好的配置才不卡?
处理器英特尔 Pentium(奔腾) 双核 T3200 @ 2.00GHz 笔记本处理器 主板华硕 A8Se (英特尔 PM965\/GM965\/GL960\/GS965 - ICH8M 笔记本芯片组)内存2 GB ( 海力士 DDR2 667MHz )主硬盘日立 HTS542525K9SA00 ( 250 GB \/ 5400 转\/分 )显卡ATI Mobility Radeon HD 3470 ( 256 MB \/ 华硕 )显...

AVA配置花费
内存 金士顿 2GB DDR3 1600(阿凡达单通道骇 2 ¥ 390 硬盘 希捷 1TB SATA2 32M 7200.12\/ST310005 1 ¥ 520 显卡 影驰 9800GT+中将版 1 ¥ 699 光驱 先锋 DVR-118CHV 1 ¥ 188 LCD LG W1942SP 1 ¥ 899 机箱 酷冷至尊 毁灭者RC-K100 1 ¥ 299 电源 航嘉 多核DH6 1 ¥ 360 键鼠装...

虹光AVA6基本参数
虹光AVA6是一款专为商业应用设计的平板式扫描仪,其最大幅面达到A6规格。扫描元件采用了彩色CCD,保证了图像的清晰度。光学分辨率高达600x1200dpi,无论是文档还是证件都能轻松扫描,满足多样化的需求。扫描速度根据不同模式有所差异,黑白模式在200dpi下只需6.1秒,而彩色模式在150dpi下则为3.8秒,效率...

CSOL和CF还有AVA哪个好玩,我是上班族
再来说人物,CSOL人物种类也比CF多,女人物更是出的一个比一个漂亮,到目前女人物已有6个,男的除了经典的CS单机人物外,还多加了6个其他男性人物。枪支更不用说了,CS单机的枪支可能没CF多,但CSOL枪支绝对比CF多,光狙就有十几种,而且有像MG3毁灭者和M134终结者的重型机枪,你可能会说CF也有加特林机枪了,我说完全...

AVA厚重防弹衣跟突袭防弹衣哪件更好
吸收能力和耐久度都是补给防弹衣的150%,对于没把握自己选择的对手是否符合自己防弹衣时推荐使用 资料地址: http:\/\/www.google.cn\/search?client=aff-cs-360se&forid=1&ie=utf-8&oe=UTF-8&q=AVA%E5%8E%9A%E9%87%8D%E9%98%B2%E5%BC%B9%E8%A1%A3%E8%B7%9F%E7%AA%81%E8%A2%AD%E...

Java JDK版本的发展?
2、发布日期从1997年9月12日至2011年7月28日的,其版本号及名称变迁如下:JDK 1.1.4、JDK 1.1.5、JDK 1.1.6、JDK 1.1.7、JDK 1.1.8、J2SE 1.2、J2SE 1.2.1、J2SE 1.2.2、J2SE 1.3、J2SE 1.3.1、J2SE 1.4.0、J2SE 1.4.1、J2SE 1.4.2、J2SE 5.0、Java SE 6、...

配台能够玩AVA不卡的电脑
主板 华硕 P5QL SE 1 ¥ 590 内存 金士顿 2GB DDR2 800(窄板) 1 ¥ 335 硬盘 希捷 500GB 7200.12 16M(串口\/散)ST3 1 ¥ 335 显卡 七彩虹 逸彩250-GD3 冰封骑士3F 1G M08 1 ¥ 849 电源 长城 静音大师BTX-400SD 1 ¥ 268 光驱+机箱300 共3300 我现大用的 玩AVA 不卡 FPS180 吧...

怎么才能跳过AVA的显卡扫描
首先在配置检测里面调成低特效,多启动几次然后再选用普通特效(普通可以运行的话)它就不会再提示你了

我主玩大型网络游戏 比如穿越火线 AVA 魔域等等 想组装个电脑在4200...
这2套配置整体的搭配不错 给你做个参考 C P U AMD 羿龙X3 8450(盒) 620 散热器 盒装自带 - 主 板 华硕 M3N78 SE 499 显 卡 影驰GTS250加强版 699 内 存 金士顿 2GB DDR3 1333 290 硬 盘 日立 320G 7200转 16M(串口\/3年盒) 320 显示器 三星 943SN 790 光 驱...

我的配置可以流畅玩AVA吗
可以啊 AVA要求很低的 比CF好一点 首先,CPU定义是双核,怎么判断是双核呢,很简单,CTRL+ALT+DEL三个按键按下去,在"性能"这一栏中,有个CPU使用记录,单核就是一个,如果有两个框,OK,就是双核,三个就是AMD三核CPU,四个就是intelQ级别的四核CPU,如果你这里还看不懂,再换个地方,桌面...

忻州市15582684896: java 调用编译器 -
逄适替卡: 根本就不知道你要做什么,脑子里一片混乱.eclipse不是编译器,那个叫集成开发环境(IDE).如果你的程序是java程序,直接调用内建的com.sun.tools.javac.*就可以.如果你要做编译器,可能还要学个几年. --------------------------------------------- 你要做的事情我明白了,不过要运行java程序还是比较麻烦的.这个里面有些代码的例子:http://www.rgagnon.com/javadetails/java-0014.html 不过实际上能够考虑比较多的情况的代码大约需要上万行.我做了好几年还是没有完全完成.

忻州市15582684896: java程序中如何调用外部编译器编译并运行项目文件夹下单独的一个.java文件(Eclipse) -
逄适替卡: exec()方法需要抛出异常,需用try,catch语句处理.

忻州市15582684896: 编写一个java的编辑软件 怎么调用javac编译器编译JTextArea里的代码 -
逄适替卡: JAVAC 编译是以一个public类型的 class 为单位的.所以,搜索 JTextArea 里面的内容,如果有且仅有一个public的class,则以这个class的名字输出一个.java的文件到目录,然后调用Runtime的exec方法执行 javac 跟上 java 文件名.exec方法返回一个Process ,可以 getInputStream().返回的就是执行命令行的结果.可以显示这个结果就能看到编译的情况.不过既然是java的编辑软件,要做好的话至少得还有关键字高亮等等不同的颜色区分.也得有java的语法分析功能,实时的提示一些语法错误.这个工作量很多啊.

忻州市15582684896: java程序编译时怎么调用编译好的class文件 -
逄适替卡: import 导入后直接可以用吧!!..要在同一个包内.

忻州市15582684896: 如何使用命令行编译以及运行java文件 -
逄适替卡: 方法/步骤 我们先新建文本文档,输入自己的java程序.这里我写一个简单的java程序,来做示范.import java.util.*; public class HelloDate{ public static void main(String[] args){ System.out.println("Hello,it's:"); System.out.println(new Date()); } } ...

忻州市15582684896: java编译后 产生两个class文件 怎么调用 -
逄适替卡: 这种情况是由于sender是chatclient的内部类决定的~直接java chatclient就行

忻州市15582684896: Java中的super、函数和方法如题 谢谢了 -
逄适替卡: 函数和方法就是一回事 你在这里super根本调不到x参数的任何方法,普通方法就是用super. 但是构造方法不一样,构造方法在定义的时候有一个非常死的规定就是方法名字必须和类名字...

忻州市15582684896: 怎么用cmd编译java程序 -
逄适替卡: 1.先新建文本文档,输入自己的java程序.这里我写一个简单的java程序,来做示范.import java.util.*; public class HelloDate{ public static void main(String[] args){ System.out.println("Hello,it's:"); System.out.println(new Date()); } }2.然后另存为一...

忻州市15582684896: java中public double speed 和 double speed是一样的吗? -
逄适替卡: 不一样,前者任何调用的类都可以使用此方法;后者调用的类必须和该类在同一包中,否则不能调用这个方法,编译器会报错

忻州市15582684896: jdk的所有命令,比如javac java javadoc 等的具体使用 -
逄适替卡: JDK 常用命令 JDK 后,JAVAHOME 下会出现许多可执行的 exe 文件,它们的用途如下: 文件,它们的用途如下: javac:Java 编译器,将 Java 源代码换成字节代 : 编译器, java:Java 解释器e69da5e887aa7a686964616f31333330346532,...

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网