|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
j2EE和asp比较,其实也没什么比的,原因和我上面说那些比较差不了多少,也是稳定性,安全性,J2EE比asp高,速度上比不过asp,asp也是延续着它的拖拽控件的方法,提高速度。 在良多Java使用中必要在程序中挪用Java编译器来编译和运转。但在初期的版本中(JavaSE5及之前版本)中只能经由过程tools.jar中的com.sun.tools.javac包来挪用Java编译器,但因为tools.jar不是尺度的Java库,在利用时必需要设置这个jar的路径。而在JavaSE6中为我们供应了尺度的包来操纵Java编译器,这就是javax.tools包。利用这个包,我们能够不必将jar文件路径增加到classpath中了。
1、利用JavaCompiler接口来编译Java源程序
利用JavaAPI来编译Java源程序有良多办法,如今让我们来看一种最复杂的办法,经由过程JavaCompiler举行编译。
我们能够经由过程ToolProvider类的静态办法getSystemJavaCompiler来失掉一个JavaCompiler接口的实例。
JavaCompilercompiler=ToolProvider.getSystemJavaCompiler();
JavaCompiler中最中心的办法是run。经由过程这个办法能够编译java源程序。这个办法有3个流动参数和1个可变参数(可变参数是从JaveSE5入手下手供应的一个新的参数范例,用type…argu暗示)。前3个参数分离用来为java编译器供应参数、失掉Java编译器的输入信息和吸收编译器的毛病信息,前面的可变参数能够传进一个或多个Java源程叙文件。假如run编译乐成,前往0。
intrun(InputStreamin,OutputStreamout,OutputStreamerr,String...arguments)
假如前3个参数传进的是null,那末run办法将以尺度的输出、输入取代,即System.in、System.out和System.err。假如我们要编译一个test.java文件,并将利用尺度输出输入,run的利用办法以下:
intresults=tool.run(null,null,null,"test.java");
上面是利用JavaCompiler的完全代码:
importjava.io.*;
importjavax.tools.*;
publicclasstest_compilerapi
{
publicstaticvoidmain(Stringargs[])throwsIOException
{
JavaCompilercompiler=ToolProvider.getSystemJavaCompiler();
intresults=compiler.run(null,null,null,"test.java");
System.out.println((results==0)?"编译乐成":"编译失利");
//在程序中运转test
Runtimerun=Runtime.getRuntime();
Processp=run.exec("javatest");
BufferedInputStreamin=newBufferedInputStream(p.getInputStream());
BufferedReaderbr=newBufferedReader(newInputStreamReader(in));
Strings;
while((s=br.readLine())!=null)
System.out.println(s);
}
}
publicclasstest
{
publicstaticvoidmain(String[]args)throwsException
{
System.out.println("JavaCompiler测试乐成!");
}
}
编译乐成的输入了局:
编译乐成
JavaCompiler测试乐成
编译失利的输入了局:
test.java:9:找不到标记
标记:办法printlnln(java.lang.String)
地位:类java.io.PrintStream
System.out.printlnln("JavaCompiler测试乐成!");
^
1毛病
编译失利
2、利用StandardJavaFileManager编译Java源程序
在第一部分我们会商挪用java编译器的最简单的办法。这类办法能够很好地事情,但它确不克不及更无效地失掉我们所必要的信息,如尺度的输出、输入信息。而在JavaSE6中最好的办法是利用StandardJavaFileManager类。这个类能够很好地把持输出、输入,而且能够经由过程DiagnosticListener失掉诊断信息,而DiagnosticCollector类就是listener的完成。
利用StandardJavaFileManager必要两步。起首创建一个DiagnosticCollector实例和经由过程JavaCompiler的getStandardFileManager()办法失掉一个StandardFileManager对象。最初经由过程CompilationTask中的call办法编译源程序。
在利用这类办法挪用Java编译时最庞大的办法就是getTask,上面让我们会商一下getTask办法。这个办法有以下所示的6个参数。
getTask(Writerout,JavaFileManagerfileManager,
DiagnosticListener<?superJavaFileObject>diagnosticListener,
Iterable<String>options,
Iterable<String>classes,
Iterable<?extendsJavaFileObject>compilationUnits)
这些参数年夜多半都可为null。它们的寄义所下。
·out::用于输入毛病的流,默许是System.err。
·fileManager::尺度的文件办理。
·diagnosticListener:编译器的默许举动。
·options:编译器的选项
·classes:介入编译的class。
最初一个参数compilationUnits不克不及为null,由于这个对象保留了你想编译的Java文件。
在利用完getTask后,必要经由过程StandardJavaFileManager的getJavaFileObjectsFromFiles或getJavaFileObjectsFromStrings办法失掉compilationUnits对象。挪用这两个办法的体例以下:.
Iterable<?extendsJavaFileObject>getJavaFileObjectsFromFiles(
Iterable<?extendsFile>files)
Iterable<?extendsJavaFileObject>getJavaFileObjectsFromStrings(
Iterable<String>names)
String[]filenames=…;
Iterable<?extendsJavaFileObject>compilationUnits=
fileManager.getJavaFileObjectsFromFiles(Arrays.asList(filenames));
JavaCompiler.CompilationTasktask=compiler.getTask(null,fileManager,
diagnostics,options,null,compilationUnits);
最初必要封闭fileManager.close();
上面是一个完全的演示程序。
importjava.io.*;
importjava.util.*;
importjavax.tools.*;
publicclasstest_compilerapi
{
privatestaticvoidcompilejava()throwsException
{
JavaCompilercompiler=ToolProvider.getSystemJavaCompiler();
//创建DiagnosticCollector对象
DiagnosticCollector<JavaFileObject>diagnostics=newDiagnosticCollector<JavaFileObject>();
StandardJavaFileManagerfileManager=compiler.getStandardFileManager(diagnostics,null,null);
//创建用于保留被编译文件名的对象
//每一个文件被保留在一个从JavaFileObject承继的类中
Iterable<?extendsJavaFileObject>compilationUnits=fileManager
.getJavaFileObjectsFromStrings(ArraysasList("test3.java"));
JavaCompiler.CompilationTasktask=compiler.getTask(null,fileManager,
diagnostics,null,null,compilationUnits);
//编译源程序
booleansuccess=task.call();
fileManager.close();
System.out.println((success)?"编译乐成":"编译失利");
}
publicstaticvoidmain(Stringargs[])throwsException
{
compilejava();
}
}
假如想失掉详细的编译毛病,能够对Diagnostics举行扫描,代码以下:
for(Diagnosticdiagnostic:diagnostics.getDiagnostics())
System.out.printf(
"Code:%s%n"+
"Kind:%s%n"+
"Position:%s%n"+
"StartPosition:%s%n"+
"EndPosition:%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代码以下:
publicclasstest
{
publicstaticvoidmain(String[]args)throwsException
{
aa;//毛病语句
System.out.println("JavaCompiler测试乐成!");
}
}
在这段代码中多写了个aa,失掉的编译毛病为:
Code:compiler.err.not.stmt
Kind:ERROR
Position:89
StartPosition:89
EndPosition:89
Source:test.java
Message:test.java:5:不是语句
Success:false
经由过程JavaCompiler举行编译都是在以后目次下天生.class文件,而利用编译选项能够改动这个默许目次。编译选项是一个元素为String范例的Iterable汇合。如我们可使用以下代码在D盘根目次下天生.class文件。
Iterable<String>options=Arrays.asList("-d","d:");
JavaCompiler.CompilationTasktask=compiler.getTask(null,fileManager,
diagnostics,options,null,compilationUnits);
在下面的例子中options处的参数为null,而要传送编译器的参数,就必要将options传进。
偶然我们编译一个Java源程叙文件,而这个源程叙文件必要另几个Java文件,而这些Java文件又在别的一个目次,那末这就必要为编译器指定这些文件地点的目次。
Iterable<String>options=Arrays.asList("-sourcepath","d:src");
下面的代码指定的被编译Java文件所依附的源文件地点的目次。
3、从内存中编译
JavaCompiler不但能够编译硬盘上的Java文件,并且还能够编译内存中的Java代码,然后利用reflection来运转它们。我们能够编写一个JavaSourceFromString类,经由过程这个类能够输出Java源代码。一但创建这个对象,你能够向个中输出恣意的Java代码,然后编译和运转,并且无需向硬盘上写.class文件。
importjava.lang.reflect.*;
importjava.io.*;
importjavax.tools.*;
importjavax.tools.JavaCompiler.CompilationTask;
importjava.util.*;
importjava.net.*;
publicclasstest_compilerapi
{
privatestaticvoidcompilerJava()throwsException
{
JavaCompilercompiler=ToolProvider.getSystemJavaCompiler();
DiagnosticCollector<JavaFileObject>diagnostics=newDiagnosticCollector<JavaFileObject>();
//界说一个StringWriter类,用于写Java程序
StringWriterwriter=newStringWriter();
PrintWriterout=newPrintWriter(writer);
//入手下手写Java程序
out.println("publicclassHelloWorld{");
out.println("publicstaticvoidmain(Stringargs[]){");
out.println("System.out.println("Hello,World");");
out.println("}");
out.println("}");
out.close();
//为这段代码取个名子:HelloWorld,以便今后利用reflection挪用
JavaFileObjectfile=newJavaSourceFromString("HelloWorld",writer.toString());
Iterable<?extendsJavaFileObject>compilationUnits=Arrays.asList(file);
JavaCompiler.CompilationTasktask=compiler.getTask(null,null,
diagnostics,null,null,compilationUnits);
booleansuccess=task.call();
System.out.println("Success:"+success);
//假如乐成,经由过程reflection实行这段Java程序
if(success)
{
System.out.println("-----输入-----");
Class.forName("HelloWorld").getDeclaredMethod("main",newClass[]
{String[].class}).invoke(null,newObject[]
{null});
System.out.println("-----输入-----");
}
}
publicstaticvoidmain(Stringargs[])throwsException
{
compilerJava();
}
}
//用于传送源程序的JavaSourceFromString类
classJavaSourceFromStringextendsSimpleJavaFileObject
{
finalStringcode;
JavaSourceFromString(Stringname,Stringcode)
{
super(URI.create("string:///"+name.replace(".","/")+Kind.SOURCE.extension),Kind.SOURCE);
this.code=code;
}
@Override
publicCharSequencegetCharContent(booleanignoreEncodingErrors)
{
returncode;
}
}
来自:http://dev.yesky.com/451/3039451.shtml
什么时候上述的三种开发工具能和三为一,什么时候java的竞争力才更强,才有机会拉拢更多的程序员投入到对java的开发上,因为到时的开发工具将会比.net网页编程的更简单。还有一点也很关键,什么时候java推出的jsf能成为真正意义上的标准。 |
|