2009-07-13 8 views
17

Javaでは、型が複数のインタフェースであるフィールド/変数を宣言できますか?たとえば、SerializableであるMapを宣言する必要があります。変数がシリアライズ可能なマップを参照していることを確認したい。 MapインターフェイスはSerializableを拡張しませんが、Mapの実装のほとんどはSerializableです。Java、複数のインタフェースで変数を宣言しますか?

私は答えがノーだと確信しています。

フォローアップ:私は MapSerializableの両方を拡張する新しいインタフェースを作成するための十分に認識です。既存の実装( HashMapなど)が新しいインタフェースを実装しないため、これは機能しません。

答えて

7

必要はありませんそのようなフィールド/変数を宣言します。特に、それは実行時にしかテストできず、コンパイル時にはできません。渡されたMapがSerializableを実装していない場合は、セッターを作成し、エラーを報告します。

独自のインターフェイスを作成することを推奨する回答は、マップやシリアライズ可能なものではなく、特別なインターフェイスではないものを送信することを積極的に禁止するため、あまり実用的ではありません。

+0

'Map'が' Serializable'を実装していても、必ずしもそれがシリアル化可能であるとは限りません。しかし、はい、Javaの直列性はJavaの実行時の問題です。 –

+0

残念なことにJavaの場合、これは正しい答えであり、トップになる価値があります。 – hythlodayr

+0

あなたは私の答えの重要な部分を見逃しました...オブジェクトがSerializableのインスタンスであるかどうかをMapとTHENチェックに受け入れます。あなたはもちろんそれを逆にしても構いませんが、ユーザーが実際にどのような種類のコレクションを必要としているかわからないインターフェースを得ることができます。 – Fredrik

6
public interface MyMap extends Map, Serializable { 
} 

MapSerializableの和集合である新しいインターフェイスを定義します。

あなたは明らかに、このの適切な実装(例えばMyMapImpl)を提供するために持っていて、その後、(要件に応じて、またはMap、またはSerializable)変数の型MyMapの参照を提供することができます。

説明を明確にするために、動作(例:シリアライズ可能なマップ)を更新することはできません。 にはがあり、インターフェースと適切な実装があります。

+2

私は、変数に既存のオブジェクトを割り当てたいとしていました。 HashMapオブジェクト – skaffman

+2

私は彼が可変シグネチャとしてシリアライズ可能なマップを持っていたいと思うが、HashMap、TreeMapなどを使用できるように思っていると思います。MyMap map = new HashMap();私は思っています。 – JeeBee

3

あなたはジェネリックでそれを行うことができますが、

public interface SerializableMap<K, V> extends Map<K, V>, Serializable { 

} 
11

をするインターフェイスを拡張し、独自のインタフェースを行うことによって、これを達成することができますが、それはかなりありません。

class MyClass<T,K,V extends Serializable & Map<K,V>> { 

    T myVar; 

} 
+1

おそらくそれにK&Vを追加したいと思っています。 –

+0

あなたはまた、通常、それをどのように使用するかにはかなりの醜さが必要です。 –

+0

はい、それは大きなものを吸うだろう、と私はむしろ私が上に書いたものを使用するよりも自分の爪を引っ張るだろうが、他の男はここでお金を払っている。 – skaffman

0

既存のMapの実装を引き続き使用したい場合は、実際には実行できません。

代替は、ヘルパークラスを作成し、この1のようにメソッドを追加することです:私はブライアンの答えを投票したが、思った少し高いレベルを追加したい

public static Serializable serializableFromMap(Map<?, ?> map) { 
    if (map instanceof Serializable) { 
     return (Serializable)map; 
    } 
    throw new IllegalArgumentException("map wasn't serializable"); 
} 
2

..

SDKを見れば、実際のコレクションオブジェクトをまれに渡すことはほとんどありません。

その理由はあまり良い考えではないということです。コレクションは非常に保護されていません。

ほとんどの場合、コピーを渡してコピーを渡してコレクションに変更を加えても、それに依存している他のものの環境が変更されないようにする必要があります。また、スレッド化は悪夢になる - 同期化されたコレクションでさえも!

私は2つの解決法を見てきました.1つは常に配列を抽出して渡すことです。これは、SDKがそれを行う方法です。

もう1つは、親クラスのコレクションを常にラップすることです(拡張しないでカプセル化することを意味します)。私はこの習慣に慣れてきましたが、それは非常に価値があります。とにかくすべてのコレクションメソッドを複製しないので、実際には何の費用もかかりません(実際には複製することはめったにありません)。実際にあなたがやっているのは、コード全体に分散している他のクラスの「ユーティリティ」機能を、まず最初にあったはずのラッパークラスに移動することです。

"method(collection、...)"と一致するシグネチャを持つメソッドは、そのコレクションのメンバーメソッドである必要があります。コレクションを反復するループも同様です。

私はちょうどこれを捨てなければなりません。なぜなら、それは私がしばらくの間得られなかったものだからです(誰もコンセプトを擁護しなかったからです)。いつもそれはいくつかの欠点があるように見えるが、これをしばらくの間行って、それが解決した問題を見て、それを排除すると、私は自分自身の可能性のある欠点を想像することもできない。

+0

私はこれに同意します。現在のコードに固有の意味的に意味のあるインターフェースではなく、恣意的な既存の 'Map'を受け入れることが望ましい理由は私には分かりません。 –

6

これは、いくつかのジェネリック医薬品のトリックを使ってこれを実行することが可能です:

public <T extends Map<?,?> & Serializable> void setMap(T map) 

上記のコードは両方のインタフェースを実装してマップを渡すことを強制するためにジェネリックを使用しています。ただし、実際にマップを渡すときには、おそらくシリアライズ可能またはシリアライズ可能なマップタイプのいずれかにマークする必要があることに注意してください。また、読むのがかなり難しいです。私はマップがシリアル化可能であり、それをテストする必要があることを文書化します。

0

いいえ、あなたはかなりキャストする必要があります。

関連する問題