web-dev-qa-db-ja.com

Javaのマーカーインターフェイス?

JavaのMarkerインターフェイスは空のインターフェイスであり、このインターフェイスを実装するクラスのオブジェクトは、シリアル化、複製、等.

しかし、最近、それが実際にはコンパイラまたはJVMとは何の関係もないことを学びました。たとえば、Serializableインターフェースの場合、ObjectOutputStreamのメソッドwriteObject(Object)は、クラスがSerializableを実装し、それに応じてNotSerializableExceptionをスローするかどうかを検出するためにinstanceOf Serializableのようなことを行います。すべてがコードで処理され、これはデザインパターンのようであるため、独自のマーカーインターフェイスを定義できると思います。

今私の疑問:

  1. 1点目の上記のマーカーインターフェイスの定義は間違っていますか?それでは、マーカーインターフェイスをどのように定義できますか?

  2. また、instanceOf演算子を使用する代わりに、メソッドをwriteObject(Serializable)のようにできないので、実行時ではなくコンパイル時の型チェックが行われるのはなぜですか?

  3. 注釈はマーカーインターフェイスよりも優れていますか?

127
Xavier DSouza
  1. 第1点で上記のマーカーインターフェイスの定義は間違っていますか?1)マーカーインターフェイスが空でなければならず、(2)それを実装することは、実装クラスの特別な扱い。不正確な部分は、JVMまたはコンパイラがそのクラスのオブジェクトを異なる方法で処理することを意味することです。これらのオブジェクトを複製可能として処理するのはJavaクラスライブラリのコードであることに注意してください。シリアライズ可能など。コンパイラまたはJVMとは関係ありません。
  2. ---(instanceOf演算子を使用する代わりに、メソッドがwriteObject(Serializable)のようなものになり得ないため、コンパイル時の型チェックがあります-これにより、マーカーインターフェイスの名前でコードが汚染されないようにします。 「プレーンObject」が必要です。たとえば、シリアライズ可能にする必要があり、オブジェクトメンバを持つクラスを作成する場合、コンパイル時にオブジェクトをキャストするか、変数Serializableにする必要があります。インターフェースには機能がないため、これは不便です。
  3. マーカーインターフェイスよりもアノテーションが優れている方法-クラスに関するメタデータをコンシューマに伝えるという同じ目的を達成できます。注釈も強力であるため、プログラマはより洗練された情報を「消費」するクラスに渡すことができます。
111
dasblinkenlight

SerializablewriteObjectを適用することはできません。なぜなら、シリアライズ不可能なクラスの子はシリアライズ可能ですが、インスタンスは親クラスにアップキャストされる可能性があるためです。その結果、シリアル化できないもの(Objectなど)への参照を保持しても、参照されたインスタンスを実際にシリアル化できないということにはなりません。例えば

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

親クラス(Object)はシリアライズ可能ではなく、パラメーターなしのコンストラクターを使用して初期化されます。 xによって参照される値Stringはシリアル化可能であり、条件ステートメントが実行されます。

20
h22

Javaのマーカーインターフェイスは、フィールドまたはメソッドのないインターフェイスです。簡単に言うと、Javaの空のインターフェイスはマーカーインターフェイスと呼ばれます。マーカーインターフェイスの例は、SerializableCloneable、およびRemoteインターフェイスです。これらは、コンパイラまたはJVMにいくつかの情報を示すために使用されます。したがって、JVMがクラスがSerializableであると認識すると、JVMはそのクラスに対して特別な操作を実行できます。同様に、JVMが何らかのクラスがCloneableを実装していると判断した場合、クローニングをサポートするためにいくつかの操作を実行できます。 RMIおよびRemoteインターフェイスについても同様です。要するに、マーカーインターフェイスは、コンパイラまたはJVMへの信号またはコマンドを示します。

上記は ブログ投稿 のコピーとして始まりましたが、文法のために軽く編集されています。

6
vidya k n

a /その名前が示すように、マーカーインターフェイスは、それについて知っているものに通知するためにのみ存在しますクラスが何かを宣言すること。何でも、SerializableインターフェースのJDKクラス、またはカスタムインターフェース用に自分で作成したクラスになります。

b /マーカーインターフェイスの場合、メソッドの存在を暗示してはなりません。インターフェイスに暗示されたメソッドを含めることをお勧めします。しかし、 why yo必要なことがわかっている場合は、必要に応じて設計することができます。

c /空のインターフェースと、値やパラメーターを使用しないアノテーションとの間にほとんど違いはありません。ただし、違いがあります。注釈は、実行時にアクセスできるキー/値のリストを宣言できます。

4
Serge Ballesta
  1. JVMとコンパイラーとは(必ずしも)関係ありません。特定のマーカーインターフェイスに関心があり、テストしているコードとは関係があります。

  2. それは設計上の決定であり、正当な理由で行われています。 AudriusMeškauskasからの回答をご覧ください。

  3. この特定のトピックに関しては、良くも悪くも問題ではないと思います。マーカーインターフェイスは、正常に機能するはずです。

3
peter.petrov

a。私は常にそれらを設計パターンとして見てきましたが、JVM特別なものは何もありません。いくつかの状況でそのパターンを使用しました。

c。注釈を使用して何かをマークする方が、マーカーインターフェイスを使用するよりも優れたソリューションであると信じています。インターフェースがそもそもタイプ/クラスの共通インターフェースを定義することを目的としているためです。それらはクラス階層の一部です。

注釈はコードにメタ情報を提供することを目的としており、マーカーはメタ情報であると思います。したがって、それらはまさにそのユースケースに適しています。

3
treeno

マーカーインターフェイスの主な目的は、タイプ自体に独自の動作がない特別なタイプを作成することです。

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);
}

