ページ更新: 2005-09-03 (土) (4731日前)

関連: Java/Jakarta Commons/Lang#v64f0336

目次

[編集]

クラスインスタンス (AClass.class) から new AClass[0] を作る #

(2006-04-27のメモ、未確認)

クラスがわかっていれば:

return (AClass[]) results.toArray(new AClass[0]);

クラスがわかっていない(ただし、AClassを継承した物だと判明しているが)、clazzから作成

return (AClass[]) results.toArray((AClass[])java.lang.reflect.Array.newInstance(clazz, 0));
[編集]

メソッドから複数の値を返す (2005-09-02) #

こんなメソッドがあるとき、このメソッドから複数の値を返したくなったとき。

boolean doProcess() {
 //
    return true;
}
  • まだコンパイルしてないので、エラーがあるかも。
[編集]

1. クラスに結果を取り出すメソッドを追加する #

クラスにXxxを格納するフィールドとアクセサを追加し:

  private Xxx xxxResult;
  
  boolean doProcess() {
    xxxResult = ....
    return true;
  }
  
  Xxx getXxx() {
      return xxxResult;
  }

こういうふうに使う:

  final XxxResult result = foo.doProcess();
  if (result) {
     Xxx xxx = foo.getXxx();
  }
[編集]

2. return値にすべて格納するクラスを用意する #

こういうのを用意して:

  class XxxResult {
     Xxx value;
     boolean result;
  }

こういうメソッドを作成し:

  XxxResult doProcess();
     final XxxResult result = new XxxResult();
     result.value = 値;
     result.result = true;
     return result;
  }

こういうふうに使う:

  final XxxResult result = doProcess();
  System.out.println("result=" + result.result + " value=" + result.value);
  • メリット
    • 返す値がたくさんあっても、メソッドの引数は変化しない
  • デメリット
    • クラスが1つ余分に必要
[編集]

3. holderクラスを用意する #

  • Apache Axisがこの方法を使っていたはず。

こういうのを用意して:

  class XxxHolder {
     Xxx value;
  }

こういうメソッドを作成し:

  boolean doProcess(final class XxxHolder holder) {
     holder.value = 値;
     return true;
  }

こういうふうに使う:

  final XxxHolder holder = new XxxHolder();
  final boolean result = doProcess(holder);
  System.out.println("result=" + result + " value=" + holder.value);
  • メリット
    • 返す値がたくさんあっても、メソッドの引数は変化しない
  • デメリット
    • クラスが1つ余分に必要
[編集]

4. 配列をholderとして使う #

  • SWTの書籍で見かけたもの

こういうメソッドを作成し:

  boolean doProcess(final Xxx[] xxx);
     xxx[0] = new Xxx();
     return result;
  }

こういうふうに使う:

  final Xxx[] holder= new Xxx[1];
  final boolean result = doProcess(holder);
  System.out.println("result=" + result + " value=" + holder[0]);
  • メリット
    • クラスが増えない
  • デメリット
    • 返す値が沢山あると、その数だけ配列が必要
[編集]

HttpURLConnectionのリクエスト発行タイミング #

2005-04-28

BuferedWriterですが。。より引用:

HTTPというのはrequestを送ってresponseを得るものなので、 HttpUrlConnectionの実装は、responseを参照した時点で初めてrequestを送るように なっています。
responseに意味がなさそうなPUTメソッドやDELETEメソッドといえども、 getResponseCodeとかgetInputStreamをしないと、 requestが送られないのです。

使うときはまりそうなので、メモ。 (普段はCommons HttpClient使ってるか、自前のを使ってるけど)

[編集]

2005-06-27 #

think or die- HTML変換処理処理
http://homepage1.nifty.com/masada/cyber/javahtmlparser.htm

JavaTM Secure Socket Extension (JSSE) リファレンスガイド JavaTM 2 SDK, Standard Edition, v 1.4
http://www.techfirm.co.jp/manual/jdk14ja/guide/security/jsse/JSSERefGuide.html

