marker_有没有更好的Marker方法?

marker

marker

自Java 1.5推出以来,就是否在Java中使用Marker接口进行了广泛的讨论和辩论。 这是因为Java 1.5引入了注释功能,这些功能几乎可以解决Marker接口的目的。 本文将涵盖这场辩论的一个有趣的部分。
定义:
Java中的标记接口是一个空接口,没有任何方法,字段或常量。 有时也称为标记接口。

那么为什么使用Marker接口呢?

有效的问题! 它不能解决与实现该接口的类定义契约的接口的目的。 这些接口定义了没有实现的方法,因为它们告诉子类需要做什么,但是由子类决定如何实现此方法。 但是,在Marker接口的情况下,没有成员。

标记接口是一种声明有关类的元数据的方法。 它告诉JVM,需要以不同的方式对实现标记器接口的类的对象进行特殊处理。 Java API中定义了一些现成的Marker接口:java.io.Serializablejava.lang.Cloneablejava.util.RandomAccessjava.util.EventListener我们也可以像创建其他接口一样创建自己的标记接口版本。

让我们更深入地了解Cloneable接口。 当需要在Java中克隆对象时,我们使用Object的clone()方法。 但是请注意,此方法不是Cloneable接口的一部分,即,当您的类默认实现Cloneable接口时,将不会像其他任何标准接口一样实现clone方法。 当我们明确定义它或调用对象的clone方法时,就可以完成它。因此,不可能仅凭借对象实现此接口的事实来克隆对象。 即使克隆方法是反射式调用的,也不能保证它会成功。

public Object clone() {
		Object clone = null;
		try {
			clone = super.clone();
		} catch (CloneNotSupportedException e) {
			e.printStackTrace();
		}
		return clone;
}

这里的一个关键点是,当您尝试使用clone()方法克隆对象时,除非实现Cloneable接口,否则将获得CloneNotSupportedException 。 JVM非常聪明–是吗?

注意事项:

如前所述,除了使用内置的标记接口之外,我们还可以创建特定于应用程序的标记接口,因为这是标记和逻辑分类代码的一种好方法。 这在尝试创建框架或开发API时主要有用。

有趣的一点:

Runnable不是Marker接口。 尽管run是对JVM启动方法的特殊指令,但是Runnable并不是标记接口,因为Runnable内部有一个公共的void run()方法。

标记界面存在问题:

标记接口的主要问题是接口定义了用于实现类的协定,并且该协定被所有子类继承。 这意味着您不能取消实施标记。 如果创建不想序列化的子类(可能是因为它依赖于瞬时状态),则必须诉诸显式抛出NotSerializableException .

现在让我们回到重点。 使用注释比标记界面更好吗?

为了回答这个问题,让我们更详细地研究Java注释。

定义:
Java注释是Java 1.5中引入的语法元数据(关于数据的数据)的特殊形式。 像Java类一样,接口甚至注释都可以在多个Java元素上使用。

标记界面与标记注释

与Javadocs不同,Annotations具有丰富的功能,有助于在运行时进行处理。 注释用于程序包或类声明,方法声明,字段声明和变量声明中。 它减少了编码工作,让开发人员可以轻松开发,专注于业务逻辑,从而提高了自动化程度。

注释与标准Java元素之间用“ @”符号分隔。 每当编译器遇到带有任何Java元素的这些注释时,它都会从注释中提取信息并自动生成代码。

注释的用途:

  • 将信息传递给编译器–用于检测错误或抑制警告。 例如@ SuppressWarnings,@不建议使用
  • 编译时间和部署时间处理–几种工具可以处理注释信息以生成代码XML文件等。诸如Spring,Hibernate之类的框架大量使用注释。
  • 运行时处理–仅在运行时处理这些批注。

以标记接口的类似方式,我们还具有标记注释。 标记注释没有任何方法或元素。 该行为与Marker接口相同。

例如, @ Override是内置的Java Marker批注类型,可以将其实现为方法,以指示编译器编译器该方法将覆盖超类中的方法。 它不包含任何其他程序元素。 如果您在不覆盖超类方法的方法上使用此批注,则编译器将发出编译错误以提醒您该事实。 这种注释类型可以防止程序员在重写方法时犯错误,因为开发人员很可能实际上会在超类中重载方法而不是重写。

注释比标记界面似乎是更好的选择,因为注释可以实现相同的效果。

  • 它可以标记变量,方法和/或类。
  • 它可以专门标记任何类,也可以通过继承标记。 标记接口将标记已标记类的所有子类。 例如,如果我们必须将一个类标记为不可序列化,则必须专门将其标记为瞬态。 这可能是值得商as的,因为注释不是不可子类化的,可能是优点还是缺点。 注释默认情况下不会继承– isAnnotationPresent()会告诉您该特定类上是否存在该注释,而不是它是否存在于超类或超接口上。 因此,如果您作为批注旨在提供的特殊功能的实现者,希望批注的行为像继承一样,则不仅要检查该类,还要检查每个超类和每个超接口的isAnnotationPresent()
  • 您可以将数据添加到标记中。 换句话说,非空白的注释具有价值,因为您所标记的不仅仅是类型。

因此,他们每个人都有一定的优点和缺点,我个人认为应该由开发人员来决定是否使用标记界面或标记注释,因为他们必须决定考虑实际情况并判断优点和缺点。他们两个,并确定最适合该要求的。

参考:是否有更好的Marker方法? 从我们的JCG合作伙伴Mainak Goswami在Idiotechie博客上获得。

2012-10-30

翻译自: https://www.javacodegeeks.com/2012/10/is-there-a-better-approach-to-marker.html

marker

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值