Marker Interfaces in Java?

2019-01-04 05:28发布

I was being taught that Marker interface in Java is an empty interface and is used to signal to compiler or JVM that the objects of the class implementing this interface must be treated in a special way, like serializing, cloning, etc.

But lately I have learned that it actually has nothing to do with the compiler or the JVM. For example, in case of Serializable interface the method writeObject(Object) of ObjectOutputStream does something like instanceOf Serializable to detect whether the class implements Serializable & throws NotSerializableException accordingly. Everything is handled in the code and this seems to be a design-pattern so I think we can define our own marker interfaces.

Now my doubts:

  1. Is the definition of a marker interface mentioned above in 1st point wrong? How can we define a Marker interface then?

  2. And instead of using the instanceOf operator why can't the method be something like writeObject(Serializable) so that there is a compile-time type checking rather than runtime?

  3. How are Annotations better than Marker Interfaces?

10条回答
你好瞎i
2楼-- · 2019-01-04 06:14

a. I have always seen them as a design pattern and nothing JVM-Special I have used that pattern in several situations.

c. I beleive that using Annotations to mark something is a better solution then using marker interfaces. Simply because Interfaces are in the first place aimed to define common interfaces of Types / Classes. They are part of the class-hierachy.

Annotations are aimed to provide Meta-Informations to Code, and I think that marker are meta-informations. So they are exactly for that use-case.

查看更多
beautiful°
3楼-- · 2019-01-04 06:15

I have made a simple demonstration to resolve doubt no 1 and 2 :

We will be having Movable interface which will be implemented by MobilePhone.java Class and one more class LandlinePhone.java which do NOT implement Movable interface

Our marker Interface:

package com;

public interface Movable {

}

LandLinePhone.java and MobilePhone.java

 package com;

 class LandLinePhone {
    // more code here
 }
 class MobilePhone implements Movable {
    // more code here
 }

Our Custom Exception Class : package com;

public class NotMovableException extends Exception {

private static final long serialVersionUID = 1L;

@Override
public String getMessage() {
    return "this object is not movable";
}
// more code here
}

Our Test class : TestMArkerInterface.java

package com;

 public class TestMarkerInterface {

public static void main(String[] args) throws NotMovableException {
    MobilePhone mobilePhone = new MobilePhone();
    LandLinePhone landLinePhone = new LandLinePhone();

    TestMarkerInterface.goTravel(mobilePhone);
    TestMarkerInterface.goTravel(landLinePhone);

}

public static void goTravel(Object o) throws NotMovableException {
    if (!(o instanceof Movable)) {
        System.out.println("you cannot use :" + o.getClass().getName() + "   while travelling");
        throw new NotMovableException();
    }

    System.out.println("you can use :" + o.getClass().getName() + "   while travelling");
}}

Now when we execute main class :

you can use :com.MobilePhone while travelling
you cannot use :com.LandLinePhone while travelling
Exception in thread "main" com.NotMovableException: this object is not movable
    at com.TestMarkerInterface.goTravel(TestMarkerInterface.java:22)
    at com.TestMarkerInterface.main(TestMarkerInterface.java:14)

So Which ever class implements marker interface Movable will pass the test else error message will be displayed.

This is the way instanceOf operator check is done for Serializable, Cloneable etc

查看更多
倾城 Initia
4楼-- · 2019-01-04 06:19

The main purpose of marker interfaces is to create special types where types themselves have no behavior of their own.

public interface MarkerEntity {

}

public boolean save(Object object) throws InvalidEntityFoundException {
   if(!(object instanceof MarkerEntity)) {
       throw new InvalidEntityFoundException("Invalid Entity Found, can't be  saved);
   } 
   return db.save(object);
}

Here save method makes sure that only the objects of classes that implement the MarkerEntity interface are saved, for other types InvalidEntityFoundException is thrown. So here MarkerEntity marker interface is defining a type that adds special behavior to the classes implementing it.

Though annotations can also used now to mark classes for some special treatments but marker annotations are replacement for naming pattern not for Marker interfaces.

But marker annotations can't fully replace the marker interfaces because; marker interfaces are used to define type (as already explained above) where as marker annotations do not.

Source for marker interface comment

查看更多
Ridiculous、
5楼-- · 2019-01-04 06:22

It is not possible to enforce Serializable on writeObject because children of non-serializable class can be serializable, but they instances may be upcasted back to the parent class. As a result, holding a reference to something non-serializable (like Object) does not mean that the referred instance really cannot be serialized. For instance in

   Object x = "abc";
   if (x instanceof Serializable) {
   }

the parent class (Object) is not serializable and would be initialized using its parameter-less constructor. The value referenced by x, String, is serializable and the conditional statement would run.

查看更多
登录 后发表回答