以下引用:

  • デバッグメッセージをすべて表示する場合
    java -Djavax.net.debug=all MyApp
  • ハンドシェークメッセージを 16 進ダンプで表示するには、次のように入力します。コロンは省略できます。
    java -Djavax.net.debug=ssl:handshake:data MyApp
  • ハンドシェークメッセージを 16 進ダンプで表示し、さらにトラストマネージャのトレース状態を表示するには、次のように入力します。カンマは省略できます。
    java -Djavax.net.debug=SSL,handshake,data,trustmanager MyApp

SSL-TLS 接続のデバッグ
http://java.sun.com/j2se/1.5.0/ja/docs/ja/guide/security/jsse/ReadDebug.html

CodeZine:JavaのSSLSocketでSSLクライアントとSSLサーバーを実装する - 2005/07/07 (2005-07-07)
http://codezine.jp/a/article.aspx?aid=105

[編集]

Collectionの全要素に特定の処理を行う #

Commons Collections

CollectionUtils.forAllDo(collection, new Closure() {
    public void execute(Object input) {
        // inputがCollectionの各要素。
        }
    });
[編集]

コピーコンストラクタ #

nullを許可する場合。

public Hoge(Hoge rhs) {
    if (rhs != null) {
        // フィールドのコピー
    }
}

nullを許可しない場合は、rhs == null なら例外にする。 IllegalArgumentException か、org.apache.commons.lang.NullArgumentException。

[編集]

byte[]からintやdoubleをLittle-endianやBig-endianで読み出す #

SOCKET通信での受信データ処理について - Java Solution

byte[] hogehoge;
 : (hogehogeに値を入れる)
ByteBuffer buffer = ByteBuffer.wrap(hogehoge);
buffer.order(ByteOrder.BIG_ENDIAN);

int intData = buffer.getInt();
double doubleData = buffer.getDouble();
[編集]

(JDK1.4.2) URLConnectionのタイムアウト設定 (システムプロパティで設定) #

URLConnectionクラスのgetInputStream()メソッドでの時間切れ? - Java Solution

タイムアウトの設定方法が分かりました。

 クライアントに下記の設定を行うと
  設定:System.setProperty("sun.net.client.defaultReadTimeout", "3000");

 リクエストを出して3000ミリ秒の間サーバから応答がない場合
  −java.net.SocketTimeoutException: Read timed out
 をだしてくれます。 

知らなかったので、メモ。

ネットワークのプロパティ

Networking Properties

jGuru: How do I handle timeouts in my networking applications?

[編集]

Collectionを配列に変換 #

しょっちゅう手順を忘れるので、メモ。

FooType[] foos = (FooType[]) collection.toArray(new FooType[0]);

なお、頻繁に使うなら、あらかじめFooType[0]を用意しておくべき。もし、FooType自体に定数で 定義するなら、次のようにする。

public static final FooType[] EMPTY_ARRAY = new FooType[0];
   :
FooType[] foos = (FooType[]) collection.toArray(EMPTY_ARRAY);

プログラミング言語Java p.429

http://java.sun.com/j2se/1.4/ja/docs/ja/api/java/util/Collection.html#toArray(java.lang.Object[])

この操作のコストは不明(未調査)。

[編集]

指定したURLにアクセスしてそのリソースをファイルに。 #

Basic認証部分は動作未確認。

public class TryHttpUrlConnection {

