来自不同编程语言的竞争,正在驱使Java不断吸收新特性,更加适应时代和开发者的新需求。我们行业一直有一个热门话题,那就是对Java的批判,很大程度上是因为它的繁琐和生成的样板代码量很大,在很多场景下根本不需要。虽然我一直很喜欢Java,但我不能说这些指责是错误的。事实上,在许多情况下,Java的繁琐和大量的混乱是令人讨厌的。在大多数情况下,我们不得不接受我们生活在一个不完美的世界中的事实,很多时候我们不得不在两害相权取其轻。我们都知道Java并不完美,但主要问题是为什么在此之前没有采取任何措施来解决这些问题?我认为改变需要这么长时间的唯一原因是Java没有足够的竞争。Java语言之所以能够称霸市场,很可能是因为缺乏真正的竞争者,当然也离不开Sun和后来的甲骨文的巨大努力。Java提供的强类型安全性,以及作为一种结构良好的语言所具有的其他特性,使其成为大型项目中非常流行的语言。通过使用Java,我们很少让事情失控。Java的另一个重要特性是它是一种在自己的虚拟机上运行的多平台语言,这使得它非常适合许多组织。如果您启用著名的JIT编译器执行自动性能优化的固有能力,那么在许多情况下可以将错误代码的影响降至最低,并且我们有充分的理由使用Java。但后来发生了什么?接下来是可以与Java在同一JVM中运行的新语言上市,这消除了Java中最令人头疼的问题,并为开发人员提供了更好的环境,而且在许多情况下,他们的学习曲线非常平坦。在继续之前,让我们简要回顾一下JVM语言的历史。1.JVM语言的历史在开始之前,我想澄清一下,我省略了一些现有的JVM语言,主要是因为它们从未获得足够的吸引力,无法被认为在我们的行业候选语言中被广泛使用。那么,让我们首先快速浏览一下JVM语言的历史。图片来自Unsplash网站,作者:MaximilianWeisbecker我们的旅程当然是从Java开始的,它是JVM世界中最古老、最受欢迎的语言。Java语言于1996年1月首次正式发布,至今已有24年历史,对吧?最初,Java是一种遵循纯面向对象编程风格的命令式语言。它也是一种强类型语言,Java的语法有点类似于C++和C,但它被认为是一个改进版本,因为用Java编写代码比C或C++容易得多。此外,在其批评者中,最大的争议是其繁琐。第二个发布的JVM语言是Groovy,它于2003年首次出现,尽管它的第一个正式标准版本1.0是在2007年发布的。Groovy的好处在于它也可以用作脚本语言。Groovy是一种动态类型语言,因此类型检查发生在运行时;这是一些开发人员不喜欢Groovy的原因之一。我们在Groovy中编写的代码在编译时看起来是正确的,但在运行时我们发现有问题。图片来源:Wikipedia接下来介绍另一种流行的语言,即Scala,我们将讨论它。Scala于2004年正式发布,为JVM世界带来了一种新的编程模型,即函数式编程及其声明式方法。我们可以肯定,Scala最先提出了不变性的思想,因此对Java的改造做出了重要的贡献。另一方面,Scala的批评者不喜欢它,因为它的语法复杂且可读性通常很差。图片来源:维基百科JVM领域出现的下一个语言是Clojure,这是一种最近变得非常流行的纯函数式语言,但它首次出现是在2007年。Clojure是一种基于LISP的语言,其特点是简单和使用纯函数.在其缺点中,值得一提的是动态类型(与Groovy相同)和更陡峭的学习曲线,因为它的语法与其他JVM语言完全不同。如果你有兴趣学习Clojure,有两本好书你应该读一读:《Clojure的乐趣》和《ProgrammingClojure(ThirdEdition)》。图片来源:维基百科最后但同样重要的是Kotlin!Kotlin于2016年2月首次发布,从那时起它就越来越受欢迎。该语言由JetBrains公司设计,目标明确:消除Java中的所有常见问题。它的设计方式保留了Java的所有优点,但消除了它的大部分问题,这就是为什么它如此受欢迎,以至于许多人甚至认为它有可能在未来几年内击败Java。如果您想了解更多关于Kotlin的信息(我鼓励您这样做,因为它是一门很棒的语言),那么我建议您阅读《KotlininAction》一书,这对Java开发人员来说是一本很好的指南。一本入门Kotlin的好书。图片来自Unsplash网站byLouisTsai以下是最重要的JVM语言,我们省略了一些不太流行的JVM语言,但我们可以提及它们的名称:Jython、JRuby、Ceylon、Fantom等。您可以获得现有JVM的完整列表此地址的语言。我们可以看到,在最初的八年、十年里,Java没有太多的竞争,但是从那以后,Java就面临着一些竞争,那么竞争是好事还是坏事呢?2.竞争加剧的好处正如我们之前所说,Java在早期并没有太大变化,很可能是因为不需要它,虽然它远非完美,但它被广泛接受。使用。然而,新的竞争者已经出现,这些更现代的语言带来了新的特性,解决了一些长期困扰Java开发者的痛点。举个例子,让我们看看自2009年以来越来越流行的Scala语言,开发人员接受了这种新的函数式风格,这使他们能够更灵活、更安全地编码,并轻松生成并行代码。我们可以在下面的GoogleTrends图中看到这一趋势:图片来源:theboreddev.com那么Oracle对这一新趋势的反应是什么?那是在2014年发布JavaLambdas和Streams的时候。当时很多人认为这是Java击败Scala的最大举措。业内人人都能感受到Scala这几年因为没有流而受到的损失。JVM空间中存在竞争的另一个好处是JIT编译器和JVM本身正在经历的持续改进。现在,越来越多的人对JVM优化和性能提升感兴趣。所以,竞争对每个人都有好处。Kotlin是这个领域的最新成员。Kotlin非常重要,因为它为Oracle指明了前进的方向。Kotlin表明它可以保留Java的优点,同时创建一种更简洁、更快速的编码语言。如果我们看一下GoogleTrends,就可以看出Kotlin在过去几年的流行程度:图片来源:theboreddev.com从图中可以看出,Kotlin迅速变得非常流行,但最近几年似乎稳定下来。Oracle很好地记录了行业对Kotlin的反应,如果您查看JDK15的发行说明,一些新的Java功能基本上是Kotlin更改的重复。例如,新的Java记录、文本块(使用三重引号的多行字符串)和switch语句(或多或少借鉴了Kotlin的when语句)。我们可以通过这个地址参考JDK15的releasenotes。刚才提到的,我称之为“Java的科特林化(Kotlinisation)”。Kotlin成为Java有史以来最强大的竞争对手,从而为Java设定了方向。在我看来,Kotlin是我见过的唯一一种能够打败Java成为行业领导者的语言。3.Java的“Kotlin”Java的一些新特性主要是增强可读性,改善其主要弱点之一,即笨重。我们可以断言它与Kotlin的一些特性有相似之处。需要注意的是,这些功能中的大部分仍处于功能预览阶段,这意味着当您安装JDK14或JDK15时,默认情况下不会启用这些功能。Java功能预览是发布版本中包含但默认情况下禁用的功能。它们包含在发布中只是为了收集社区开发人员的反馈,因此它们更频繁地更改,这就是为什么不建议在生产代码中使用它们。要在编译时启用这些功能,我们需要执行以下代码:javac--enable-preview--release14如果要在运行时启用它们,请执行以下代码,如下所示:Javajava--enable-previewYourClass当然,您也可以在IDE中启用它们,但默认情况下不要在新项目中启用预览。下面我们就来看看这些变化,在以后的Java版本中,对我们编码的影响会比较大。JavarecordJavarecord是我们要求很久的一个特性,相信大家之前也遇到过很多次这种场景,就是勉强实现每个字段的toString、hashCode、equals方法和getter(这里,我我假设您不再实现setter,还记得我们在“Java中的新并发模型”一文中谈到的不变性吗?)。Kotlin提供了数据类来解决这个问题,Java也通过发布记录类解决了这个问题,Scala通过案例类解决了同样的问题。这些类的主要目的是在对象中保存不可变数据。让我们通过一个例子看看它在Java中的表现如何。我们我们实例化并员工类:packagecom.theboreddev.java14;importjava.util.objects;impactjava.util.objects;prublyClassEmployee{privateFinalfinalFirstName;privatefinalStranme;privateFinalStransem;privatefinallinefinallinefinalfinalfinal;privatefinallyfinallyfinaldrandintring;){this.firstName=firstName;this.surname=surname;this.age=age;this.address=address;this.salary=salary;}publicStringgetFirstName(){returnfirstName;}publicStringgetSurname(){returnsurname;}publicintgetAge(){returnage;}publicAddressgetAddress(){returnaddress;}publicdoublegetSalary(){returnsalary;}@Overridepublicbooleanequals(Objecto){if(this==o)returntrue;if(o==null||getClass()!=o.getClass())returnfalse;Employeeemployee=(Employee)o;returnage==employee.age&&Double.compare(employee.salary,salary)==0&&Objects.equals(firstName,employee.firstName)&&Objects.equals(surname,employee.surname)&&Objects.等于(地址,雇员.address);}@OverridepublicinthashCode(){returnObjects.hash(firstName,surname,age,address,salary);}@OverridepublicStringtoString(){return"Employee{"+"firstName='"+firstName+'\''+",surname='"+surname+'\''+",age="+age+",address="+address+",salary="+salary+'}';}}它所含的地址如下所示:packagecom的{returnfirstLine;}publicStringgetSecondLine(){returnsecondLine;}publicStringgetPostCode(){returnpostCode;}@Overridepublicbooleanequals(Objecto){if(this==o)returntrue;if(o==null||getClass()!=o.getClass())returnfalse;Addressaddress=(Address)o;returnObjects.equals(firstLine,address.firstLine)&&Objects.equals(secondLine,address.secondLine)&&Objects.equals(postCode,address.postCode);}@OverridepublicinthashCode(){returnObjects.hash(firstLine,secondLine,postCode);}@OverridepublicStringtoString(){return"地址{"+"firstLine='"+firstLine+'\''+",secondLine='"+secondLine+'\''+",postCode='"+postCode+'\''+'}';}}为了完成一件简单的事情,我们写的代码太多了吧?接下来,让我们看看使用新的Java记录后代码会是什么样子:publicrecordEmployeeRecord(StringfirstName,Stringsurname,intage,AddressRecordaddress,doublesalary){}再看看Address类:publicrecordAddressRecord(StringfirstLine,StringsecondLine,StringpostCode){}这和我们之前写的一堆代码是一样的效果,不得不承认:很酷!在节省的代码量和简单性方面现在让我们看看新的switch语句有何不同。改进的switch语句新的switch语句解决了在Java中使用switch语句的一些固有问题。长期以来,我们一直被教导应该避免使用switch语句,因为它们容易出错并导致代码重复。比如我们很容易遇到某个case条件无法覆盖的场景。新的switch语句解决了这个问题,因为如果我们的switch语句没有覆盖我们传递给它的域类型的所有范围,它就不会编译。为了说明这个例子,让我们在Java中创建一个DayOfTheWeek枚举:publicenumDayOfTheWeek{MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY}我们需要switch语句来告诉我们星期几对应的位置。看看如何用Java11实现它:finalDayOfTheWeekdayOfTheWeek=DayOfTheWeek.THURSDAY;intposition=0;switch(dayOfTheWeek){caseMONDAY:position=1;break;caseTUESDAY:position=2;break;caseWEDNESDAY:position=3;break;caseTHURSDAY:position=4;break;caseFRIDAY:position=5;break;caseSATURDAY:position=6;break;caseSUNDAY:position=7;break;}System.out.println("Day"+dayOfTheWeek+"isinposition"+position+“一周中的”);对于原始的switch语句,我们必须使用一个变量,如果我们省略了星期几,代码就会编译。这是switch语句的问题之一,它非常容易出错。Java14将如何改善这种情况?让我们快速浏览一下:finalDayOfTheWeekdayOfTheWeek=DayOfTheWeek.THURSDAY;intposition=switch(dayOfTheWeek){caseMONDAY->1;caseTUESDAY->2;caseWEDNESDAY->3;caseTHURSDAY->4;caseFRIDAY->5;caseSATURDAY->6;caseSUNDAY->7;};System.out.println("Day"+dayOfTheWeek+"isinposition"+position+"oftheweek");我们可以看到,新的switch语句可以作为一个表达式来使用,而不仅仅是一个语句。结果更加简洁和表达,这足以说服我们使用它。不过目前的switch还有一个重要的改进,就是如果switch中没有覆盖到所有的case,就会编译失败。它将显示如下错误:Error:(9,24)java:theswitchexpressiondoesnotcoverallpossibleinputvaluesNow,wedon'tmisscasesinswitchstatements,这是一个很棒的功能。这与Kotlin的when语句非常相似,您可以在此处阅读更多相关信息。接下来,我们看看文本块。文本块您是否遇到过将大型JSONblob分配给Java变量的情况?你是否也受够了这种丑陋的代码?Java会引入多行字符串特性,我们可以通过三引号封装来定义。当这个特性正式发布时,定义多行的长字符串会更容易。让我们来看看这两种模式之间的区别。假设我们要将格式化的JSON存储到变量中,丑陋的代码如下所示:finalStringtext="{\"widget\":{\n"+"\"debug\":\"on\",\n"+"\"window\":{\n"+"\"title\":\"SampleKonfabulatorWidget\",\n"+"\"name\":\"main_window\",\n"+"\"width\":500,\n"+"\"height\":500\n"+"},\n"+"\"image\":{\n"+"\"src\":\"图片/Sun.png\",\n"+"\"name\":\"sun1\",\n"+"\"hOffset\":250,\n"+"\"vOffset\":250,\n"+"\"alignment\":\"center\"\n"+"},\n"+"\"text\":{\n"+"\"data\":\"点击这里\",\n"+"\"size\":36,\n"+"\"style\":\"bold\",\n"+"\"name\":\"text1\",\n"+"\"hOffset\":250,\n"+"\"vOffset\":100,\n"+"\"alignment\":\"center\",\n"+"\"onMouseUp\":\"sun1.opacity=(sun1.opacity/100)*90;\"\n"+"}\n"+"}}";编写整洁的代码更容易:finalStringmultiLineText="""{"widget":{"debug":"on","window":{"title":"SampleKonfabulatorWidget","name":"main_window","width":500,"height":500},"image":{\s"src":"Images/Sun.png","name":"sun1","hOffset":250,"vOffset":250,"alignment":"center"},"text":{"data":"ClickHere","size":36,"style":"bold","name":"text1","hOffset":250,"vOffset":100,"对齐方式":"center","onMouseUp":"sun1.opacity=(sun1.opacity/100)*90;"}}}""";我觉得这样好多了这也是Kotlin支持的,可以在此处的类型定义中找到。综上所述,我们可以看到Java从其竞争对手之一,即Kotlin那里“继承”了很多针对自身问题的解决方案。不知道甲骨文这次有没有及时做出正确的反应来对抗Kotlin的崛起,或许来的有点晚了。但我个人认为Java正在朝着正确的方向前进,尽管这些变化不知何故是由其竞争对手引发的,而且可能有点晚了。如前所述,如果这篇文章激发了你学习Kotlin语言的兴趣,我推荐阅读《KotlininAction》,这是一本非常适合Java开发人员的Kotlin入门书籍。4.结论我认为竞争是Java语言有史以来最好的事情。如果你不这样做,Java将成为茧。Java的竞争者还展示了不同的编程方式是可能的,它展示了前进的方向,让我们避免老式、过时的代码编写方式。我最近看到了Java的一些变化,以及所有即将到来的特性和改进,它们使Java比以往任何时候都更强大。它是一种适合时代的语言,一种想要进化并忘记传统做事方式的语言:Java的新未来!
