Java中的标记接口

image

标记接口

标记接口是内部没有任何方法或常量的接口。它提供有关对象的运行时类型信息,因此编译器和 JVM 具有有关该对象的附加信息。

早起的Java版本中,标记接口主要用来提供一种方法像编译器或者运行时发出信号,表示某个类具有特殊属性。而且大多时候都是底层框架提供,并且同时实现检查。

常见示例

Java中内置的常见标记接口,比如Serializable、Cloneable和 Remote。

  • 当实现了Serializable接口,表示当前类的对象是可以被序列化和反序列化处理的,也就是说可以被ObjectOutputStream、ObjectInputStream里读取和写入的。
  • 如果一个类没有实现序列化接口,却当成序列化对象传入,此时就会异常。【需要注意的是,ObjectOutputStream、ObjectInputStream接受的参数是Object类型,并不是Serializable类型,因此出只会在运行时才会异常;假设如果接收的只允许Serializable类型是不是更好,这样在编译时,如果传入的类没有实现序列化接口,IDE就会直接提示,编译不通过,而不是讲问题带到运行时才发现呢
package java.io;
public interface Serializable {
}

package java.lang;
public interface Cloneable{
}
  • Cloneable而言,如果我们尝试克隆未实现此接口的对象,JVM 将抛出CloneNotSupportedException。因此,Cloneable 标记接口是向 JVM 发出的一个指示 ,表示我们可以调用Object.clone()方法【同样的,因为clone是Object类中提供的方法,检查是否可以被克隆,是在运行时抛出异常的】
  • Spring中也有标记接口,属于顶层接口类,最常见的就是Aware。它作为一个顶级标记接口只是做限制,具体的Aware子接口继承它并定义自己的接口方法声明。
    /**
     * 一个标记超接口,指示bean有资格通过回调样式的方法由特定框架对象的Spring容器通知。实际的方法签名由各个子接口决定,但通常应该只包含一个接受单个参数的空返回方法。
    注意,仅仅实现Aware不提供默认功能。相反,处理必须显式地完成
     * */
    public interface Aware {
    
    }
    

标记接口的优势

  • 标记接口定义的类型是由被标记的类的实例实现的,相对于注解而言,标记接口的限定,在编译时就能发现错误,而注解只有在运行时才能发现。
  • 标记接口的可读性更强,意义更加的明确,更符合面向对象编程的多态性实现。无论是作为参数、变量,在判断某个对象是否是某个接口声明时,和判断普通对象并无二致,使用instanceof关键字即可。注解测需要通过注解解析器解析。
  • 标记接口侧重于行为,或者从广义上限定某种类型。注解侧重于属性,以及携带元数据和更多注解信息。依据实际情况而做出设计,两者并不冲突,也不能完全替代。

一个小示例

  1. 声明一个标记接口,作用很简单,只是说明继承它接口、实现它的类可以被作为一个“机器人”

    public interface Robot{}
    
  2. 业务方法中使用,假设发现是个“机器人实例”就要被回收,而不是直接销毁

    public class ToyDestoryService{
      public void destory(Object obj){
        if(obj instanceof Robot){
          System.out.print("机器人暂不彻底销毁...");
        }
        else{
          System.out.print("彻底摧毁.");
        }
        
      }
    }
    
posted @ 2024-11-11 15:56  冰雪女娲  阅读(3)  评论(0编辑  收藏  举报