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 指定的消息字段。
示例代码:
1 import java.awt.*; 2 import java.io.File; 3 import java.io.IOException; 4 import java.net.URI; 5 6 public class Test { 7 public static void main(String[] args) throws IOException { 8 //先判断当前平台是否支持Desktop类 9 if (Desktop.isDesktopSupported()) { 10 //获取Desktop实例 11 Desktop desktop = Desktop.getDesktop(); 12 //使用默认浏览器打开链接 13 desktop.browse(URI.create("http://www.cnblogs.com/peter1018")); 14 // 打开指定文件/文件夹 15 desktop.open(new File("D:\\")); 16 17 //...... 18 19 //其他方法可以自行演示... 20 }else { 21 System.out.println("当前平台不支持 Desktop类!"); 22 } 23 24 } 25 26 }
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) : 返回所有已关联的监听器数组
示例代码:
1 import javax.swing.*; 2 import java.awt.*; 3 4 public class Test { 5 public static void main(String[] args) throws AWTException { 6 //先判断当前平台是否支持SystemTray类 7 if (SystemTray.isSupported()) { 8 //获取SystemTray实例 9 SystemTray systemTray = SystemTray.getSystemTray(); 10 //获得托盘显示图标 11 ImageIcon imageIcon=new ImageIcon("D:\\icon.jpg"); 12 //获得Image对象 13 Image icon=imageIcon.getImage(); 14 //任务栏程序托盘图标 15 TrayIcon trayicon = new TrayIcon(icon,"JAVA系统托盘"); 16 //关键点,设置托盘图标的自适应属性,这样才能在系统显示托盘处正常显示出需要的图片。 17 trayicon.setImageAutoSize(true); 18 //添加系统托盘 19 systemTray.add(trayicon); 20 //...... 21 //其他方法可以自行演示... 22 //移除系统托盘 23 systemTray.remove(trayicon); 24 }else { 25 System.out.println("当前平台不支持 SystemTray类!"); 26 } 27 28 } 29 30 }
展示结果如下:
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类
1 import javax.xml.bind.annotation.XmlAttribute; 2 import javax.xml.bind.annotation.XmlElement; 3 4 public class Address { 5 6 @XmlAttribute 7 String province; 8 @XmlElement 9 String area; 10 @XmlElement 11 String street; 12 13 public Address() {} 14 15 public Address(String province, String area, String street) { 16 this.province = province; 17 this.area = area; 18 this.street = street; 19 } 20 21 @Override 22 public String toString() { 23 return "Address{" + 24 "province='" + province + '\'' + 25 ", area='" + area + '\'' + 26 ", street='" + street + '\'' + 27 '}'; 28 } 29 }
Person类
1 import javax.xml.bind.annotation.XmlAttribute; 2 import javax.xml.bind.annotation.XmlElement; 3 import javax.xml.bind.annotation.XmlRootElement; 4 5 @XmlRootElement 6 public class Person{ 7 8 @XmlAttribute 9 private String name; 10 11 @XmlElement 12 private int age; 13 14 @XmlElement 15 private Address address; 16 17 public Person() { 18 } 19 20 public Person(String name, int age, Address address) { 21 this.name = name; 22 this.age = age; 23 this.address = address; 24 } 25 26 @Override 27 public String toString() { 28 return "Person{" + 29 "name='" + name + '\'' + 30 ", age=" + age + 31 ", address=" + address + 32 '}'; 33 } 34 }
测试类:
1 import javax.xml.bind.JAXBContext; 2 import javax.xml.bind.JAXBException; 3 import javax.xml.bind.Marshaller; 4 import javax.xml.bind.Unmarshaller; 5 import java.io.FileReader; 6 import java.io.FileWriter; 7 import java.io.IOException; 8 9 public class Test { 10 public static void main(String[] args) throws JAXBException, IOException { 11 JAXBContext jaxbContext = JAXBContext.newInstance(Person.class); 12 13 //根据Person对象转换为person.xml文件 14 Marshaller marshaller = jaxbContext.createMarshaller(); 15 Address address = new Address("广东省","深圳市","宝安区"); 16 Person person = new Person("niannianjiuwang", 20, address); 17 FileWriter fileWriter = new FileWriter("D:\\person.xml"); 18 marshaller.marshal(person, fileWriter); 19 20 //根据person.xml文件转换为对象 21 FileReader fileReader = new FileReader("D:\\person.xml"); 22 Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); 23 Person personNew = (Person) unmarshaller.unmarshal(fileReader); 24 System.out.println(personNew); 25 } 26 }
输出结果:
先看看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采用的是游标机制。
示例代码:
1 import javax.xml.stream.*; 2 import javax.xml.stream.events.XMLEvent; 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.FileOutputStream; 6 7 public class Test { 8 public static void main(String[] args) throws FileNotFoundException, XMLStreamException { 9 writeXMLByStAX();//用XMLStreamWriter写xml文档 10 readXMLByStAX();//用XMLEventReader解析xml文档 11 } 12 13 /** 14 * 通过StAX读XML 15 */ 16 private static void readXMLByStAX() throws XMLStreamException, FileNotFoundException { 17 XMLInputFactory xmlif = XMLInputFactory.newInstance(); 18 XMLEventReader xmler = xmlif.createXMLEventReader(new FileInputStream("D:\\write.xml")); 19 XMLEvent event; 20 StringBuffer parsingResult = new StringBuffer(); 21 while (xmler.hasNext()) { 22 event = xmler.nextEvent(); 23 parsingResult.append(event.toString()); 24 } 25 System.out.println(parsingResult); 26 } 27 28 /** 29 * 通过StAX写XML 30 */ 31 private static void writeXMLByStAX() throws FileNotFoundException, XMLStreamException { 32 XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newFactory(); 33 XMLStreamWriter xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(new FileOutputStream("D:\\write.xml")); 34 35 // 写入默认的 XML 声明到xml文档 36 xmlStreamWriter.writeStartDocument(); 37 // 写入注释到xml文档 38 xmlStreamWriter.writeComment("testing comment"); 39 // 写入一个catalogs根元素 40 xmlStreamWriter.writeStartElement("catalogs"); 41 xmlStreamWriter.writeNamespace("myUrl", "http://www.cnblogs.com/peter1018"); 42 xmlStreamWriter.writeAttribute("name","niannianjiuwang"); 43 // 写入子元素catalog 44 xmlStreamWriter.writeStartElement("http://www.cnblogs.com/peter1018", "catalog"); 45 xmlStreamWriter.writeAttribute("id","StAX"); 46 xmlStreamWriter.writeCharacters("Apparel"); 47 // 写入catalog元素的结束标签 48 xmlStreamWriter.writeEndElement(); 49 // 写入catalogs元素的结束标签 50 xmlStreamWriter.writeEndElement(); 51 // 结束 XML 文档 52 xmlStreamWriter.writeEndDocument(); 53 xmlStreamWriter.close(); 54 } 55 }
输出结果:
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文件)
1 import javax.tools.JavaCompiler; 2 import javax.tools.JavaFileObject; 3 import javax.tools.StandardJavaFileManager; 4 import javax.tools.ToolProvider; 5 import java.io.IOException; 6 7 public class Test { 8 public static void main(String[] args) throws IOException { 9 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 10 StandardJavaFileManager standardJavaFileManager = compiler.getStandardFileManager(null,null,null); 11 Iterable<? extends JavaFileObject> sourcefiles = standardJavaFileManager.getJavaFileObjects("D:\\TestObject.java"); 12 compiler.getTask(null, standardJavaFileManager, null, null, null, sourcefiles).call(); 13 standardJavaFileManager.close(); 14 15 } 16 }
输出结果:会在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实现类的回调方法。
示例代码:
1 import com.sun.net.httpserver.HttpExchange; 2 import com.sun.net.httpserver.HttpHandler; 3 4 import java.io.*; 5 6 public class TestHandler implements HttpHandler { 7 8 9 @Override 10 public void handle(HttpExchange httpExchange) throws IOException { 11 System.out.println("==进入Hadnler方法"); 12 String responseMsg = "OK"; //响应信息 13 InputStream in = httpExchange.getRequestBody(); //获得输入流 14 BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 15 String temp = null; 16 while((temp = reader.readLine()) != null) { 17 System.out.println("client request:"+temp); 18 } 19 httpExchange.sendResponseHeaders(200, responseMsg.length()); //设置响应头属性及响应信息的长度 20 OutputStream out = httpExchange.getResponseBody(); //获得输出流 21 out.write(responseMsg.getBytes()); 22 out.flush(); 23 httpExchange.close(); 24 } 25 }
1 import com.sun.net.httpserver.HttpServer; 2 import com.sun.net.httpserver.spi.HttpServerProvider; 3 4 import java.io.IOException; 5 import java.net.InetSocketAddress; 6 7 public class Test { 8 public static void main(String[] args) throws IOException { 9 //启动服务,监听来自客户端的请求 10 HttpServerProvider provider = HttpServerProvider.provider(); 11 //监听8888端口,能同时接受100个请求 12 HttpServer httpserver =provider.createHttpServer(new InetSocketAddress(8888), 100); 13 //将 /test 请求交给 TestHandler 处理器处理 14 httpserver.createContext("/test", new TestHandler()); 15 httpserver.setExecutor(null); 16 httpserver.start(); 17 System.out.println("server started"); 18 } 19 }
输出结果:
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类:
示例代码:
1 import java.io.Console; 2 3 public class Test { 4 public static void main(String[] args){ 5 Console console = System.console(); 6 if(console!=null){//判断console是否可用 7 String user = new String(console.readLine("Enter user:")); //读取整行字符 8 String pwd = new String(console.readPassword("Enter passowrd:")); //读取密码,密码输入时不会显示 9 console.printf("User is:"+user+"/n"); 10 console.printf("Password is:"+pwd+"/n"); 11 }else{ 12 System.out.println("JVM无法使用当前的Console"); 13 } 14 } 15 }
在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方法执行脚本
示例代码:
1 import javax.script.Invocable; 2 import javax.script.ScriptEngine; 3 import javax.script.ScriptEngineManager; 4 5 public class Test { 6 public static void main(String[] args){ 7 ScriptEngineManager factory = new ScriptEngineManager(); 8 ScriptEngine engine = factory.getEngineByName("JavaScript"); 9 String script; 10 try { 11 script = "print('Hello')"; 12 engine.eval(script);// 执行脚本 13 script = "1-23*9/3+77"; 14 System.out.println(engine.eval(script).toString());// 不用对字符串做解析便可得到算式结果 15 engine.put("a", "一个字符串"); 16 script = "print(a)"; 17 engine.eval(script);// 脚本调用java对象 18 script = "function hello(name) { return 'Hello,' + name;}"; 19 engine.eval(script); 20 Invocable inv = (Invocable) engine; 21 System.out.println(inv.invokeFunction("hello", "Scripting"));//java调用脚本方法 22 } catch (Exception e) { 23 e.printStackTrace(); 24 } 25 } 26 27 }
输出结果:
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不支持。