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來標識測試期間需要執行的測試方法,如下所示:
@TestMethodpublic 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聲明的且目標源代碼擁有的所有Annotationsfor(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();//獲取方法的Annotationsnote("--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里面的一個Annotationpublic 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來檢驗安全角色 。
注意:
?
JDK6 改動最大的就是java GUI界面的顯示,JDK6支持最新的windows vista系統的Windows Aero視圖效果,而JDK5不支持。
?
總結
- 上一篇: 键盘映射
- 下一篇: 2018年最好的8款杀毒软件