|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
但是对于JAVA技术类的学习,我觉得大课堂反而会影响自身独立思考的过程,因为上课的时候,老师讲课的速度很快为了不遗漏要点,通常会仔细的听,编译|程序|静态在SunJDK1.2及后续版本中,包括了一组可在程序运转时候编译和实行Java代码的API。这些API被包括在tools.jar类库中。这个功效同意Java程序在运转时静态编译、实行小的代码块,在有些情形下这个功效会让Java使用程序的架构加倍天真、开放。
本文假定读者已在盘算机中安装并设置好了SunJDK1.2或更高的版本,并对javac编译器命令有所懂得。
在Java程序中利用编译器
假定要利用javac命令编译/home/mytest目次下Test.java文件,并设定class文件寄存在/home/mytest/classes路径下,输出上面命令:
javac-d/home/mytest/classesTest.java
到达一样的目标,也能够利用Sun供应的一个Java编译器的API来完成。它的利用也很复杂,中心代码段以下:
…
String[]args=newString[]{“-d”,“/home/mytest/classes”,“Test.java”};
Intstatus=javac.compile(args);
…
javac编译工具被安装在JDK根目次的/bin目次下,卖力将源代码编译成运转于JVM的字节码。现实上,我们常常利用/bin目次下的javac编译工具来编译Java源文件。假如在Java程序中静态编译恣意制订的Java语句,利用这个内部的javac编译器就显得不敷天真了。固然偶然可以使用Runtime类来实行一个内部命令,但假如想晓得代码是不是被编译经由过程、编译时产生了甚么毛病,用Runtime类的exec()办法就很难完成了。
在Sun的JDK1.2及后续版本中,JDK安装路径的/lib路径下包括了一个tools.jar文件,这个类库包括了一个完全的编译器包。com.sun.tools.javac.Main是编译器的主类出口,假如已熟习了javac编译器命令行的利用办法,很简单了解这个类的利用办法。办法compile(String[]p)实行编译举措,参数p是一个String数组,用来寄存javac命令的参数选项,编译后的形态前往一个Int值,其对应值参考以下表所示:
表形态参数与对应值
EXIT_OK0
EXIT_ERROR1
EXIT_CMDERR2
EXIT_SYSERR3
EXIT_ABNORMAL4
在程序实行时编译和实行Java语句
从下面一段中,我们已基础懂得了静态编译一个Java文件的办法。那末,怎样运转时静态编译指定的Java语句呢?这里必要一个技能。
假定要静态编译的Java条语句以下:
System.out.println(“Hello,Thisruntimecode!”);
编译器不撑持编译单个Java语句,被编译的对象必需是一个以.java为后缀的、布局正当的类源程叙文件,以是必要对这个语句举行改革,酿成一个完全的类,并把这条语句置进main办法中,便于测试。
publicclass<一时类文件名>{
publicstaticvoidmain(String[]args)throwsException{
System.out.println(“Hello,Thisruntimecode!”);
}
}
如许,欲静态编译的代码已被程序静态拼装成了下面那段代码,筹办事情还没有停止,不外看起来事情在趋势略微的庞大化。由于上述代码以后还寄存在内存中,编译器仿佛对一个硬盘文件更感乐趣。我们必要援用java.io.File类(JDK1.2以上),创立一个一时的文件来寄存上述代码的内容。java.io.File类的静态办法createTempFile()办法包管所创立的文件名是不反复的,如许会增年夜这段程序的天真性。天真性取决于真正使用到体系架构中的战略。
System.getProperty(“user.dir”)用来取得以后路径,在这里作为一时文件的寄存目次。
Filefile;
file=File.createTempFile(“JavaRuntime”,“.java”,newFile(System.getProperty(“user.dir”)));
Stringfilename=file.getName();
Stringclassname=getClassName(filename);
//将代码输入到文件
PrintWriterout=newPrintWriter(newFileOutputStream(file));
out.println(“publicclass”+classname+“{”};
out.println(“..代码..”);
out.println(“}”);
//封闭文件流
out.flush();
out.close();
我们商定被创立的一时文件名以“JavaRuntime”为头缀(可恣意定名),后缀名以“.java”开头。一个待编译的Java源文件已主动态天生。下一步要从com.sun.tools.javac包中创立一个Main实例,挪用javac.compile()办法编译这个一时文件:
Privatestaticcom.sun.tools.javac.Mainjavac=newcom.sun.tools.javac.Main();
String[]args=newString[]{“-d”,System.getProperty(“user.dir”),filename};
Intstatus=javac.compile(args);
假定一时文件经由过程了编译器文法考证等考证,编译乐成(status值即是0,参看前表),在以后程序的运转目次下就会多了一个Java类文件。我们将经由过程实行这个Java类文件,来摹拟实行欲静态编译代码的了局。
Java供应在运转时候加载类的特征,可静态辨认和挪用类机关办法、类字段和类办法。java.lang.reflect.Method完成了Member接口,能够挪用接口的办法来取得办法类的称号、润色词等。办法getRuturnType()、getParameterTypes()、getExeptionTypess()等前往被暗示办法的机关信息。Method另外一个主要的特征是能够挪用invoke()实行这个办法(具体利用办法能够检察java.lang.reflect包文档)。上面这段代码中创立一个java.lang.reflect.Method类办法,挪用getMethod()办法取得被拼装的main办法的映照,这段代码以下:
try{
//会见这个类
Classcls=Class.forName(classname);
//挪用main办法
Methodmain=cls.getMethod(“main”,newClass[]{String[].class});
main.invoke(null,newObject[]{newString[0]});
}catch(SecurityExceptionse){
debug(“accesstotheinformationisdenied:”+se.toString());
}catch(NoSuchMethodExceptionnme){
debug(“amatchingmethodisnotfoundorifthennameisor:
”+nme.toString());
}catch(InvocationTargetExceptionite){
debug(“Exceptioninmain:”+ite.getTargetException());
}catch(Exceptione){
debug(e.toString());
}
运转了局参以下:
Hello,Thisruntimecode!
树模程序
上面给出了一个复杂的Java程序,这个程序申明了怎样使用Sun的javac编译器完成静态编译Java语句。运转该程序必要盘算机安装JDK1.2以上版本,并在classpath中或运转时指定tools.jar文件地位。
程序布局:
◆compile()编译Java代码,前往天生的一时文件;
◆run()运转编译的class文件;
◆debug()输入调试信息;
◆getClassName()从一个Java源文件取得类名;
◆readLine()从把持台读取用户输出的JavaCode。
Importjava.io.File;
…
PublicclassRuntimeCode{
/**编译器*/
privatestaticcom.sun.tools.javac.Mainjavac=newcom.sun.tools.javac.Main();
/**守候用户输出JavaCode,然后编译、实行*/
publicstaticvoidmain(String[]args)throwsException{
…
run(compile(code));
}
/**编译JavaCode,前往一时文件对象*/
privatesynchronizedstaticFilecompile(Stringcode)
throwsIOException,Exception{
Filefile;
//在用户以后文件目次创立一个一时代码文件
file=File.createTempFile(“JavaRuntime”,“.java”,
newFile(System.getProperty(“user.dir”)));
//当假造机加入时,删除此一时java源文件
file.deleteOnExit();
//取得文件名和类名字
Stringfilename=file.getName();
Stringclassname=getClassName(filename);
//将代码输入到文件
PrintWriterout=newPrintWriter(newFileOutputStream(file));
out.println(“/**”);
…
//封闭文件流
out.flush();
out.close();
//编译代码文件
String[]args=newString[]{“-d”,System.getProperty(“user.dir”),filename};
//前往编译的形态代码
intstatus=javac.compile(args);
//处置编译形态
…
}
/**实行方才编译的类文件*/
privatestaticsynchronizedvoidrun(Filefile)
…
//当假造机加入时,删除此一时编译的类文件
newFile(file.getParent(),classname+“.class”).deleteOnExit();
try{
//会见这个类
Classcls=Class.forName(classname);
//映照main办法
Methodmain=cls.getMethod(“main”,newClass[]{String[].class});
//实行main办法
main.invoke(null,newObject[]{newString[0]});
}catch(SecurityExceptionse){
…
}
}
/**打印调试信息*/
privatestaticvoiddebug(Stringmsg){
System.err.println(msg);
}
/**依据一个java源文件名取得类名*/
privatestaticStringgetClassName(Stringfilename){
returnfilename.substring(0,filename.length()-5);
}
/**从把持台取得用户输出的Java代码段*/
…
}
编译运转上述代码,在pleaseinputjavacode提醒下输出以下代码:
for(inti=0;i<10;i++){System.out.println(“thisis:”+i);}
运转了局以下所示:
Pleaseinputjavacode:
for(inti=0;i<10;i++){System.out.println(“thisis:”+i);}
wait....
--------------------
thisis:0
thisis:1
thisis:2
thisis:3
thisis:4
thisis:5
thisis:6
thisis:7
thisis:8
thisis:9
总结
在年夜中型企业使用体系平台中,利用代码静态编译手艺分离OO编程模子,可在体系不菪机前提下包管体系的可扩大性和伸缩性。假如你是一个Java程序员,略加调剂以上代码,还能够匡助调试小段的Java代码.
对于一个大型项目,如果用java来作,可能需要9个月,并且可能需要翻阅10本以上的书,但如果用ruby来作,3个月,3本书就足够了,而.net也不过3,4本书足以,这就是区别。 |
|