美文网首页
第四十一条:用标记接口定义类型【枚举和注解end】

第四十一条:用标记接口定义类型【枚举和注解end】

作者: taogan | 来源:发表于2021-02-25 10:38 被阅读0次

标记接口是不包含方法声明的接口,他只是指明(或者“标明”)一个类实现了某种属性的接口。例如,考虑Serializable接口(详见第12章)。通过实现这个接口,类表明它的实例可以被写入ObjectOutputStream中(或者“被序列化”)。

你可能听说过标记注解(详见第39条)使得标记接口过时了。这种断言是不正确的。标记接口有两点胜过标记注解。首先,也是最重要的一点是,标记接口定义的类型是由被标记类的实例实现的;标记注解则没有定义这样的类型。标记接口类型的存在,允许你在编译时就能捕捉到在使用标记注解的情况下要到运行时才能捕捉到的错误

Java序列化设施(详见第6章)利用Serializable标记接口表明一个类型是可以序列化的。ObjectOutputStream.writeObject方法将传入的对象序列化,其参数必须是可序列化的。该方法的参数类型应该为Serializable,如果试着序列化一个不恰当的对象,(通过类型检查)在编译时就会发现。编译时的错误侦测时标记接口的目的,但遗憾的是,ObjectOutputStream.write API并没有利用Serializable接口的优势:其参数声明为Object类型,因此,如果尝试序列化一个不可序列化的对象,将知道程序运行时才会失败。

标记接口胜过标记注解的另一个优点是,它们可以被更加精确的进行锁定。如果注解类型用目标ElementType.TYPE声明,它就可以被应用于任何类或者接口。假设有一个标记只适用于特殊接口的实现。如果将它定义成一个标记接口,就可以让它扩展它所适用的唯一接口,确保所有被标记的类型也都是该唯一接口的子类型

Set接口可以说就是这种有限制的标记接口。它只适用于Collection子类型,但是它不会添加除了Collection定义之外的方法。一般情况下,不把它当作是标记接口,因为它改进了几个Collection方法的合约,包括add、equals和hashCode。但是很容易想象只适用于某种特殊接口的子类型的标记接口,它没有改进接口的任何方法的合约。这种标记接口可以描述整个对象的某个约束条件,或者表明实例能够利用其他某个类的方法进行处理(就像Serializabele接口表明实例可以通过ObjectOutputStream进行处理一样)。

标记注解胜过标记接口的最大优点在于,它们是更大的注解机制的一部分。因此,标记注解在那些支持注解作为编程元素之一的框架中同样具有一致性。

那么什么时候应该适用标记注解,什么时候应该适用标记接口呢?很显然,如果标记是应用于任何程序元素而不是类或者接口,就必须使用注解,因为只有类和接口可以用来实现或者扩展接口。如果标记只应用于类和接口,就要问问自己:我要编写一个还是多个只接收有这种标记的方法呢?如果是这种情况,就应该优先使用标记接口而非注解。这样你就可以用接口作为相关方法的参数类型,它可以真正为你提供编译时进行类型检查的好处。如果你确信自己永远不需要编写一个只接收带有标记的对象,那么或许最好使用标记注解。此外,如果标记是广泛使用注解的框架的一个组成部分,则显然应该选择标记注解。

总而言之,标记接口和标记注解都各有用处。如果想要定义一个任何新方法都不会与之关联的类型,标记接口就是最好的选择。如果想要标记程序元素而非类和接口,或者标记要适用于已经广泛使用了注解类型的框架,那么标记注解就是正确的选择。如果你发现自己在编写的是目标ElementType.TYPE的标记注解类型,就要点时间考虑清楚,它是否真的应该为注解类型,想象标记接口是否会更加合适

从某种意义上说,本条目第第22条中”如果不想定义类型就不要使用接口“的说法相反,本条目最接近的意思是说:”如果想要定义类型,一定要使用接口“。

相关文章

网友评论

      本文标题:第四十一条:用标记接口定义类型【枚举和注解end】

      本文链接:https://www.haomeiwen.com/subject/rupsfltx.html