JDK6 新特性
JDK6新特性目录导航:
- Desktop类和SystemTray类
- JAXB2实现对象与XML之间的映射
- StAX
- Compiler API
- 轻量级 Http Server API
- 插入式注解处理API(Pluggable Annotation Processing API)
- 用Console开发控制台程序
- 对脚本语言的支持(如:ruby,groovy,javascript)
- Common Annotations
Desktop类和SystemTray类
JDK6在java.awt包下新增了两个类:Desktop和SystemTray
Desktop类:允许 Java 应用程序启动已在本机桌面上注册的关联应用程序来处理 URI 或文件。
Desktop类的主要方法:
1.browse(URI uri): 使用默认浏览器打开uri资源。
2.checkActionSupport(Action actionType): 检查是否支持的Action。
3.open(File file): 启动关联应用程序来打开文件。
4.edit(File file): 启动关联编辑器应用程序并打开一个文件编辑。
5.print(File file): 使用关联应用程序打印文件。
6.mail(): 启动用户默认邮件客户端的邮件组合窗口。
7.mail(URI mailtoURI): 启动用户默认邮件客户端的邮件组合窗口, 填充由 mailto:URI 指定的消息字段。
示例代码:
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.net.URI; public class Test {
public static void main(String[] args) throws IOException {
//先判断当前平台是否支持Desktop类
if (Desktop.isDesktopSupported()) {
//获取Desktop实例
Desktop desktop = Desktop.getDesktop();
//使用默认浏览器打开链接
desktop.browse(URI.create("http://www.cnblogs.com/peter1018"));
// 打开指定文件/文件夹
desktop.open(new File("D:\\")); //...... //其他方法可以自行演示...
}else {
System.out.println("当前平台不支持 Desktop类!");
} } }
SystemTray类:代表一个系统托盘桌面。在微软的Windows上,它被称为“任务栏”状态区域,在Gnome上,它被称为“通知”在KDE上,它被称为“系统托盘”。该系统托盘由在桌面上运行的所有应用程序共享。
SystemTray类的主要方法:
1.isSupported() : 检测系统是否支持SystemTray类。
2.getSystemTray() : 获得SystemTray实例。
1.add(TrayIcon trayIcon): 在“系统托盘”上添加一个“TrayIcon”。TrayIcon对象代表一个托盘图标,它可以有一个工具提示(文本),一个图像,一个弹出框菜单,以及一组与之相关的侦听器。托盘图标一旦出现,就会在系统托盘中显示。
2.remove(TrayIcon trayIcon): 删除指定的“TrayIcon”。
3.getTrayIcons(): 返回一个由这个托盘添加到托盘上的所有图标的数组应用程序。
4.getTrayIconSize(): 以像素为单位,返回在系统托盘中占据的一个托盘图标的大小。
5.addPropertyChangeListener(String propertyName,PropertyChangeListener listener): 将 PropertyChangeListener 添加到监听器
6.removePropertyChangeListener(String propertyName,PropertyChangeListener listener): 将PropertyChangeListener 从监听器移除
7.getPropertyChangeListeners(String propertyName) : 返回所有已关联的监听器数组
示例代码:
import javax.swing.*;
import java.awt.*; public class Test {
public static void main(String[] args) throws AWTException {
//先判断当前平台是否支持SystemTray类
if (SystemTray.isSupported()) {
//获取SystemTray实例
SystemTray systemTray = SystemTray.getSystemTray();
//获得托盘显示图标
ImageIcon imageIcon=new ImageIcon("D:\\icon.jpg");
//获得Image对象
Image icon=imageIcon.getImage();
//任务栏程序托盘图标
TrayIcon trayicon = new TrayIcon(icon,"JAVA系统托盘");
//关键点,设置托盘图标的自适应属性,这样才能在系统显示托盘处正常显示出需要的图片。
trayicon.setImageAutoSize(true);
//添加系统托盘
systemTray.add(trayicon);
//......
//其他方法可以自行演示...
//移除系统托盘
systemTray.remove(trayicon);
}else {
System.out.println("当前平台不支持 SystemTray类!");
} } }
展示结果如下:
JAXB2实现对象与XML之间的映射
JAXB是Java Architecture for XML Binding的缩写,可以将一个Java对象转变成为XML格式,反之亦然。我们把对象与关系数据库之间的映射称为ORM, 其实也可以把对象与XML之间的映射称为OXM(Object XML Mapping)。原来JAXB是Java EE的一部分,在JDK6中,SUN将其放到了Java SE中,这也是SUN的一贯做法。JDK6中自带的这个JAXB版本是2.0, 比起1.0(JSR 31)来,JAXB2(JSR 222)用JDK5的新特性Annotation来标识要作绑定的类和属性等,这就极大简化了开发的工作量。实际上,在Java EE 5.0中,EJB和Web Services也通过Annotation来简化开发工作。另外,JAXB2在底层是用StAX(JSR 173)来处理XML文档。
重要的注解和说明
注解 | 说明 |
@XmlRootElement |
将类或enum类型映射到XML元素,类名或名作为根节点 |
@XmlAttribute |
将JavaBean属性映射到XML属性 |
@XmlElement |
将JavaBean属性映射到源自属性名的XML元素 |
@XmlAnyAttribute |
将JavaBean属性映射到通配符属性的映射 |
@XmlAnyElement |
将JavaBean属性映射到XML infoset或JAXB |
@XmlElements |
一个用于多XmlElement注解的容器。 |
@XmlID |
将JavaBean属性映射到XML ID |
@XmlIDREF |
将JavaBean属性映射到XML IDREF |
@XmlList |
用来将一个属性映射到一个List |
@XmlSchema |
将包映射到XML名称空间 |
@XmlTransient |
该属性无需映射到XML |
示例代码:
Address类
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement; public class Address { @XmlAttribute
String province;
@XmlElement
String area;
@XmlElement
String street; public Address() {} public Address(String province, String area, String street) {
this.province = province;
this.area = area;
this.street = street;
} @Override
public String toString() {
return "Address{" +
"province='" + province + '\'' +
", area='" + area + '\'' +
", street='" + street + '\'' +
'}';
}
}
Person类
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement
public class Person{ @XmlAttribute
private String name; @XmlElement
private int age; @XmlElement
private Address address; public Person() {
} public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
} @Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", address=" + address +
'}';
}
}
测试类:
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException; public class Test {
public static void main(String[] args) throws JAXBException, IOException {
JAXBContext jaxbContext = JAXBContext.newInstance(Person.class); //根据Person对象转换为person.xml文件
Marshaller marshaller = jaxbContext.createMarshaller();
Address address = new Address("广东省","深圳市","宝安区");
Person person = new Person("niannianjiuwang", 20, address);
FileWriter fileWriter = new FileWriter("D:\\person.xml");
marshaller.marshal(person, fileWriter); //根据person.xml文件转换为对象
FileReader fileReader = new FileReader("D:\\person.xml");
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Person personNew = (Person) unmarshaller.unmarshal(fileReader);
System.out.println(personNew);
}
}
输出结果:
先看看person.xml文件:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<person name="niannianjiuwang">
<age>20</age>
<address province="广东省">
<area>深圳市</area>
<street>宝安区</street>
</address>
</person>
控制台结果:
Person{name='niannianjiuwang', age=20, address=Address{province='广东省', area='深圳市', street='宝安区'}}
StAX
StAX的来历 :
在JAXP1.3(JSR 206)有两种处理XML文档的方法:DOM(Document Object Model)和SAX(Simple API for XML).由于JDK6.0中的JAXB2(JSR 222)和JAX-WS 2.0(JSR 224)都会用到StAX所以Sun决定把StAX加入到JAXP家族当中来,并将JAXP的版本升级到1.4(JAXP1.4是JAXP1.3的维护版本). JDK6里面JAXP的版本就是1.4。
StAX简介:
StAX是Streaming API for XML的缩写,它包含在2004年3月的JSR 173 中。StAX是JDK6.0中包含的新特性。
在推式模型中,直到整个XML文件全部被解析,解析器才会产生解析事件。而拉式解析由应用程序来控制,也就是说解析事件由应用程序产生。这就意味着,你可以暂缓解析、解析时跳过某个元素或者同时解析多个文件。用DOM解析式要先将XML文件解析成DOM结构,因此降低了解析效率。使用StAX,解析事件在XML文件解析过程中产生。
下面是各种解析方法之间的比较:
Feature | StAX | SAX | DOM | TrAX |
API Type | Pull, streaming | Pull, streaming | In memory tree | XSLT Rule |
Ease of Use | High | Medium | High | Medium |
XPath Capability | No | No | Yes | Yes |
CPU and Memory Efficiency | Good | Good | Varies | Varies |
Forward Only | Yes | Yes | No | No |
Read XML | Yes | Yes | Yes | Yes |
Write XML | Yes | No | Yes | Yes |
Create, Read, Update, Delete | No | No | Yes | No |
StAX API同样也在JWSDP(Java Web Services Developer Pack )1.6中得到实现,你可以在包javax.xml.stream 中找到它。XMLStreamReader接口用来解析XML文件。XMLStreamWriter接口用来生成XML文件,XMLEventReader用一个对象事件迭代器来解析XML事件。与之相反,XMLStreamReader采用的是游标机制。
示例代码:
import javax.xml.stream.*;
import javax.xml.stream.events.XMLEvent;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream; public class Test {
public static void main(String[] args) throws FileNotFoundException, XMLStreamException {
writeXMLByStAX();//用XMLStreamWriter写xml文档
readXMLByStAX();//用XMLEventReader解析xml文档
} /**
* 通过StAX读XML
*/
private static void readXMLByStAX() throws XMLStreamException, FileNotFoundException {
XMLInputFactory xmlif = XMLInputFactory.newInstance();
XMLEventReader xmler = xmlif.createXMLEventReader(new FileInputStream("D:\\write.xml"));
XMLEvent event;
StringBuffer parsingResult = new StringBuffer();
while (xmler.hasNext()) {
event = xmler.nextEvent();
parsingResult.append(event.toString());
}
System.out.println(parsingResult);
} /**
* 通过StAX写XML
*/
private static void writeXMLByStAX() throws FileNotFoundException, XMLStreamException {
XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newFactory();
XMLStreamWriter xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(new FileOutputStream("D:\\write.xml")); // 写入默认的 XML 声明到xml文档
xmlStreamWriter.writeStartDocument();
// 写入注释到xml文档
xmlStreamWriter.writeComment("testing comment");
// 写入一个catalogs根元素
xmlStreamWriter.writeStartElement("catalogs");
xmlStreamWriter.writeNamespace("myUrl", "http://www.cnblogs.com/peter1018");
xmlStreamWriter.writeAttribute("name","niannianjiuwang");
// 写入子元素catalog
xmlStreamWriter.writeStartElement("http://www.cnblogs.com/peter1018", "catalog");
xmlStreamWriter.writeAttribute("id","StAX");
xmlStreamWriter.writeCharacters("Apparel");
// 写入catalog元素的结束标签
xmlStreamWriter.writeEndElement();
// 写入catalogs元素的结束标签
xmlStreamWriter.writeEndElement();
// 结束 XML 文档
xmlStreamWriter.writeEndDocument();
xmlStreamWriter.close();
}
}
输出结果:
write.xml文件内容:
<?xml version="1.0" ?><!--testing comment--><catalogs xmlns:myUrl="http://www.cnblogs.com/peter1018" name="niannianjiuwang"><myUrl:catalog id="StAX">Apparel</myUrl:catalog></catalogs>
控制台打印结果:
<?xml version="1.0" encoding='UTF-8' standalone='no'?><!--testing comment--><catalogs name='niannianjiuwang' xmlns:myUrl='http://www.cnblogs.com/peter1018'><['http://www.cnblogs.com/peter1018']:myUrl:catalog id='StAX'>Apparel</['http://www.cnblogs.com/peter1018']:myUrl:catalog></catalogs>ENDDOCUMENT
Compiler API
Java编程语言编译器javac读取以Java编程语言编写的源文件,并将它们编译为字节码class文件。或者,编译器也可以使用注解找到源文件和类文件并使用comiler API。编译器是一个命令行工具,但也可以使用Java compiler API调用。原话:(官网介绍)
我们可以用JDK6 的Compiler API(JSR 199)去动态编译Java源文件,Compiler API结合反射功能就可以实现动态的产生Java代码并编译执行这些代码,有点动态语言的特征。这个特性对于某些需要用到动态编译的应用程序相当有用, 比如JSP Web Server,当我们手动修改JSP后,是不希望需要重启Web Server才可以看到效果的,这时候我们就可以用Compiler API来实现动态编译JSP文件,当然,现在的JSP Web Server也是支持JSP热部署的,现在的JSP Web Server通过在运行期间通过Runtime.exec或ProcessBuilder来调用javac来编译代码,这种方式需要我们产生另一个进程去做编译工作,不够优雅而且容易使代码依赖与特定的操作系统;Compiler API通过一套易用的标准的API提供了更加丰富的方式去做动态编译,而且是跨平台的。
API Specification
- javax.annotation.processing - Annotation processing.
- javax.lang.model - Language model used in annotation processing and Compiler Tree API
- javax.lang.model.element - Language elements.
- javax.lang.model.type - Types.
- javax.lang.model.util - Language model utilities.
- javax.tools - Java Compiler API.
- com.sun.source.* - Compiler Tree API.
示例代码:(Tips:运行代码之前必须在D目录下存放TestObject.java文件)
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.IOException; public class Test {
public static void main(String[] args) throws IOException {
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager standardJavaFileManager = compiler.getStandardFileManager(null,null,null);
Iterable<? extends JavaFileObject> sourcefiles = standardJavaFileManager.getJavaFileObjects("D:\\TestObject.java");
compiler.getTask(null, standardJavaFileManager, null, null, null, sourcefiles).call();
standardJavaFileManager.close(); }
}
输出结果:会在D目录下生成TestObject.class文件。
轻量级 Http Server API
JDK6 提供了一个简单的Http Server API,据此我们可以构建自己的嵌入式Http Server,它支持Http和Https协议,提供了HTTP1.1的部分实现,没有被实现的那部分可以通过扩展已有的Http Server API来实现,必须自己实现HttpHandler接口,HttpServer会调用HttpHandler实现类的回调方法来处理客户端请求,我们把一个Http请求和它的响应称为一个交换,包装成HttpExchange类,HttpServer负责将HttpExchange传给 HttpHandler实现类的回调方法。
示例代码:
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler; import java.io.*; public class TestHandler implements HttpHandler { @Override
public void handle(HttpExchange httpExchange) throws IOException {
System.out.println("==进入Hadnler方法");
String responseMsg = "OK"; //响应信息
InputStream in = httpExchange.getRequestBody(); //获得输入流
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String temp = null;
while((temp = reader.readLine()) != null) {
System.out.println("client request:"+temp);
}
httpExchange.sendResponseHeaders(200, responseMsg.length()); //设置响应头属性及响应信息的长度
OutputStream out = httpExchange.getResponseBody(); //获得输出流
out.write(responseMsg.getBytes());
out.flush();
httpExchange.close();
}
}
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.spi.HttpServerProvider; import java.io.IOException;
import java.net.InetSocketAddress; public class Test {
public static void main(String[] args) throws IOException {
//启动服务,监听来自客户端的请求
HttpServerProvider provider = HttpServerProvider.provider();
//监听8888端口,能同时接受100个请求
HttpServer httpserver =provider.createHttpServer(new InetSocketAddress(8888), 100);
//将 /test 请求交给 TestHandler 处理器处理
httpserver.createContext("/test", new TestHandler());
httpserver.setExecutor(null);
httpserver.start();
System.out.println("server started");
}
}
输出结果:
server started
==进入Hadnler方法
==进入Hadnler方法
==进入Hadnler方法
插入式注解处理 API(Pluggable Annotation Processing API)
插入式注解处理API(JSR 269)提供一套标准API来处理Annotations(JSR 175)。实际上JSR 269不仅仅用来处理Annotation,它还建立了Java 语言本身的一个模型,它把method, package, constructor, type, variable, enum,,annotation等Java语言元素映射为Types和Elements, 从而将Java语言的语义映射成为对象,我们可以在javax.lang.model包下面可以看到这些类. 所以我们可以利用JSR 269提供的API来构建一个功能丰富的元编程(metaprogramming)环境。JSR 269用Annotation Processor在编译期间而不是运行期间处理Annotation, Annotation Processor相当于编译器的一个插件,所以称为插入式注解处理。如果Annotation Processor处理Annotation时(执行process方法)产生了新的Java代码,编译器会再调用一次Annotation Processor,如果第二次处理还有新代码产生,就会接着调用Annotation Processor,直到没有新代码产生为止。每执行一次process()方法被称为一个"round",这样整个Annotation processing过程可以看作是一个round的序列,JSR 269主要被设计成为针对Tools或者容器的API。
举个例子,我们想建立一套基于Annotation的单元测试框架(如TestNG),在测试类里面用Annotation来标识测试期间需要执行的测试方法,如下所示:
@TestMethod
public void testCheckName(){
//do something here
}
这时我们就可以用JSR 269提供的API来处理测试类,根据Annotation提取出需要执行的测试方法。
另一个例子是如果我们出于某种原因需要自行开发一个符合Java EE 5.0的Application Server(当然不建议这样做),我们就必须处理Common Annotations(JSR 250),Web Services Metadata(JSR 181)等规范的Annotations,这时可以用JSR 269提供的API来处理这些Annotations. 在现在的开发工具里面,Eclipse 3.3承诺将支持JSR 269
下面我用代码演示如何来用JSR 269提供的API来处理Annotations和读取Java源文件的元数据(metadata)
@SupportedAnnotationTypes("PluggableAPT.ToBeTested")//可以用"*"表示支持所有Annotations
@SupportedSourceVersion(SourceVersion.RELEASE_6)
public class MyAnnotationProcessor extends AbstractProcessor {
private void note(String msg) {
processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, msg);
}
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
//annotations的值是通过@SupportedAnnotationTypes声明的且目标源代码拥有的所有Annotations
for(TypeElement te:annotations){
note("annotation:"+te.toString());
}
Set<? extends Element> elements = roundEnv.getRootElements();//获取源代码的映射对象
for(Element e:elements){
//获取源代码对象的成员
List<? extends Element> enclosedElems = e.getEnclosedElements();
//留下方法成员,过滤掉其他成员
List<? extends ExecutableElement> ees = ElementFilter.methodsIn(enclosedElems);
for(ExecutableElement ee:ees){
note("--ExecutableElement name is "+ee.getSimpleName());
List<? extends AnnotationMirror> as = ee.getAnnotationMirrors();//获取方法的Annotations
note("--as="+as);
for(AnnotationMirror am:as){
//获取Annotation的值
Map<? extends ExecutableElement, ? extends AnnotationValue> map= am.getElementValues();
Set<? extends ExecutableElement> ks = map.keySet();
for(ExecutableElement k:ks){//打印Annotation的每个值
AnnotationValue av = map.get(k);
note("----"+ee.getSimpleName()+"."+k.getSimpleName()+"="+av.getValue());
}
}
}
}
return false;
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@interface ToBeTested{
String owner() default "Chinajash";
String group();
}
编译以上代码,然后再创建下面的Testing对象,不要编译Testing对象,我在后面会编译它
public class Testing{
@ToBeTested(group="A")
public void m1(){
}
@ToBeTested(group="B",owner="QQ")
public void m2(){
}
@PostConstruct//Common Annotation里面的一个Annotation
public void m3(){
}
}
下面我用以下命令编译Testing对象
javac -XprintRounds -processor PluggableAPT.MyAnnotationProcessor Testing.java
-XprintRounds表示打印round的次数,运行上面命令后在控制台会看到如下输出:
Round 1:
input files: {PluggableAPT.Testing}
annotations: [PluggableAPT.ToBeTested, javax.annotation.PostConstruct]
last round: false
Note: annotation:PluggableAPT.ToBeTested
Note: --ExecutableElement name is m1
Note: ")
Note: ----m1.group=A
Note: --ExecutableElement name is m2
Note: ", owner="QQ")
Note: ----m2.group=B
Note: ----m2.owner=QQ
Note: --ExecutableElement name is m3
Note: --as=@javax.annotation.PostConstruct
Round 2:
input files: {}
annotations: []
last round: true
本来想用JDK6.0的Compiler API来执行上面编译命令,可是好像现在Compiler API还不支持-processor参数,运行时总报以下错误
Exception in thread "main" java.lang.IllegalArgumentException: invalid flag: -processor PluggableAPT.MyAnnotationProcessor
调用Compiler API的代码是这样的
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> sourcefiles = fileManager.getJavaFileObjects("Testing.java");
Set<String> options = new HashSet<String>();
options.add("-processor PluggableAPT.MyAnnotationProcessor");
compiler.getTask(null, fileManager, null, options, null, sourcefiles).call();
不知道这是不是Compiler API的一个bug。
用Console开发控制台程序
JDK6中提供 了java.io.Console类专用来访问基于字符的控制台设备。程序如果要与Windows下的cmd或者Linux下的Terminal交互,就可以用Console类代劳。但我们不总是能得到可用的Console,一个JVM是否有可用的Console依赖于底层平台和JVM如何被调用。如果JVM是在交互式命令行(比如Windows的cmd)中启动的,并且输入输出没有重定向到另外的地方,那么就可以得到一个可用的Console实例 。
Console类:
示例代码:
import java.io.Console; public class Test {
public static void main(String[] args){
Console console = System.console();
if(console!=null){//判断console是否可用
String user = new String(console.readLine("Enter user:")); //读取整行字符
String pwd = new String(console.readPassword("Enter passowrd:")); //读取密码,密码输入时不会显示
console.printf("User is:"+user+"/n");
console.printf("Password is:"+pwd+"/n");
}else{
System.out.println("JVM无法使用当前的Console");
}
}
}
在IntelliJ IDEA 中直接运行执行结果:
JVM无法使用当前的Console
在cmd里面直接 java Test 结果:红色字体是输入部分,密码后面输入默认是隐藏的
F:\test\>java Test
Enter user:niannianjiuwang
Enter passowrd:
User is:niannianjiuwang/nPassword is:123456/n
对脚本语言的支持(如: ruby, groovy, javascript)
JDK6增加了对脚本语言的支持(JSR 223),原理上是将脚本语言编译成字节码,这样脚本语言也能享用Java平台的诸多优势,包括可移植性,安全等,另外,由于现在是编译成字节码后再执行,所以比原来边解释边执行效率要高很多。加入对脚本语言的支持后,对
Java语言也提供了以下好处。
1、许多脚本语言都有动态特性,比如,你不需要用一个变量之前先声明它,你可以用一个变量存放完全不同类型的对象,你不需要做强制类型转换,因为转换都是自动的。现在Java语言也可以通过对脚本语言的支持间接获得这种灵活性。
2、可以用脚本语言快速开发产品原型,因为现在可以Edit-Run,而无需Edit-Compile-Run,当然,因为Java有非常好的IDE支持,我 们完全可以在IDE里面编辑源文件,然后点击运行(隐含编译),以此达到快速开发原型的目的,所以这点好处基本上可以忽略。
3、通过引入脚本语言可以轻松实现Java应用程序的扩展和自定义,我们可以把原来分布在在Java应用程序中的配置逻辑,数学表达式和业务规则提取出来,转用JavaScript来处理。
Sun的JDK6实现包含了一个基于Mozilla Rhino的 脚本语言引擎,支持JavaScript,这并不是说明JDK6只支持JavaScript,任何第三方都可以自己实现一个JSR-223兼容的脚本引擎 使得JDK6支持别的脚本语言,比如,你想让JDK6支持Ruby,那你可以自己按照JSR 223的规范实现一个Ruby的脚本引擎类,具体一点,你需要实现 javax.script.ScriptEngine(简单起见,可以继承 javax.script.AbstractScriptEngine) 和 javax.script.ScriptEngineFactory 两个接口。当然,在你实现自己的脚本语引擎之前,先到 scripting.dev.java.net project 这里看看是不是有人已经帮你做了工作,这样你就可以直接拿来用。
Scripting API
Scripting API是用于在Java里面编写脚本语言程序的API, 在Javax.script中可以找到Scripting API,我们就是用这个API来编写JavaScript程序,这个包里面有一个ScriptEngineManager类,它是使用Scriptng API 的入口,ScriptEngineManager可以通过Jar服务发现(service discovery)机制寻找合适的脚本引擎类(ScriptEngine),使用Scripting API的最简单方式只需下面三步
1、创建一个ScriptEngineManager对象
2、通过ScriptEngineManager获得ScriptEngine对象
3、用ScriptEngine的eval方法执行脚本
示例代码:
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager; public class Test {
public static void main(String[] args){
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("JavaScript");
String script;
try {
script = "print('Hello')";
engine.eval(script);// 执行脚本
script = "1-23*9/3+77";
System.out.println(engine.eval(script).toString());// 不用对字符串做解析便可得到算式结果
engine.put("a", "一个字符串");
script = "print(a)";
engine.eval(script);// 脚本调用java对象
script = "function hello(name) { return 'Hello,' + name;}";
engine.eval(script);
Invocable inv = (Invocable) engine;
System.out.println(inv.invokeFunction("hello", "Scripting"));//java调用脚本方法
} catch (Exception e) {
e.printStackTrace();
}
} }
输出结果:
Hello
9
一个字符串
Hello,Scripting
Common Annotations
Common annotations原本是Java EE 5.0(JSR 244)规范的一部分,现在SUN把它的一部分放到了Java SE 6.0中。随着Annotation元数据功能(JSR 175)加入到Java SE 5.0里面,很多Java 技术(比如EJB,Web Services)都会用Annotation部分代替XML文件来配置运行参数(或者说是支持声明式编程,如EJB的声明式事务), 如果这些技术为通用目的都单独定义了自己的Annotations,显然有点重复建设, 所以,为其他相关的Java技术定义一套公共的Annotation是有价值的,可以避免重复建设的同时,也保证Java SE和Java EE 各种技术的一致性。
下面列举出Common Annotations 1.0里面的10个Annotations Common Annotations
- @Generated:生成的注释用于标记已生成的源代码。
- @Resource: 用于标注所依赖的资源,容器据此注入外部资源依赖,有基于字段的注入和基于setter方法的注入两种方式 。
- @Resources: 同时标注多个外部依赖,容器会把所有这些外部依赖注入 。
- @PostConstruct:标注当容器注入所有依赖之后运行的方法,用来进行依赖注入后的初始化工作,只有一个方法可以标注为PostConstruct 。
- @RunAs:执行期间应用程序的角色 。
- @PreDestroy:当对象实例将要被从容器当中删掉之前,要执行的回调方法要标注为RunAs用于标注用什么安全角色来执行被标注类的方法,这个安全角色必须和Container 的Security角色一致的。
- @RolesAllowed: 用于标注允许执行被标注类或方法的安全角色,这个安全角色必须和Container 的Security角色一致的 。
- @PermitAll:允许所有角色执行被标注的类或方法 。
- @DenyAll:不允许任何角色执行被标注的类或方法,表明该类或方法不能在Java EE容器里面运行 。
- @DeclareRoles:用来定义可以被应用程序检验的安全角色,通常用isUserInRole来检验安全角色 。
注意:
- RolesAllowed,PermitAll,DenyAll不能同时应用到一个类或方法上
- 标注在方法上的RolesAllowed,PermitAll,DenyAll会覆盖标注在类上的RolesAllowed,PermitAll,DenyAll
- RunAs,RolesAllowed,PermitAll,DenyAll和DeclareRoles还没有加到Java SE 6.0上来
- 处理以上Annotations的工作是由Java EE容器来做, Java SE 6.0只是包含了上面表格的前五种Annotations的定义类,并没有包含处理这些Annotations的引擎,这个工作可以由Pluggable Annotation Processing API(JSR 269)来做
JDK6 改动最大的就是java GUI界面的显示,JDK6支持最新的windows vista系统的Windows Aero视图效果,而JDK5不支持。
JDK6 新特性的更多相关文章
- Java 新特性(2) - JDK6 新特性
http://freesea.iteye.com/blog/160133 JDK6的新特性之一_Desktop类和SystemTray类 JDK6的新特性之二_使用JAXB2来实现对象与XML之间的映 ...
- 用ScriptEngine在java中和javascript交互的例子(JDK6新特性)
package demo7; import java.util.Arrays; import java.util.List; import javax.script.Invocable; import ...
- JDK 5 ~ 10 新特性倾情整理!
JDK 5 ~ 10 新特性倾情整理! 最近连 JDK11都在准备发布的路上了,大家都整明白了吗?也许现在大部分人还在用6-8,8的新特性都没用熟,9刚出不久,10-11就不用说了. 为了大家对JDK ...
- JDK 5 ~ 11 新特性倾情整理
为了大家对JDK有一个全面的了解,下面我为大家整理了JDK5~11的所有关键新特性! 先看一下JDK的版本迭代图: 注: OpenJDK和JDK区别 GPL协议通用性公开许可证(General ...
- Java程序员必备基础:JDK 5-15都有哪些经典新特性
前言 JDK 15发布啦~ 我们一起回顾JDK 5-15 的新特性吧,大家一起学习哈~ 本文已经收录到github ❝ https://github.com/whx123/JavaHome ❞ 「公众 ...
- java基础(1)-比较jdk5,jdk6,jdk7的新特性
jdk8已经出来好长时间了,这里自己学习时简单总结的jdk5,jdk6和jdk7的新特性:本文提纲: 一.jdk5的新特性 二.jdk6的新特性 三.jdk7的新特性 一.jdk5的新特性 首先简单介 ...
- JDK1.5/1.6/1.7之新特性总结(转载)
原文地址:http://www.cnblogs.com/yezhenhan/archive/2011/08/16/2141510.html 如果原作者看到不想让我转载请私信我! 开发过程中接触到了从j ...
- JDK各个版本的新特性jdk1.5-jdk8
JDK各个版本的新特性 对于很多刚接触java语言的初学者来说,要了解一门语言,最好的方式就是要能从基础的版本进行了解,升级的过程,以及升级的新特性,这样才能循序渐进的学好一门语言.今天先为大家介绍一 ...
- JDK各版本新特性!
1.JDK1.5 新特性 1.自动装箱与拆箱:自动装箱的过程:每当需要一种类型的对象时,这种基本类型就自动地封装到与它相同类型的包装中.自动拆箱的过程:每当需要一个值时,被装箱对象中的值就被自动地提取 ...
随机推荐
- java 理解有符号数和无符号数
转至:http://jinguo.iteye.com/blog/212049 理解有符号数和无符号数负数在计算机中如何表示呢? 这一点,你可能听过两种不同的回答. 一种是教科书,它会告诉你:计算机用“ ...
- 玩得一手好注入之order by排序篇
看了之前Gr36_前辈在先知上的议题,其中有提到排序注入,这个在最近经常遇到这样的问题,所以先总结下order by 排序注入的知识. 0×00 背景 看了之前Gr36_前辈在先知上的议题,其中有提到 ...
- 设计模式之适配器模式(Adapter)
1. 概述 将一个类的接口转换成客户希望的另外一个接口.Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以在一起工作. 2. 解决的问题 即Adapter模式使得原本由于接口不兼容而不 ...
- 【Leetcode】【Easy】Valid Sudoku
Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board could be ...
- Oracle数据库克隆后temp文件因路径变化无法找到问题
Oracle数据库克隆后temp文件因路径变化无法找到出现如下报错Errors in filexxxx.trc:ORA-01157: cannot identify/lock data file xx ...
- python操作oracle小测试
首先使用python操作数据库需要导入cx_Oracle包import cx_Oracle这个包需要单独下载,下载地址:https://pypi.python.org/pypi/cx_Oracle使用 ...
- ANT 的Table表格样式修改方法
注:(大家在给页面添加参数或者方法的时候,记得写上注释,方便别人查看) 1.表格行选中样式添加:(可以去beijing,精子库质控统计查看例子) (咱们以前页面上的表格都是在hover时显示选中效果, ...
- simple2.py
#coding: utf-8 import xlsxwriter workbook = xlsxwriter.Workbook('chart.xlsx') worksheet = workbook.a ...
- Jmeter入门2 http请求—简单的get请求
发送一个简单的get http请求 1 启动Jmeter,在测试计划上点击鼠标右键>添加>Threads(Users)>线程组 2 线程组界面.可设置线程数,几秒启动所有线程,循环次 ...
- python 提取字符串中的数字组成新的字符串
方法一 # 有一个字符串text = "aAsmr3idd4bgs7Dlsf9eAF" # 请将text字符串中的数字取出,并输出成一个新的字符串 import re text = ...