ここでsaveメソッドは、MarkerEntityインターフェースを実装するクラスのオブジェクトのみが保存されるようにします。他のタイプではInvalidEntityFoundExceptionがスローされます。したがって、MarkerEntityマーカーインターフェイスは、それを実装するクラスに特別な動作を追加する型を定義しています。

アノテーションは現在、いくつかの特別な処理のためにクラスをマークするためにも使用できますが、マーカーアノテーションは、マーカーインターフェイスではなく命名パターンの代わりになります。

ただし、マーカーアノテーションはマーカ​​ーインターフェイスを完全に置き換えることはできません。マーカーインターフェイスは、マーカーアノテーションでは定義されていないタイプを定義するために使用されます(既に説明したとおり)。

マーカーインターフェイスコメントのソース

2
infoj

私は疑い1と2を解決するために簡単なデモを行いました:

MobilePhone.Javaクラスともう1つのクラスLandlinePhone.Javaによって実装されるMovableインターフェースを作成します。これらのクラスはNOT Movableインターフェースを実装します

マーカーインターフェイス:

package com;

public interface Movable {

}

LandLinePhone.JavaおよびMobilePhone.Java

 package com;

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

カスタム例外クラス:package com;

パブリッククラスNotMovableException extends Exception {

private static final long serialVersionUID = 1L;

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

テストクラス: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");
}}

さて、メインクラスを実行すると:

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)

したがって、Movableがマーカーインターフェイスを実装するクラスはどれもテストに合格し、そうでない場合はエラーメッセージが表示されます。

これは、Serializable、CloneableなどのinstanceOf演算子チェックの方法です。

2
Shashank Bodkhe

まず、SerializableとCloneableはマーカーインターフェイスの悪い例だと主張します。もちろん、それらはメソッドとのインターフェースですが、暗黙的にメソッド(writeObject(ObjectOutputStream)など)です。 (オーバーライドしない場合、コンパイラはwriteObject(ObjectOutputStream)メソッドを作成します。すべてのオブジェクトにはすでにclone()がありますが、コンパイラーは実際にclone()メソッドを作成しますが、注意が必要です。良い設計例ではありません。)

マーカーインターフェイスは通常、次の2つの目的のいずれかで使用されます。

1)多くのジェネリックで発生する可能性のある、過度に長いタイプを避けるためのショートカットとして。たとえば、次のメソッドシグネチャがあるとします。

public void doSomething(Foobar<String, Map<String, SomethingElse<Integer, Long>>>) { ... }

それは面倒で入力するのが面倒で、さらに重要なのは理解するのが難しいことです。代わりにこれを考慮してください:

public interface Widget extends Foobar<String, Map<String, SomethingElse<Integer, Long>>> { }

次に、メソッドは次のようになります。

public void doSomething(Widget widget) { ... }

より明確になっただけでなく、ウィジェットインターフェースをJavadocできるようになりました。また、ウィジェットのコード内のすべての出現箇所を簡単に検索できるようになりました。

2)マーカーインターフェイスは、Javaの交差タイプの欠如を回避する方法としても使用できます。マーカーインターフェイスを使用すると、メソッドシグネチャなど、2つの異なるタイプのものを要求できます。上記で説明したように、アプリケーションにいくつかのインターフェイスウィジェットがあるとします。ウィジェットを必要とするメソッドがあり、それを繰り返し処理する場合(不自然ですが、ここで私と一緒に動作します)、唯一の良い解決策は、両方のインターフェースを拡張するマーカーインターフェースを作成することです:

public interface IterableWidget extends Iterable<String>, Widget { }

そしてあなたのコードで:

public void doSomething(IterableWidget widget) {
    for (String s : widget) { ... }
}
1
MikeyB

インターフェイスにメソッドが含まれておらず、オブジェクトが何らかの機能を取得する場合、そのインターフェイスを実装することにより、そのようなタイプのインターフェイスはマーカーインターフェイスと呼ばれます。

0
yogesh kumar