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.自动装箱与拆箱:自动装箱的过程:每当需要一种类型的对象时,这种基本类型就自动地封装到与它相同类型的包装中.自动拆箱的过程:每当需要一个值时,被装箱对象中的值就被自动地提取 ...
随机推荐
- 类数组转数组Array.prototype.slice.call(arrayLike)
转换方式:Array.prototype.slice.call(arrayLike) 附:(http://www.jianshu.com/p/f8466e83cef0) 首先Array.prototy ...
- jboss安全配置规范
https://wenku.baidu.com/view/aad157a4f242336c1fb95ed5.html https://wenku.baidu.com/view/ac227281ec3a ...
- monkeyrunner之安卓开发环境搭建(二)
在上一篇文章-安卓开发环境搭建中,我们创建并启动了eclipse自带的安卓模拟器,该模拟器不仅启动慢,而且在使用过程中的反应速度也是出奇的差,经常出现卡机现象.为了解决这种现象,因此,我们又寻找到了更 ...
- 通过bat设置系统环境变量
在软件运行过程中,可能需要配置计算机的环境变量,在这里分为两种情况: 一:增加或修改环境变量只在当前软件环境中使用 如我们设置Java的环境变量: set CLASSPATH=%CLASSPATH%; ...
- 第二次Surm冲刺
一.小组完成情况: 因为技术原因,小组部分代码还没有完成,现在已经可以实现简单的借书与还书操作. 二.个人情况 我对代码进行了测试,与大家进相关的讨论. 三.总结 这次实验的团队合作真的很重要,有许多 ...
- DOS下启动MySQL时输入net start mysql 提示服务名无效的问题
原因:mysql服务名错误. 正确做法:net start +mysql服务名
- Python:一些小知识
小知识点总结 一.Python2与Python3 的区别 1.Python2中可以加括号输出,也可不加输出 Python3中必须加 2.python2 中有xrange(生成器)也有range ...
- Uva 11468 AC自动机或运算
AC自动机 UVa 11468 题意:给一些字符和各自出现的概率,在其中随机选择L次,形成长度为L的字符串S,给定K个模板串,求S不包含任意一个串的概率. 首先介绍改良版的AC自动机: 传统的AC自动 ...
- CentOS如何部署TinyProxy
TinyProxy是个非常便利,及容易架设的HTTP代理 安装方法 rpm -Uvh http://dl.fedoraproject.org/pub/epel/5/i386/epel-release- ...
- 2018.10.2 Eclipse中如何测地修改一个we项目步骤
找到项目的web.xml文件 大概的路径如下: 修改xml文件中的display-name 节点的值 下一步就是切换工作目录 显示的效果 打开最后一个文件修改 接下来找到这个文件 是部署的时候用的 运 ...