当前位置: 首页 > 科技观察

Java 8新特性探究(4)-类型注解 复杂还是便捷

时间:2023-03-11 23:15:29 科技观察

Java8新特性探索(四):类型注解是程序中复杂或方便的配置。那些有争议的类型注释到底是什么?复杂还是方便?什么是类型注解?在Java8之前,注解只能在声明的地方使用,比如类、方法和属性;在Java8中,注解可以应用在任何地方,例如:创建一个类实例new@InternedMyObject();类型映射myString=(@NonNullString)str;implements语句classUnmodifiableListimplements@ReadonlyList<@ReadonlyT>{...}throwexceptiondeclarationvoidmonitorTemperature()throws@CriticalTemperatureException{...}required注意类型注解只是语法而不是语义,并且不会影响java的编译时间、加载时间和运行时间,即编译成class文件时不包含类型注解。类型注解的作用先看下面代码Collections.emptyList().add("One");inti=Integer.parseInt("你好");System.console().readLine();以上代码编译通过,但是运行会报UnsupportedOperationException;数字格式异常;NullPointerException,这些是运行时错误;类型注释用于支持Java程序中的强类型检查。通过插件检查框架,可以在编译过程中检测运行时错误,提高代码质量。这就是类型注解的作用。checkframeworkcheckframework是一个第三方工具,配合Java类型注解的效果是1+1>2。可以嵌入javac编译器,可以和ant、maven一起使用,也可以作为eclipse插件使用。地址是http://types.cs.washington.edu/checker-framework/。检查框架可以找到类型注释出现的位置并进行检查。举个简单的例子:importcheckers.nullness.quals.*;publicclassGetStarted{voidsample(){@NonNullObjectref=newObject();}}使用javac编译上面的classjavac-processorcheckers.nullness.NullnessCheckerGetStarted.java编译通过,但是如果修改为@NonNullObjectref=null;再次编译,出现GetStarted.java:5:incompatibletypes.found:@Nullablerequired:@NonNullObject@NonNullObjectref=null;^1error如果不想使用类型注解来检测错误,就不需要a处理器。可以直接编译javacGetStarted.java。这在具有类型注释支持版本的java8中是可能的,但在java5、6和7版本中是不可能的。因为javac编译器不知道@NonNull是什么东西,但是check框架有一个向后兼容的方案,就是用/**/来注解类型注解nonnull,比如把上面的例子修改为importcheckers.nullness.quals。*;publicclassGetStarted{voidsample(){/*@NonNull*/Objectref=null;}}这样javac编译器会忽略注释块,但是check框架中的javac编译器也可以检测到nonnull错误。通过类型注解+检查框架我们可以看到,现在运行时错误可以在编译时发现。关于JSR308JSR308想要解决Java1.5注解中出现的两个问题:注解的语法限制:注解只能写在声明的地方类型系统的语义限制:类型系统无法阻止所有的bugJSR308解决了以上两个问题通过:扩展Java语言的语法,让注解出现在更多的位置。包括:方法接收者(methodreceivers,注解:examplepublicintsize()@Readonly{...})、泛型参数、数组、类型转换、类型测试、对象创建、类型参数绑定、类继承和throws子句。其实就是类型注解,它现在是java8的一个特性。通过引入可插入类型系统(pluggabletypesystems),可以创建更强大的注解处理器。类型检查器分析带有类型限定注释的源代码,如果发现不匹配等错误则生成警告消息。事实上,检查框架是针对JSR308的。有人反对,认为它比较复杂和静态。例如,@NotEmptyList<@NonNullString>strings=newArrayList<@NonNullString>()>被动态语言替换为varstrings=["one","two"];有些人同意,归根结底,代码是“最根本”的文件。代码中包含的注释清楚地表明了代码编写者的意图。当它没有及时更新或丢失时,恰恰是注释中包含的意图信息最有可能在其他文档中丢失。而且,将运行时的错误转移到编译阶段,不仅可以加快开发进程,还可以节省测试时查bug的时间。总结不是每个人都喜欢这个特性,尤其是在动态语言比较流行的今天。幸运的是,Java8并没有强制所有人都使用这个特性。反对者可能不会使用这个特性,但有些对代码质量要求更高。个人或者公司都可以采用JSR308,毕竟代码是“最基本”的文档。我同意这句话。虽然代码会变多,但是可以让你的代码表现力更强。对于这个功能你怎么看,大家各抒己见。...原文链接:https://img.ydisp.cn/news/20220914/2gaz134rx11