java自动生成类_自动生成优化的Java类专业知识
java自動生成類
如果您今年訪問過JavaOne,您可能已經參加了我的演講“如何從數據庫生成定制的Java 8代碼”。 在那次演講中,我展示了如何使用Speedment Open Source工具包使用數據庫作為域模型來生成各種Java代碼。 我們沒有時間要考慮的一件事是,Speedment不僅使代碼生成變得更容易,它本身也由生成的代碼組成。 在本文中,我將向您展示我們已經設置了Speedment來生成許多類的專用版本,以減少系統中性能關鍵部分的內存占用。
背景
您可能知道,Java有許多內置值類型。 這些是字節,短褲,整數,長號,浮點數,雙打,布爾值和字符。 基本值類型與普通對象的不同之處主要在于它們可以直接在內存堆棧上分配,從而減輕了垃圾回收器的負擔。 不從Object繼承的一個問題是它們不能被放入集合中或作為參數傳遞給不帶包裝而接受對象參數的方法。 因此,典型的包裝類為“整數”,“雙精度”,“布爾”等。
包裝值類型并不總是一件壞事。 如果可以安全地用原始值替換包裝類型,則JIT(即時)編譯器非常擅長優化包裝類型,但這并不總是可行的。 如果這種情況發生在代碼的性能關鍵部分(如內部循環)中,則會嚴重影響整個應用程序的性能。
這就是我們從事Speedment時發生的事情。 我們有特殊的謂詞和函數,其中包含有關其目的的元數據。 需要在一個內部循環內非??焖俚胤治鲈撛獢祿?#xff0c;但是由于大多數元數據都包裝在通用類型中以便可以動態實例化它們的事實,我們感到放慢了速度。
解決此問題的常用方法是為包含包裝器類型的類創建多個“專業化”類。 除了使用原始值類型之一而不是通用(僅對象)類型之外,這些專業化與原始類相同。 專門化的一個很好的例子是Java 8中存在的各種Stream接口。除了“ Stream”之外,我們還具有“ IntStream”,“ DoubleStream”和“ LongStream”。 這些專業化對于其特定的值類型更為有效,因為它們不必依賴于對象中的包裝類型。
專業化類的問題在于它們為系統增加了很多樣板。 假設需要優化的零件由20個組件組成。 如果要支持Java擁有的所有8種原始變體,您突然會擁有160個組件。 那要維護很多代碼。 更好的解決方案是生成所有額外的類。
基于模板的代碼生成
高級語言中最常見的代碼生成形式是基于模板的。 這意味著您編寫一個模板文件,然后根據要生成的內容進行關鍵字替換來修改文本。 Maven原型或Thymeleaf是很好的例子。 一個好的模板引擎將支持更高級的語法,例如重復節,表達條件等。如果要使用模板引擎生成專業化類,則可以將所有出現的“ int”,“ Integer”,“ IntStream”替換為特定的像“ $ {primitive}”,“ $ {wrapper}”,“ $ {stream}”之類的關鍵字,然后指定要與每種新值類型相關聯的單詞詞典。
基于模板的代碼生成的優點是易于設置和維護。 我認為大多數閱讀本文的程序員都可能會想出如何輕松編寫模板引擎的方法。 缺點是模板難以重用。 假設您有一個專門的基本模板,但是您希望浮動類型也有其他方法。 您可以使用條件語句解決此問題,但是如果您希望該其他方法也可以在其他地方存在,則需要復制代碼。 通常需要重復的典型代碼示例是hashCode()-methods或toString()。 這是基于模型的代碼生成更強大的地方。
基于模型的代碼生成
在基于模型的代碼生成中,您可以在要生成的代碼上構建一個抽象語法樹,然后使用合適的渲染器渲染該樹。 可以根據所使用的上下文來對語法樹進行更改,例如,通過添加或刪除實現特定接口的方法來進行更改。 其主要優點是更高的靈活性。 您可以動態地采用現有模型并操縱要包括的方法和字段。 不利的一面是,基于模型的代碼生成通常需要更長的時間來設置。
案例研究:速度場發生器
在Speedment,我們開發了一個名為CodeGen的代碼生成器,它使用基于模型的方法為所有原始值類型自動生成字段專業化。 每個構建總共生成大約300個類。
Speedment CodeGen使用圍繞面向對象設計的基本概念構建的抽象語法樹。 您具有用于構建域模型的類,接口,字段,方法,構造函數等。 在方法級別以下,您仍然需要編寫模板代碼。 要定義一個新的主類,您可以編寫:
import com.speedment.common.codegen.model.Class; // Not java.lang.Class...Class createMainClass() {return Class.of("Main").public_().final_().set(Javadoc.of("The main entry point of the application").add(AUTHOR.setValue("Emil Forslund")).add(SINCE.setValue("1.0.0"))).add(Method.of("main", void.class).public_().static_().add(Field.of("args", String[].class)).add("if (args.length == 0) " + block("System.out.println(\"Hello, World!\");") + " else " + block("System.out.format(\"Hi, %s!%n\", args[0]);"))); }這將生成以下代碼:
/*** The main entry point of the application.* * @author Emil Forslund* @since 1.0.0*/ public final class Main {public static void main(String[] args) {if (args.length == 0) {System.out.println("Hello, World!");} else {System.out.format("Hi, %s!%n", args[0]);}} }不必一次生成整個模型。 例如,如果我們想自動生成toString()方法,則可以將其定義為單個方法。
public void generateToString(File file) {file.add(Import.of(StringBuilder.class));file.getClasses().stream().filter(HasFields.class::isInstance).filter(HasMethods.class::isInstance).map(c -> (HasFields & HasMethods) c).forEach(clazz -> clazz.add(Method.of("toString", void.class).add(OVERRIDE).public_().add("return new StringBuilder()").add(clazz.getFields().stream().map(f -> ".append(\"" + f.getName() + "\")").map(Formatting::indent).toArray(String[]::new)).add(indent(".toString();")))); }在這里,您可以看到特質模式如何用于從邏輯中抽象出底層實現。 該代碼將對Enum和Class均適用,因為兩者均實現了特征“ HasFields”和“ HasMethods”。
摘要
在本文中,我解釋了什么是專業化類,以及為什么有時必須使用它們來提高應用程序關鍵部分的性能。 我還向您展示了Speedment如何使用基于模型的代碼生成來自動生成專業化類。 如果您有興趣自己使用這些工具生成代碼,請繼續并在GitHub上查看生成器的最新版本 !
翻譯自: https://www.javacodegeeks.com/2016/11/auto-generate-optimized-java-class-specializations.html
java自動生成類
總結
以上是生活随笔為你收集整理的java自动生成类_自动生成优化的Java类专业知识的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 编写代码_如果您在2016年编
- 下一篇: 三星电视ip设置方法(三星电视无线网ip