    public static void main(String[] args) throws IOException {
        final int EOF = -1;
        final String targetUrl = "http://localhost";
        final String outputFile = "contents";
        final String userid = "USERID" ;
        final String password = "PASSWORD";
        final int BUFFER_SIZE = 1024;
        
        // JavaMail (javax.mail)
        String encodedString = MimeUtility.encodeText(userid + ":" + password);

        // あるいは sun.misc.BASE64Encoder
        BASE64Encoder encoder = new BASE64Encoder();
//        encodedString = encoder.encode((userid + ":" + password).getBytes());

        
        // 
        URL url = new URL(targetUrl);
        Object o = url.openConnection();
        if (!(o instanceof HttpURLConnection)) {
            return;
        }
        HttpURLConnection connection = (HttpURLConnection)o;
        connection.setRequestProperty("Authorization","Basic " + encodedString);

        //
        connection.connect();
        int responseCode = connection.getResponseCode();
        if (!(responseCode == HttpURLConnection.HTTP_OK)) {
            System.out.println("getResponseCode()=" + responseCode);
            System.out.println(
                "getResponseMessage()=" + connection.getResponseMessage());
            return;
        }

        //
        BufferedInputStream bis = new BufferedInputStream(
            connection.getInputStream());
        BufferedOutputStream os = new BufferedOutputStream(
            new FileOutputStream(new File(outputFile)));
        byte[] buffer = new byte[BUFFER_SIZE];
        int len = 0;
        while ((len = bis.read(buffer)) != EOF) {
            os.write(buffer, 0, len);    
        }
        bis.close();
        os.close();
    }
}
[編集]

ガーベッジコレクタの動作をファイルに記録する #

sun J2SE 1.4.2_03 では、非標準オプションの -Xloggc:file で記録できる。

[編集]

I/Oの入力待ちのスレッドを停止する #

Input待ちではintterrupt()では停止できないので、Streamをcloseして止める。

public void test_intterupt() {
    final class MyThread extends Thread {
        private boolean requestTerminate = false;
        public void run() {
            while (!requestTerminate) {
                try {
                    int a = System.in.read();    // I/O待ちの例
                } catch (IOException omit) {
                }
                if (requestTerminate) {
                    return;
                }
            }
        }
        public void requestTerminate() {
            requestTerminate = true;
            try {
                System.in.close();
            } catch (IOException ignore) {
            }
        }
    }

    MyThread thread = new MyThread();
    thread.start();

    while (!thread.isAlive()) 
        ;
    
    thread.requestTerminate();
    
    try {
        thread.join();
    } catch (InterruptedException ignore) {
    }
}
[編集]

ファイルからの入力を標準出力に切り替える #

// 標準入力をファイルに切り替える
InputStream in = null;
try {
	in = new FileInputStream(inFile);
} catch( FileNotFoundException e ) {
	System.err.println(e);
	System.exit(1);
}
System.setIn(in);
[編集]

複数のbyte[]を連結 #

全体の個数が分かれば単純にループで可能。

そうでなければ、ByteArrayOutputStream と DataOutputStreamを使う。

ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
    DataOutputStream os = new DataOutputStream(baos);
    try {
        os.write( byte[]を入れる );
    } finally {
        os.close();
    }
} catch (IOException e) {
    // たぶんこのExceptionは起きないと思うが。
    e.printStackTrace();
}

ただ、そもそも、連結する必要があるかどうかを考えたほうがよい。

  • ファイルに出力、あるいはネットワーク(TCP)に送信するなら、順次送信することを考える。
    • ファイルならバッファに入れるだろうし。
    • ネットワーク(TCP)なら、OS がバッファを持っているし。
  • 複数のbyte[]をまとめて扱いたいだけなら、複数の byte[] をListで管理してもよいと思う。
    • Scatter/Gather I/O みたいに(デバイスやDMAが持つ機能)
[編集]

primitiveの配列からWrapper型の配列を作る #

ここらへん、Java2 SE 1.5やC#なら楽だろうな、たぶん。

  • Jakarta Commons のLangかPrimitivesでできるかも。
    • LangのArrayUtilsならこうなる。
      byte[] prim = { 1, 2, 3, };
      Byte[] wrap = org.apache.commons.lang.ArrayUtils.toObject(prim);
    • Primitives は primitive <-> Collection なので、該当するメソッドはない。

Jakarta Commons Lang

Jakarta Commons Primitives

[編集]

nioを用いた高速ファイルコピー(動作未確認) #

J2SE 1.4での方法。

http://people.westminstercollege.edu/faculty/ggagne/spring2003/352/handouts/hw1/FastCopy.java

[編集]

現在のクラス、メソッド、ファイル、行番号の取得 #

J2SE 1.4での方法。このメソッドを呼び出した個所のクラス名、メソッド名、ファイル名、行番号を取得できる。(でもLog4J使ったほうが便利だと思うが)

