动态语言支持
本文是我們名為“ 高級Java ”的學院課程的一部分。
本課程旨在幫助您最有效地使用Java。 它討論了高級主題,包括對象創建,并發,序列化,反射等。 它將指導您完成Java掌握的過程! 在這里查看 !
目錄
1.簡介 2.動態語言支持 3.腳本API 4. JVM上JavaScript 5.在JVM上使用Groovy 6. JVM上的Ruby 7. JVM上的Python 8.使用腳本API 9.接下來 10.下載代碼1.簡介
在本教程的這一部分中,我們的注意力將完全集中在Java中的腳本和動態語言支持上。 從Java 7開始,JVM就直接支持現代動態語言(也通常稱為腳本語言),并且Java 8版本對該空間進行了進一步的增強。
動態語言的優勢之一是程序的行為是在運行時定義的,而不是在編譯時定義的。 在這些語言中, Ruby ( https://www.ruby-lang.org/en/ ), Python ( https://www.python.org/ )和JavaScript ( http://en.wikipedia.org/wiki/ JavaScript )已廣受歡迎,并且是目前使用最廣泛的JavaScript 。 我們將研究Java腳本API如何為將這些語言集成到現有Java應用程序中提供一種方法。
2.動態語言支持
眾所周知,Java是一種靜態類型的語言。 這意味著在編譯時可獲得類的所有類型化信息,其成員,方法參數和返回值。 使用所有這些詳細信息,Java編譯器會發出強類型的字節碼,然后可以在運行時由JVM有效地解釋。
但是,動態語言在運行時而不是編譯時執行類型檢查。 處理動態語言的挑戰是如何實現一個運行時系統,該系統可以選擇一種最合適的方法實現,以在程序編譯后進行調用。
長期以來,JVM一直沒有對動態類型語言的特殊支持。 但是Java 7版本引入了新的invokedynamic指令,該指令使運行時系統(JVM)可以自定義調用站點(調用方法的位置)與方法實現之間的鏈接。 它確實為在JVM平臺上提供有效的動態語言支持和實施打開了一扇門。
3.腳本API
作為2006年發行的Java 6的一部分,新的腳本API已在javax.script包下引入。 該可擴展API旨在插入大多數腳本語言(提供腳本引擎實現)并在JVM平臺上運行。
實際上,Java腳本API非常小而且非常簡單。 開始使用腳本API的第一步是創建ScriptEngineManager類的新實例。 ScriptEngineManager提供了從正在運行的應用程序類路徑中按名稱搜索和檢索可用腳本引擎的功能。
每個腳本引擎使用各自的ScriptEngine實現表示,并且實質上提供了使用eval()函數家族(具有多個重載版本)執行腳本的能力。 已經有許多流行的腳本(動態)語言提供了對Java腳本API的支持,在本教程的下一部分中,我們將通過玩JavaScript , Groovy , Ruby / JRuby和Python / Jython來了解該API在實踐中的效果。 。
4. JVM上JavaScript
我們并非偶然地開始使用JavaScript語言,因為它是Java標準庫腳本API支持的最早的腳本語言之一。 而且,從總體上講,它是每個Web瀏覽器都能理解的單一編程語言。
eval()函數以最簡單的形式執行腳本,并以純Java字符串的形式傳遞給腳本。 該腳本沒有與評估者(或調用者)共享的狀態,并且是獨立的代碼段。 但是,在典型的實際應用程序中,這種情況非常罕見,并且經常需要將一些變量或屬性提供給腳本才能執行一些有意義的計算或操作。 話雖如此,讓我們看一個使用簡單變量綁定評估真實JavaScript函數調用的簡單示例:
final ScriptEngineManager factory = new ScriptEngineManager(); final ScriptEngine engine = factory.getEngineByName( "JavaScript" );final Bindings bindings = engine.createBindings(); bindings.put( "str", "Calling JavaScript" ); bindings.put( "engine", engine );engine.eval( "print(str + ' from ' + engine.getClass().getSimpleName() )", bindings );執行后,將在控制臺上打印以下輸出:
Calling JavaScript from RhinoScriptEngine相當長一段時間以來 , Rhino一直是JVM上可用的單個JavaScript腳本引擎。 但是Java 8版本帶來了一個名為NashornJavaScript腳本引擎的全新實現( http://www.oracle.com/technetwork/articles/java/jf14-nashorn-2126515.html )。
從API的角度來看,并沒有太多的區別,但是內部實現卻有很大的不同,從而保證了更好的性能。 這是使用Nashorn JavaScript引擎重寫的同一示例:
final ScriptEngineManager factory = new ScriptEngineManager(); final ScriptEngine engine = factory.getEngineByName( "Nashorn" );final Bindings bindings = engine.createBindings(); bindings.put( "engine", engine );engine.eval( "print(str + ' from ' + engine.getClass().getSimpleName() )", bindings );以下輸出將打印在控制臺上(請注意這次不同的腳本引擎實現):
Calling JavaScript from NashornScriptEngine盡管如此,我們看過JavaScript代碼片段的例子卻是微不足道的。 實際上,您可以使用重載的eval()函數調用來評估整個JavaScript文件,并僅在JavaScript中實現相當復雜的算法。 在接下來的部分中,我們將在探索其他腳本語言時看到這些示例。
5.在JVM上使用Groovy
Groovy ( http://groovy.codehaus.org )是JVM平臺最成功的動態語言之一。 它通常與Java并行使用,但是它也提供Java腳本API引擎實現,并且可以與JavaScript相似的方式使用。
讓我們通過開發一個小的獨立腳本,使這個Groovy示例更加有意義和有趣,該腳本在控制臺上打印出通過調用Java應用程序與其共享的藏書中每本書的一些詳細信息。
Book類非常簡單,只有兩個屬性,author和title:
public class Book {private final String author;private final String title;public Book(final String author, final String title) {this.author = author;this.title = title;}public String getAuthor() {return author;}public String getTitle() {return title;} }Groovy腳本(僅命名為script.groovy )使用一些漂亮的語言功能(例如閉包和字符串插值)將書籍屬性輸出到控制臺:
books.each { println "Book '$it.title' is written by $it.author" }println "Executed by ${engine.getClass().simpleName}" println "Free memory (bytes): " + Runtime.getRuntime().freeMemory()現在,讓我們使用Java腳本API和預定義的書籍集合(當然,有關Groovy的所有內容)執行這個Groovy腳本:
final ScriptEngineManager factory = new ScriptEngineManager(); final ScriptEngine engine = factory.getEngineByName( "Groovy" );final Collection< Book > books = Arrays.asList(new Book( "Venkat Subramaniam", "Programming Groovy 2" ),new Book( "Ken Kousen", "Making Java Groovy" ));final Bindings bindings = engine.createBindings(); bindings.put( "books", books ); bindings.put( "engine", engine );try( final Reader reader = new InputStreamReader( Book.class.getResourceAsStream("/script.groovy" ) ) ) {engine.eval( reader, bindings ); }請注意, Groovy腳本引擎具有對Java標準庫的完全訪問權限,并且不需要任何附加綁定。 為了確認這一點,上述Groovy腳本的最后一行通過調用Runtime.getRuntime()靜態方法訪問當前的運行時環境,并打印出可用于運行JVM的可用堆數量(以字節為單位)。 以下示例輸出將出現在控制臺上:
Book 'Programming Groovy 2' is written by Venkat Subramaniam Book 'Making Java Groovy' is written by Ken Kousen Executed by GroovyScriptEngineImpl Free memory (bytes): 153427528自Groovy推出至今已有10年了。 由于其創新的語言功能(類似于Java語法)以及與現有Java代碼的出色互操作性,它很快變得非常流行。 看起來lambdas的引入和Java 8中的Stream API使得Groovy的吸引力降低了一些,但是它仍然被Java開發人員廣泛使用。
6. JVM上的Ruby
幾年前, Ruby ( https://www.ruby-lang.org/en/ )是用于Web應用程序開發的最流行的動態語言。 盡管如今它的流行程度已逐漸消失,但Ruby及其生態系統在現代Web應用程序開發中帶來了許多創新,激發了許多其他編程語言和框架的創建和發展。
JRuby ( http://jruby.org/ )是JVM平臺的Ruby編程語言的實現。 與Groovy相似,它還提供了與現有Java代碼的出色互操作性,從而保留了Ruby語言語法的美感。
讓我們用Ruby語言(名為script.jruby )從JVM上的Groovy腳本部分重寫Groovy腳本,并使用Java腳本API對其進行評估。
$books.each do |it| java.lang.System.out.println( "Book '" + it.title + "' is written by " + it.author ) endjava.lang.System.out.println( "Executed by " + $engine.getClass().simpleName ) java.lang.System.out.println( "Free memory (bytes): " + java.lang.Runtime.getRuntime().freeMemory().to_s )腳本評估代碼基本保持不變,只是腳本引擎和示例書籍集合有所不同,而這一切都與Ruby有關。
final ScriptEngineManager factory = new ScriptEngineManager(); final ScriptEngine engine = factory.getEngineByName( "jruby" );final Collection< Book > books = Arrays.asList(new Book( "Sandi Metz", "Practical Object-Oriented Design in Ruby" ),new Book( "Paolo Perrotta", "Metaprogramming Ruby 2" ));final Bindings bindings = engine.createBindings(); bindings.put( "books", books ); bindings.put( "engine", engine );try( final Reader reader = new InputStreamReader( Book.class.getResourceAsStream("/script.jruby" ) ) ) {engine.eval( reader, bindings ); }以下示例輸出將出現在控制臺上:
Book 'Practical Object-Oriented Design in Ruby' is written by Sandi Metz Book 'Metaprogramming Ruby 2' is written by Paolo Perrotta Executed by JRubyEngine Free memory (bytes): 142717584從上面的JRuby代碼片段中我們可以看出,使用標準Java庫中的類有點冗長,并且必須以包名稱作為前綴(有一些技巧可以擺脫這一點,但是我們不做這些特定的細節)。
7. JVM上的Python
我們最后一個但并非最不重要的示例將展示JVM平臺上的Python ( https://www.python.org/ )語言實現,稱為Jython ( http://www.jython.org/ )。
Python語言最近獲得了廣泛的關注,并且其流行程度每天都在增長。 它被科學界廣泛使用,并具有從網絡開發到自然語言處理的大量庫和框架。
遵循與Ruby相同的路徑,我們將使用Python語言(名稱為script.py )從JVM部分的Groovy重寫示例腳本,并使用Java腳本API對其進行評估。
from java.lang import Runtimefor it in books: print "Book '%s' is written by %s" % (it.title, it.author)print "Executed by " + engine.getClass().simpleName print "Free memory (bytes): " + str( Runtime.getRuntime().freeMemory() )讓我們實例化Jython腳本引擎,并使用已經熟悉的Java腳本API執行上面的Python腳本。
final ScriptEngineManager factory = new ScriptEngineManager(); final ScriptEngine engine = factory.getEngineByName( "jython" );final Collection< Book > books = Arrays.asList(new Book( "Mark Lutz", "Learning Python" ),new Book( "Jamie Chan", "Learn Python in One Day and Learn It Well" ));final Bindings bindings = engine.createBindings(); bindings.put( "books", books ); bindings.put( "engine", engine );try( final Reader reader = new InputStreamReader( Book.class.getResourceAsStream("/script.py" ) ) ) {engine.eval( reader, bindings ); }以下示例輸出將在控制臺上打印出來:
Book 'Learning Python' is written by Mark Lutz Book 'Learn Python in One Day and Learn It Well' is written by Jamie Chan Executed by PyScriptEngine Free memory (bytes): 132743352Python作為編程語言的強大之處在于其簡單性和陡峭的學習曲線。 隨著一群Python開發人員的加入,以某種可擴展性機制將Python腳本語言集成到Java應用程序中的能力聽起來像是一個有趣的主意。
8.使用腳本API
Java 腳本API是通過可擴展的腳本支持來豐富Java應用程序的好方法,只需選擇您的語言即可。 這也是插入域專用語言 (DSL)的最簡單方法,并允許業務專家以最方便的方式表達其意圖。
JVM本身的最新更改(請參見“ 動態語言支持”部分)使它成為適用于不同動態(腳本)語言實現的更友好的運行時平臺。 毫無疑問,將來會有越來越多的腳本語言引擎可用,這為與新的和現有的Java應用程序無縫集成打開了大門。
9.接下來
從這部分開始,我們實際上是在開始有關Ja??va作為語言和JVM作為高級運行時執行平臺的高級概念的討論。 在本教程的下一部分中,我們將研究Java Compiler API和Java Compiler Tree API,以學習如何在運行時操作Java源代碼。
9.下載代碼
這是動態語言支持課程,是高級Java課程的第12部分。 您可以在此處下載源代碼: advanced-java-part-12
翻譯自: https://www.javacodegeeks.com/2015/09/dynamic-languages-support.html
總結
- 上一篇: 台式电脑主板电源插线步骤图解(电脑主板电
- 下一篇: 对象池回收对象_回收对象以提高性能