반응형

이전 블로그에서 2017년 7월 21일에 작성한 글


Constant Interface를 위키에서 보다가 Constant Interface는 런타임 시에는 사용할 목적이 없지만, Marker Interface는 런타임 시에 사용할 목적이 있다고 표현되어 있었다. 고로 Marker Interface도 인터페이스이지만 메서드 선언이 없는 인터페이스라고는 추측은 되지만 그렇다면 어떤 용도로 사용하는지 자료를 찾아보았다.

 

Marker Interface

Marker Interface란 아무것도, 즉 변수와 메서드를 정의하지 않은 인터페이스이다. 먼저 대표적인 Marker Interface에는 ​자바에서 종종 보는 Serializable, Cloneable​ 인터페이스가 있다. 대학원을 다녔을 때, 오브젝트 정보를 파일로 저장하고 불러올 때 사용을 해봤지만 안에 어떤 것이 들어있는지 확인은 하지 않았다. 아래는 ​Cloneable​의 코드이다.

package java.lang;

/**
 * A class implements the <code>Cloneable</code> interface to
 * indicate to the {@link java.lang.Object#clone()} method that it
 * is legal for that method to make a
 * field-for-field copy of instances of that class.
 * <p>
 * Invoking Object's clone method on an instance that does not implement the
 * <code>Cloneable</code> interface results in the exception
 * <code>CloneNotSupportedException</code> being thrown.
 * <p>
 * By convention, classes that implement this interface should override
 * <tt>Object.clone</tt> (which is protected) with a public method.
 * See {@link java.lang.Object#clone()} for details on overriding this
 * method.
 * <p>
 * Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
 * Therefore, it is not possible to clone an object merely by virtue of the
 * fact that it implements this interface.  Even if the clone method is invoked
 * reflectively, there is no guarantee that it will succeed.
 *
 * @author  unascribed
 * @see     java.lang.CloneNotSupportedException
 * @see     java.lang.Object#clone()
 * @since   JDK1.0
 */
public interface Cloneable {
}

 

그렇다면 Marker Interface는 어디에 사용될까? instanceof 연산자를 사용하여 런타임에서 객체에 대한 타입을 확인하여 프로그램의 흐름을 제어할 수 있다. 즉 Maker Interface는 특별한 기능을 하는 것이 아닌 단순히 해당 객체의 타입을 구분하는 정도로 사용한다.

 

예를 들어 오브젝트를 입력받아 스트림에 쓰는 ObjectOutputStream.writeObject(Object obj)는 Object를 인자로 받는다. 이 매소드는 writeObject0(Object obj, ...)​을 호출한다. 이 매소드는 Object의 타입에 따라 다시 알맞은 매소드를 호출한다. 아래는 writeObject0(Object obj, ...)​의 코드 일부이다. (String, Enum도 Serializable이지만 처리를 다르게 하려고 구분한 것으로 보임)

public class ObjectOutputStream extends OutputStream implements ObjectOutput, ObjectStreamConstants {

 // ...
 private void writeObject0(Object obj, boolean unshared) throws IOException {

  // ...
  if (obj instanceof String) {
   writeString((String) obj, unshared);
  } else if (cl.isArray()) {
   writeArray(obj, desc, unshared);
  } else if (obj instanceof Enum) {
   writeEnum((Enum<?>) obj, desc, unshared);
  } else if (obj instanceof Serializable) {
   writeOrdinaryObject(obj, desc, unshared);
  } else {
   if (extendedDebugInfo) {
    throw new NotSerializableException(cl.getName() + "\n" + debugInfoStack.toString());
   } else {
    throw new NotSerializableException(cl.getName());
   }
  }

  // ...
 }
}
반응형

+ Recent posts