2012-03-01 10 views
0

さて、クラスを使用してJavaでネットワークパケット処理をしようとしています。私のストリームからデータを読み込むために、私はDataInputStreamを使用します。私はJavaの名前の一部でクラスを取得

packet = ClassUtils.newInstance(InPacket.class, "server.client.InPacket"+id); 

ラインを使用して新しいクラスをインスタンス化しようと

public void handle(short id) throws IOException 
{ 
    InPacket packet = null; 

    try { 
     packet = ClassUtils.newInstance(InPacket.class, "server.client.InPacket"+id); 
    }catch (Exception e){ 
     e.printStackTrace(); 
    } 

    if (packet!=null){ 
     packet.handle(this); 
    } 
    else{ 
     throw new IOException("Invalid packet"); 
    } 
} 

public void run() 
    { 
     while(client.isActive()) 
     { 
      try{ 
       handle(is.readShort()); 
      }catch (IOException e){ 
       client.stop(e); 
       break; 
      } 
     } 
    } 

は、今私はメソッドハンドルを持っている:私のサーバーのための私の読書スレッドは、次のようになります。 ClassUtilsで

が、これは、その関数である:

public static <T> T newInstance(Class<? extends T> type, String className) throws 
ClassNotFoundException, 
InstantiationException, 
IllegalAccessException { 
    Class<?> clazz = Class.forName(className); 
    Class<? extends T> targetClass = clazz.asSubclass(type); 
    T result = targetClass.newInstance(); 
    return result; 
} 

私の問題はです:私は名前の一部だけで、そのクラスを取得しようとすると、(私は一方で、「InPacket1」でそれを取得しようクラスは "InPacket1Connect"と呼ばれます)、それを見つけることができません。 Javaでこれを行うことは可能ですか?それでどうすればいいですか?そうでない場合は、ネットワークパケットを処理するためにどのような方法をお勧めしますか?

+0

このためになぜnewInstance()を使用する必要があるのか​​説明できますか? – Jivings

+0

パケットごとに別々のクラスでネットワークを扱いたいので、Packetクラスのインスタンスを作成してそのインスタンスを処理する必要があります。 – Gmfreaky

答えて

0

別のアプローチは、完全なクラス名にIDをマップするマップ(または列挙型)を用いることであろう。

コメントから項目を引っ張って、このマッピングクラスがjarとして利用できることを確認します(または、パケットハンドラの実装を含む同じjarファイル内にある可能性があります)。

+0

私はかなりのパケットを必要とするので、ClientとServerプロジェクトの両方ですべてのパケットをクラス名にマッピングするのは非効率です。 – Gmfreaky

+0

@Gmfreaky、それはどのように非効率ですか?マッピングを行う1つのクラス(列挙型を使用することができます)、さらに重要なことは明示的な制御(および保証された動作)を持つことです。 IMO私はそれがあなたが達成しようとしていることははっきりしているとは思わないが、私は個人的には、分散システムでの作業の約5年間でこの設計に遭遇したことはない。... – Nim

+0

私は不明な場合は申し訳ないが、余分なパケットを実装する。追加するパケットごとに、2つの余分なクラスを編集する必要があります(1つはサーバーとクライアント用です)。私は安定性のためにその解決策をとるつもりだと思う。ありがとうございます:-) – Gmfreaky

0

このように、多分?

packet = ClassUtils.newInstance(InPacket.class, "server.client.InPacket"+id+"Connect"); 
                      ^^^^^^^^^^ 

(私はあなたの質問を誤解している場合があります)

+0

ここでの問題は、クラスの完全な名前がわからないことです.InPacket0FunctionやInPacket1Testなどのクラスに名前を付けるだけです。数字はコード内のパケットのIDを示します。たとえば、InPacket4Fooというクラスを選択したいとします。私はIDが4であることを知っていますが、それ以降はFooと呼ばれていることはわかりません。 – Gmfreaky

0

完全なクラス名を作成できないのはなぜですか?

packet = ClassUtils.newInstance(InPacket.class, "server.client.InPacket"+id + "Connect" 

あなたは、あなたが求めているように見える機能実装でき - あなた自身のクラスローダを書き込むことによって - 「ファジー」クラス名のマッチングのようなものを。クラスローダは、一部のディレクトリでその型に部分的に一致するクラスファイルを検索できます。

私の気持ちは、これは潜在的に脆い解決することで、予想外のクラスをロードする危険性があります。 algorthimicクラス名ジェネレータを使用できない場合、Nimがマッピングテーブルを明示的に指定することを推奨します。

+0

うわー、素早く答えてくれてありがとう!私はパケットの名前を彼らの後にします。たとえば、InPacket1Connectは、クライアントからのパケットで、接続したことを示すクライアントの名前です。明示的にすべてのパケットのマップを作成すると、サーバとクライアントの両方のプロジェクトでマップに追加する必要があるため、ソフトウェアにパケットを追加するのが難しくなります。 – Gmfreaky

+0

これはトレードオフです。より多くの仕事、脆さに対する柔軟性を犠牲にして、より多くの制御。システムが成長するにつれ、私は操作上の安定性と明快さを優先します。ファイルからマッピングを取得した場合、ファイルを更新するためのクイック編集 - オーバーヘッドはあまり大きくありません。 – djna

関連する問題