java自动生成类_自动生成优化的Java类专业知识

java自动生成类

如果您今年访问过JavaOne,您可能已经参加了我的演讲“如何从数据库生成定制的Java 8代码”。 在那次演讲中,我展示了如何使用Speedment Open Source工具包使用数据库作为域模型来生成各种Java代码。 我们没有时间要考虑的一件事是,Speedment不仅使代码生成变得更容易,它本身也由生成的代码组成。 在本文中,我将向您展示我们已经设置了Speedment来生成许多类的专用版本,以减少系统中性能关键部分的内存占用。

背景

您可能知道,Java有许多内置值类型。 这些是字节,短裤,整数,长号,浮点数,双打,布尔值和字符。 基本值类型与普通对象的不同之处主要在于它们可以直接在内存堆栈上分配,从而减轻了垃圾回收器的负担。 不从Object继承的一个问题是它们不能被放入集合中或作为参数传递给不带包装而接受对象参数的方法。 因此,典型的包装类为“整数”,“双精度”,“布尔”等。

包装值类型并不总是一件坏事。 如果可以安全地用原始值替换包装类型,则JIT(即时)编译器非常擅长优化包装类型,但这并不总是可行的。 如果这种情况发生在代码的性能关键部分(如内部循环)中,则会严重影响整个应用程序的性能。

这就是我们从事Speedment时发生的事情。 我们有特殊的谓词和函数,其中包含有关其目的的元数据。 需要在一个内部循环内非常快速地分析该元数据,但是由于大多数元数据都包装在通用类型中以便可以动态实例化它们的事实,我们感到放慢了速度。

解决此问题的常用方法是为包含包装器类型的类创建多个“专业化”类。 除了使用原始值类型之一而不是通用(仅对象)类型之外,这些专业化与原始类相同。 专门化的一个很好的例子是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自动生成类

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/335335.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在Linux中su和sudo区别,Linux中su和sudo的用法和区别

