【しばらく編集不可モードで運営します】 編集(管理者用) | 差分 | 新規作成 | 一覧 | RSS | FrontPage | 検索 | 更新履歴

Javaの疑問 - Javaをはじめて疑問におもったこと。

目次

Javaをはじめて疑問におもったこと。

recv( s, buf, len, MSG_PEEK ) 相当の機能

ソケットによる非同期通信時、相手が接続を close してないかどうか調べるのに MSG_PEEK オプション付き recv を使用していたんだけどJava でそれ相当のことをする方法がわからない。 これがない場合、receive ハンドラのなかで read したときの戻り値をみて接続がきれたかどうか調べないといけない。 write は IOException で処理できるんだけど read は例外かえしてくれない・・・

Stream? Reader? Channel??

I/O まわりのクラスがたくさんありすぎるような・・・

TODO: それぞれの違いを調べて書くこと。

Stream
入出力の基本単位が byte。基本はこれ。
Reader/Writer
入出力の基本単位が char。テキストのやり取りをしたい場合はこれ。
Channel
入出力に Buffer が使えるため、ガベージコレクションを押さえられて高速(だが煩雑)。速度が重要なときはこれ。

enum はなんでないんだろう

標準パッケージのメソッドのフラグの型が int だったりする。 enum があれば不正なフラグをわたされていないかコンパイラが検査できたとおもうんだけど・・・

フラグ用定数を使うのはあまりいい習慣じゃないってことなのかな?

それはC#では改善(?)されていますね。

Javaで真面目にenumをやるにはこんな感じのクラスを書くんだそうですが。

 class Signal {
   public static final Signal AKA = new Signal("aka");
   public static final Signal KI = new Signal("ki");
   public static final Signal AO = new Signal("ao");
   private String myname;
   private Signal(String name){ myname = name; }
 }
面倒。

シリアライズ可能な enum の実現方法

http://www.02.246.ne.jp/~torutk/javahow2/enum.html より。 デシリアライズされた後も正しいオブジェクトを参照するようにする。

 public final class Signal implements Serializable {
     private static int nextOrdinal = 0;
     private final int ordinal = nextOrdinal++;
 
     public static final Signal AKA = new Signal();
     public static final Signal KI = new Signal();
     public static final Signal AO = new Signal();
 
     private static final Signal[] PRIVATE_VALUES = {
         AKA, AO, KI
     };
 
     private Signal() {}
 
     private Object readResolve() throws ObjectStreamException {
         return PRIVATE_VALUES[ordinal];
     }
 }

A と B の相互参照維持

Java に限ったことじゃないけど。

class A と class B が相互の参照を持つ場合。関連付けするメソッドは両方に持たせる必要がある。

 class A{
   ArrayList members;
   public addMember( B aMember ){
     members.add( aMember );
   }
 }
 class B{
    ArrayList members;
    public addMember( A aMember ){
      members.add( aMember );
    }
  }

  ....
  A a =new A();
  B b =new B();
  a.addMember( b );
  b.addMember( a );

でも必ず双方向の関連付けになることがわかっているなら、メソッド一つで済ませたい。

特定のクラスにしか見せたくないメソッド

クラスAのメソッドsetValue()をクラスBには使わせたいがクラスCに使わせたい、って時はどうしたらいいんだろう。

クラスAにSelector、クラスBにはSocketChannel?があって、 SocketChannel?#register( Selector ) したいのですが、A と B 以外には Selector も SocketChannel? も見えないようにしたいんです。

 import java.nio.channels.*;
 
 class ChannelWrapper {
   ...
   private SocketChannel channel =SocketChannel.open();
   ...
   public void register( SelectorWrapper selectorWrapper ){
     channel.register( selectorWrapper.getSelector(), SelectionKey.OP_READ );
   }
   ...
 }
 
 class SelectorWrapper {
   ...
   private Selector selector =Selector.open();
   ...
   public Selector getSelector(){ // ChannelWrapper クラス以外からは使われたくない。
     return selector;
   }
   ...
 }

どこかでパッケージスコープはよくない、っての見たような気がしたんですけど、そこらへんはどうなんでしょう・・・?

  

SWT とか New I/O について

Swing を拡張したりとか既存の java.io.* を拡張する形での導入は出来なかったのでしょうか。 SWT はまだ勉強してないのでよくわからないですが、java.nio.* の設計が java.io.* に比べて良くなってるとは ちょっと思えなかったので。なんだか C でプログラム書いてたころに戻ったかのような錯覚覚えました。

select による非同期通信より Thread 使った非同期通信の方がすっきりとした設計だと思うんですけどね。 ※接続ごとにThreadを立ち上げるようにするとサーバー系で多くの接続を処理するときに重くなるので、その対策のようです。設計をよくするためではなくて、パフォーマンスをよくするためのパッケージですね。

SWT もなんだか・・・確かに早いんだけどプログラミングスタイルが gtk on C とかといっしょのような・・・