JUG.ru集团可能会在本周发布公告。 直到我说什么。 参与秘密项目可以激发创造力,因此这是另一个有关Java的夜间视频。
令人难以置信的消息:现在已经不是一个半小时,而是大约20分钟,甚至还有一些值得关注的地方。 它由一个截屏视频组成,略少于全部。 那些无法忍受此视频垃圾并喜欢使用文本解密的人,在剪切后不得不剪切很多文本。 Welkam,也许Java与您同在。
即将发布12种Java,许多人仍然坐在Semerochka上,他们相信在升级的情况下,他们不会看到任何特别新颖或有趣的东西。 在本期超短篇文章中,我们将学习如何在脚本化Java的帮助下将同事的生活变成地狱,并且在几个地方,我将介绍一些新工具。 好吧,蒙昧主义者当然不会从进步中幸免。
告诉我,您为什么要更新您的想法? 新功能不断出现,一些新的快捷方式,使开发人员的工作效率提高了十倍。 但是你不知道他们。 你真的在读这个新闻吗? 如果您是普通用户,则可能不是。 原则上,您在大多数情况下都不会对您造成伤害。 您之所以更新想法,仅仅是因为……可以。 因为皮肤很漂亮,所以是深色主题,是MacBook上的触摸栏。 但是,这种解释在当局面前并没有作为“为什么要买这个主意”的答案。
取而代之的是,可以说是10月29日,即最近,JetBrains在Beta版的
Idea中固定了对
原始行的支持。 这个想法是在beta中,行在预览中,但这对任何人都不再重要。 如果您如此固执,以至于只放了12个Java,那么您将遇到更严重的问题。 我自己知道。
让我们看看它在实际中的外观。 为此,请尝试解决某种示范问题。 经常有脚本编写问题。 例如,在计算机游戏中,这些是任务,在詹金斯中,这些是构建脚本,依此类推。 通常,为此使用Python或Groove,让我们开始使用裸Java! 为什么,为什么? 因为我们可以做到三行,甚至没有黑客。 听起来是个好主意:-)
在哪里看
一切都在github上 。
适用范围
假设我们有一个这样的文件:
package io.javawatch; public class HelloHabrPrototype { public String get() { return "Hello Habr!"; } };
我们希望它不是在编译整个应用程序时执行,而是在启动后作为字符串执行。 就像脚本一样。
手动地
首先,您需要将所有内容都放入字符串中。
private static final String SOURCE = "\n" + " package io.javawatch;\n" + " public class HelloHabr {\n" + " public String get() {\n" + " return \"Hello Habr!\";\n" + " }\n" + " };"; public static final String CNAME = "io.javawatch.HelloHabr"; private static String CODE_CACHE_DIR = "C:/temp/codeCache";
所有这些“ \ n”加号和缩进看起来非常惨。
以前,我们所能做的就是将代码放在文件中并读取。 这可能是一个很好的解决方案,但并不总是适用。 例如,您是会议的发言人,并演示幻灯片中的代码。 即使是上面的构造,也比仅是未经证实的参考要好得多,因为您的代码在某处可以执行某些操作。 切换幻灯片会浪费时间和观众的注意力。 等等。 简而言之,当您需要完全内联的代码时,就可以提出。
现在我们有机会使用原始字符串摆脱垃圾。 我们将光标放在代码上,然后按Alt + Enter(或在Idea中的OS Quck Fix上运行的任何命令)。 选择“转换为原始字符串文字”并获得以下nyashka:
private static final String SOURCE = ` package io.javawatch; public class HelloHabr { public String get() { return "Hello Habr!"; } };`; public static final String CNAME = "io.javawatch.HelloHabr"; private static String CODE_CACHE_DIR = "C:/temp/codeCache";
我认为,就此功能而言,已经值得运行JDK 12。
顺便说一句,为了使该功能正常运行,您需要做几件事:
- 下载JDK 12并注册项目设置
- 在全局javac设置中,设置
--release
标志,字节码版本12,其他标志--enable-preview
-Xlint:preview
- 现在,在任何运行/调试配置中,您需要添加VM标志
--enable-preview
如果您不明白它的完成方式,请从帖子标题中查看我的截屏视频,那里的一切都非常清楚。
现在,开始,您需要执行三个简单的步骤:将字符串转换为源的便捷内部表示形式,对其进行编译并运行:
public static void main(String[] args) throws Exception { RuntimeSource file = RuntimeSource.create();
有一个用于“便捷表示”的
SimpleJavaFileObject
类,但是它具有一个有趣的功能。 它是非常抽象的。 也就是说,其已编译源应返回的键方法始终引发执行,以希望我们将其子类化:
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { throw new UnsupportedOperationException(); }
因此,您必须写一些继承人。 请注意,原始的
SimpleJavaFileObject
构造函数需要已编译类的URI,但是我们从哪里得到呢? 因此,我建议以最明显的方式粘贴它,例如
buildURI
函数中的
buildURI
:
public static class RuntimeSource extends SimpleJavaFileObject { private String contents = null; @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { return contents; } private static RuntimeSource create() throws Exception { return new RuntimeSource(CNAME, SOURCE); } public RuntimeSource(String className, String contents) throws Exception { super(buildURI(className), Kind.SOURCE); this.contents = contents; } public static URI buildURI(String className) {
现在让我们继续编译:
public static void compile(List<RuntimeSource> files) throws IOException { File ccDir = new File(CODE_CACHE_DIR); if (ccDir.exists()) { FileUtils.deleteDirectory(ccDir); FileUtils.forceMkdir(ccDir); } JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); Logger c = new Logger(); StandardJavaFileManager fileManager = compiler.getStandardFileManager(c, Locale.ENGLISH, null); Iterable options = Arrays.asList("-d", CODE_CACHE_DIR, "--release=12", "--enable-preview", "-Xlint:preview"); JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, c, options, null, files); if (task.call()) { System.out.println("compilation ok"); } }
请注意:我们传递了四个组装标志,其中三个标志负责在Idea的javac设置中指定与使用鼠标所做的完全相同的选项。
最后,运行我们的临时课程:
public static String run() throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, MalformedURLException {
请注意,
var clss = loader.loadClass
比
Class<?> clss = loader.loadClass
var clss = loader.loadClass
编写,并且不会引入任何新的变化。
var
关键字出现在前十名中。
另请注意,建议从9开始削减
clss.newInstance()
。 他吞下异常,这很糟糕。 九人建议首先调用
getConstructor
,该方法已参数化并抛出正确的异常。
还请注意,我将变量称为
class
,但是Java却没有誓言。 作业:您可以通过多种方式来完成作业,您需要了解哪种方式最有趣以及为什么。
好吧,总的来说,仅此而已。 可以用
自动化技术
评论家会在这里惊叹,这里的所有内容都是黑色的,因为Java世界中有一些库可以一站式为您编译所有内容。
好,让我们看一下。 这是位于Google顶部的JOOR库中的代码:
package io.javawatch; import org.joor.Reflect; import java.util.function.Supplier; public class Automatic { public static void main(String[] args) { Supplier<String> supplier = Reflect.compile( "io.javawatch.HelloHabr", ` package io.javawatch; public class HelloHabr implements java.util.function.Supplier<String> { public String get() { return "Hello Habr!"; } };` ).create().get(); System.out.println(supplier.get()); } }
好像一切都很好。 的确,除了我不得不拖动saplayer之外,一行都可以。
但是有细微差别。 尝试返回“ Hello Habr!” 像原始字符串文字一样:
public String get() { return ``Hello Habr!``; }
一切都会立即崩溃,并显示错误“(使用--able-preview启用原始字符串文字)”。 但是我们已经打开了吗? 是的,两个地狱。 我们将其包含在Idea中,然后JOOR使用系统编译器进行构建! 让我们看看里面是什么:
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); ompiler.getTask(out, fileManager, null, null, null, files).call();
当我们自己调用相同的JavaCompiler时,我们呢?
Iterable options = Arrays.asList("-d", CODE_CACHE_DIR, "--release=12", "--enable-preview", "-Xlint:preview"); JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, c, options, null, files);
而在JOOR中,仅有一个空null而不是选项。 他们甚至无法通过里面!
在JOOR中向Github发送这样的拉取请求可能是一个好主意。 如果我自己不想做,那就去吧?
而且道德很简单,不要怕开源礼物。 有时候,写下一小段文字会比较容易,但是可以控制它。
最简单的方法
有一种方法不写文字墙,也不使用可疑库。 从Java 9开始,我们有一个交互式外壳程序(类似于Python,Ruby和其他脚本语言的外壳程序),可以执行Java命令。 当然,它是用Java本身编写的,并且可以作为Java类使用。 您可以创建它的实例,然后直接直接执行必要的分配:
public class Shell { public static void main(String[] args) { var jShell = JShell.create();
Streams出现在Java 8中,现在已在各处使用,您甚至不需要自己调用
stream()
,其他人会为您调用它。 在这种情况下,调用
variables()
完全返回流,而不是ArrayList,就像一个困难的七个童年时期的人会做的那样。 流的结果可以立即倒入
var
。
请注意,现在您也可以在lambda参数中编写
var
。 自Java 11起,此功能就一直存在。
通常,这是非常重要的一类。 它使用了来自不同Java世代的许多功能,所有这些看起来都是整体和谐的。 我确信这样的事情将被所有人和世界各地所使用,因此Java 12中的代码在视觉上将直接不同于Java 7中的代码。
总结一下
我们研究了一些功能:
- 8:溪流(用于坦克中的人)
- 9:JShell和新的不推荐使用的方法
- 10:var关键字
- 11:lambda参数的Var开发
- 12:原始字符串文字及其在IntelliJ IDEA中的支持
对初学者的一点警告。 如果您在没有任何特殊含义的实际应用程序中不断进行此操作,那么您的同事会首先发疯,试图理解您的内容,然后他们可能会非常痛苦地击败您。 而且,我现在不是在谈论新的Java功能,而是在运行时进行编译。
如果您想了解有关Java作为一种语言的更多信息,那么您应该例如查看Tagir Valeev的报告。 您知道他是
哈尼 (Habré)Java集线器顶端的家伙。 在Joker,他谈论了
Amber ,在JPoint,谈论了他著名的
难题 ,等等。 那里,以及有关Java语言和IntelliJ IDEA的所有信息。 所有这些都可以
在YouTube上找到 。 实际上,出于对Tagir的嫉妒,他可以说一些关于语言本身的信息,但我没有,这篇文章已经证明了。 也将有新的玩笑者和JPoint,但我们稍后会讨论。
我履行了我的道德义务,这是Java的义务。 从我这边,子弹飞了出来。 在那七个没有第十二个Java的人那里,您一直都很好,心情很好,身体健康。 谢谢啦