public void sample() {
    StackTraceElement a = (new Exception().getStackTrace())[1];
    String str = a.getClassName() + "#"	+ a.getMethodName() 
                 + " (" + a.getFileName() + ":" + a.getLineNumber() + ")";
    System.out.println(str);
}

次のようにすると、Eclipse 3.1.1で該当ソースコードにジャンプできる (log4jの出力と同じ)

public void sample() {
    StackTraceElement a = (new Exception().getStackTrace())[1];
    String str = a.getClassName() + "." + a.getMethodName() 
                 + "(" + a.getFileName() + ":" + a.getLineNumber() + ")";
    System.out.println(str);
}
[編集]

文字出力時(ファイル、画面)の改行コードの扱い #

うまくいくかどうか確認していない。 (Windows=CRLFでコンパイルして、Linux=LFで実行とか)

final String EOLN = System.getProperty("line.separator");
System.out.println(
    "first line " + EOLN +
    "second line" + EOLN +
    "third line" +EOLN
);
[編集]

システムプロパティの確認 #

/**
 * システムプロパティとその値を一覧表示する。
 */
class ShowSystemProperties {
        public static void main(String[] args) {
                System.getProperties().list(System.out);
        }
}

Cygwin+JEでの起動設定

java -cp `cygpath -w $HOME/bin` ShowSystemProperties
[編集]

16進ダンプ #

[編集]

org.apache.commons.io.HexDump #

Java/Jakarta Commons/IO

[編集]

sun.misc.HexDumpEncoder #

sun.misc.HexDumpEncoderを使う。

OutputStreamへ出力

import sun.misc.HexDumpEncoder;
   :(略)
new HexDumpEncoder().encodeBuffer(a, os);

文字列に出力 (aはbyte[])

new HexDumpEncoder().encodeBuffer(a)

出力例:

0000: 00 01 02 03 04 05 06 07   08 09 0A 0B 0C 0D 0E 0F  ................
0010: 10 11 12 13 14 15 16 17   18 19 1A 1B 1C 1D 1E 1F  ................
0020: 20 21 22 23 24 25 26 27   28 29 2A 2B 2C 2D 2E 2F   !"#$%&'()*+,-./
0030: 30 31 32 33 34 35 36 37   38 39 3A 3B 3C 3D 3E 3F  0123456789:;<=>?

出力例。64KB (0xFFFF)を超えると、アドレス表記は0000に戻る。:

:(略)
FFE0: E0 E1 E2 E3 E4 E5 E6 E7   E8 E9 EA EB EC ED EE EF  ................
FFF0: F0 F1 F2 F3 F4 F5 F6 F7   F8 F9 FA FB FC FD FE FF  ................
0000: 00 01 02 03 04 05 06 07   08 09 0A 0B 0C 0D 0E 0F  ................
0010: 10 11 12 13 14 15 16 17   18 19 1A 1B 1C 1D 1E 1F  ................
:(略)
[編集]

インスタンスのダンプ #

Apache Commons LANG 2.0 に含まれるorg.apache.commons.lang.builder.ReflectionToStringBuilderを使う。 (LANG 1.0には見当たらないようだ) perlのData::Dumperみたいなもの。

import org.apache.commons.lang.builder.ReflectionToStringBuilder;

public String toString() {
	return ReflectionToStringBuilder.toString(this);
}
[編集]

実行時カレントディレクトリ取得 #

new File(".");

[編集]

タイムアウト付き wait (2004-08-20) #

  • wait(timeout) には、waitの終了原因のうち、 notify/notifyAll と timeout を区別する機能がない。

(デザインパターン入門 マルチスレッド編 p.141)

実装例

1. Timeout を示す例外クラスを、InterruptedException から作る。

public class TimeoutException extends InterruptedException {
  public TimeoutException(String msg) {
    super(msg);
  }
}

2. wait()のループ内で開始時刻・現在時刻を記録し、それが過ぎていた場合は notifyではなくtimeoutとみなすようにする。