目录sudosudo:暂时切换到超级用户模式以执行超级用户权限,提示输入密码时该密码为当前用户的密码,而不是超级账户的密码。缺点是每次执行超级用户权限都要在命令前加上 sudo ,优点是在当前终端再使用 sudo 不要再重复输入密码(只对…

neo4j 添加属性_Neo4j:动态添加属性/设置动态属性

neo4j 添加属性我一直在研究一个具有英国国家铁路时刻表的数据集,它们以文本格式为您提供每列火车的出发和到达时间。 例如,可以这样创建代表停止的节点: CREATE (stop:Stop {arrival: "0802", departure: "0803H"})该…

python 提升效率_@Python 程序员,如何最大化提升编码效率?

作者 | Enoch CK 译者 | 刘畅 整理 | Jane 出品 | Python大本营 【导语】无论你是一位高级的AI工程师还是学生,你都会在工作或学习过程中需要用到 Python。自 1991 年首次发布后,Python 很快就成为了程序员和技术人员最喜欢的语言。作为一种拥有相对简单…

linux tar -xvf命令,linux下tar命令详解

2011-11-28 13:03朋友你好!我刚开始搞linux,碰到了很多问题,想问你下,希望能帮我解答下。下面是我的一段shell 程序#!/bin/shwhile [ 0 ]doread scoreif [ $score -lt 60 ];thenecho " you must work hard!"…

linux下如何查看主机是否安装了ftp server

常用的发行版的软件包管理系统有Debian系(包括Debian,Ubuntu,Mint等)和Red Hat系(包括RHEL,Fedora,CentOs,Scientific),前者查看是否安装了ftp的命令是&#…

spring boot rabbitmq_Spring Boot+RabbitMQ 实现延迟消息实现完整版,实用!

本文同步Java知音社区,专注于Java作者:Sam哥哥http://blog.csdn.net/linsongbin1/article/details/80178122概述曾经去网易面试的时候,面试官问了我一个问题,说下完订单后,如果用户未支付,需要取消订单&…

jax-rs jax-ws_信守承诺:针对JAX-RS API的基于合同的测试

jax-rs jax-ws自从我们谈论测试和应用有效的TDD做法以来,已经有一段时间了,特别是与REST(ful) Web服务和API有关的做法。 但是,这个主题永远都不应忘记,特别是在每个人都在做微服务的世界中,无论…

手机流量共享 linux,linux – 通过HTB共享带宽和优先处理实时流量,哪种方案更好?...

我想在我们的互联网线路上添加一些流量管理.在阅读了大量文档之后,我认为HFSC对我来说太复杂了(我不了解所有曲线的东西,我担心我永远不会把它弄好),CBQ不推荐,基本上HTB就是通往适合大多数人.我们的内部网络有三个“段”,我想在这些段之间或多或少地分享带宽(至少在开始时).此…

负载均衡解决方案

某网站随着知名度的提高,用户访问量日渐增多,近段时间以来,由于访问量的激增,服务不可用的情况时有发生。针对这种状况,结合实际情况,设计了一套解决方案。 技术实现 1、负载均衡。2台同样配置的linux服务…

pcf8523_PCF上的Spring Cloud合同和Spring Cloud Services

pcf8523最近,我们有一个客户,对于使用Spring Cloud Contract (SCC)来防止微服务团队之间的API“漂移”,微型开发团队会照顾个体的API(构成企业应用程序的一部分),这些客户非常感兴趣…

python二分法查找时间点_python有序查找算法:二分法

二分法是一种快速查找的方法,时间复杂度低,逻辑简单易懂,总的来说就是不断的除以2除以2... 但是需要注意:待查找的序列区间单调有序 例如需要查找有序数组arr里面的某个关键字key的位置,那么首先确认arr的中位数或者中…

linux shell ls -l,linux之ls -l|grep ^-|wc -l命令 Shell 中常見的日志統計方法

轉:http://www.cnblogs.com/senior-engineer/p/6203268.htmlShell 中常見的日志統計方法https://my.oschina.net/waterbear/blog/371845Linux Shell工具grep awk cut sort uniq sort 使用小結http://www.linuxidc.com/Linux/2012-05/61126.htm查看某文件夾下文件的個…

怎么运行aws的示例程序_使Spring Boot应用程序在AWS上无服务器运行

怎么运行aws的示例程序在之前的 几篇 文章中,我描述了如何设置Spring Boot应用程序并在AWS Elastic Beanstalk上运行它。 尽管这是从物理服务器到云服务器的重要一步,但还有更好的可能! 走向无服务器 。 这意味着无需花费任何服务器费用&…

自己写的 ORACLE 函数的解读

DECLARE MAXWRITNO INTEGER ; <!--声明了2个变量&#xff0c;变量类型是INTEGER-->LINETY INTEGER; BEGIN <!--表示进入方法体-->----------获取要循环的结果集&#xff0c;APPLINPER班线许可申请表FOR REC IN (select * from $PRDLINE.APPLINPER a where (A.APPP…

python调用linux命令输出结果,Python-运行shell命令并捕获输出

小编典典这个问题的答案取决于你使用的Python版本。最简单的方法是使用以下subprocess.check_output功能&#xff1a;>>> subprocess.check_output([ls, -l])btotal 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n该check_output功能适用于仍在广泛使用的几乎…

python cls_关于python中的self,ins , cls的解释

关于python中的self,ins,cls的解释参考下面两篇博文self比较好理解&#xff0c;self指的是类实例对象本身(注意&#xff1a;不是类本身) class Person: def _init_(self,name): self.namename def sayhello(self): print My name is:,self.name pPerson(Tom) print p 为什么不是…

脚本语言和工程语言_语言工程中有趣的事情

脚本语言和工程语言如果您阅读此博客&#xff0c;您将知道我坚信语言的力量。 所以&#xff0c;我当然有很大的偏见&#xff0c;但是我感觉语言工程社区正在增长&#xff0c;并且越来越有趣的东西正在涌现。 为此&#xff0c;我认为通过查看社区中正在发生的事情并列出一些我发…

linux useradd 数字,详解linux useradd用户组合权限管理等

1&#xff0c;权限相关概念Rwx任何一个文件都应该由两部分组成&#xff0c;这两部分其实基于文件系统来组织&#xff0c;磁盘分区创建完成后&#xff0c;在高级格式化的时候&#xff0c;就把整个磁盘分区分成两部分&#xff0c;其中一部分是源数据&#xff0c;一部分是来放数据…

windows上的python能否在unix上使用_怎么用python在Windows系统下,生成UNIX格式文件

在Windows下换行时&#xff0c;有两个字符&#xff1a;回车(/r)和换行(/n)。但在Linux下&#xff0c;只有一个换行(/n)可使用unix2dos和dos2unix命令进行格式的转换&#xff1a; 参数&#xff1a; -k 保持输出文件和输入文件的日期时间戳不变 -o file 默认模式 . 将file转换&am…

.dmp数据文件的解读

通过PL/SQL Developer导出表数据&#xff0c;生成后缀名为.dmp的文件&#xff0c;如果你以某个用户例如&#xff1a;HYT2LINEHN访问数据库&#xff0c;那么你可以将这个用户下的所有表导成dmp文件&#xff0c;那么这个dmp文件里就包含了这个用户下的所有表的数据&#xff0c;当…