My Photo

« January 2012 | Main | March 2012 »

February 29, 2012

アビセアブンカールSeps戦、敗北 #FF11

トリガがあったのでアビセア-ブンカールのプークNM Seps にシ/踊で挑んでみた。
最初は結構いい感じ避けられる削れるので行けるかなと思ったが、ダメージで起きない睡眠になる特殊技を続けて食らって死亡。
同じように「ダメージで起きない睡眠」を使うミザレオのマントラップNMと較べると、手数・命中率はSepsの方が弱いが、通常攻撃に毒がついてくるのと睡眠と同時にチョークになるのでスリップダメージが結構きつい。
次回は
・気休めかもしれないがレジストスリープのついた食事を使う。スキッドスシとか。
・同じく気休めかもしれないが胡蝶のイヤリングを装備。
・毒消しを大量に持っていく。
という対策でやってみようと思う。
これでだめならソロで倒すのはあきらめよう。

February 28, 2012

サカダイ順位予想で新潟16位 #albirex #jleague

今週のサカダイに順位予想が載っていた。予想屋は解説者、ライター、編集部の計32人。
予想を集計した総合ランクで新潟は降格圏の16位。まあ予想通だけどね。くやしー!!
#17位は鳥栖、18位は札幌。

解説者で降格と予想したのは前園だけ(17位)。まあギリギリセーフの15位予想も2人いるが、評価は意外と悪くない。
福西にいたっては1桁順位の9位と予想している。「B・ロペス次第」って言っているからBLを評価してこの順位みたい。
ライター、編集部は大体新潟を低く評価しているようで、編集長に至っては鳥栖より下の17位だった。

見返してやれ!!

しかし、開幕が近いというに新潟市にはまだ雪が残っている。
ビッグスワンの芝は大丈夫だろうか。

可変長パラメータ

可変長パラメータは以下のように書く。

type ... variableName

これは以下の宣言と同じ扱いである。

type[] variableName

また、可変長パラメータの部分に何も書かずにメソッドを呼び出すと、可変長パラメータには長さ0の配列が与えられる。

以下は可変長パラメータを使用し引数の合計値を返すメソッドである。

int sum(int ... numbers) {
  int total = 0;
  for (int i: numbers) {
    total += i;
  }
  return total;
}

printf()、format()

PrintStream#printf() と String#format() は可変長引数を引数を使用して書式を指定して文字列を出力・生成するメソッドである。C言語の関数printf()、sprintf() にあたる。

class PrintfTest {
  public static void main(String[] args) {
    int x = 10;
    int y = 20;
    int sum = x + y;
    System.out.printf("%d + %d = %d n", x, y, sum);
  }
}

参考記事:Java Press Vol.38 続報 J2SE 5.0 実践チュートリアル

staticインポート

staticインポートを用いると、staticなメンバをクラス名を介さずに直接記述できるようになる。
文法は以下。後者はワイルドカードを用いてTypeNameのstaticなメンバすべてを対象としてstaticインポートする。

import static TypeName.Idenrifier;
import static TypeName.*;

enum型もstaticインポートを用いて定数を直接書くようにできる。ただし、そのenum型がデフォルトパッケージではないパッケージに属している必要がある。

以下のコードは java.lang.Math のstaticなメンバーを直接記述できるようにstatciインポートをしている。
1.4までは Math.E や Math.abs() と記述しなければならなかったが、下記のコードではE や abs() とクラス名なしで記述している。

import static java.lang.Math.*;

public class StaticImportTest {
  public static void main(String args[]) {
    System.out.println(E);
    System.out.println(abs(-10));
  }
}

参考記事:Java Press Vol.38 続報 J2SE 5.0 実践チュートリアル

February 27, 2012

アビセア-ウルラガンのクエをコンプリート #FF11

先日、「モグハウスがなくても負けないクポ」をクリアしたのでウルガランのクエ全部終わったと思ったが、拠点のNPCに話しかけたら1個残っていた。
「偵察の報酬 」をまだやってなかった。動き回っているNPC3人に話しかける面倒くさいクエw
ジュノに戻って上層の日替わり酒場で豆のスープを買い、再度ウルガランに入ってクリアした。
これでアビセア-ウルラガンのクエをコンプリート^^/

覇者エリアでまだクリアしてないクエあったかなー。

enum型

J2SE 1.4まではC言語のenumに当たるものがなかったので、定数を列挙する下記のようなコードが良く書かれていた。

public class PlayingCard {
  public static final int CLUBS = 0;
  public static final int DIAMONDS = 1;
  public static final int HEARTS = 2;
  public static final int SPADES = 3;
}

上記のPlayCardクラスで定義された定数を引数に取ることを想定した下記メソッドを考える。

String suitColor(int suit) {
  switch (suit) {
  case PlayingCard.CLUBS:
  case PlayingCard.SPADES:
    return "black";
  case PlayingCard.DIAMONDS:
  case PlayingCard.HEARTS:
    return "red";
  default:
      throw new IllegalArgumentException();
  }
}

suitColor() はPlayCardクラスの定数以外の任意のint型の値を引数に取れる。
よって、仮に

suitColor(5);

とコーディングしても、コンパイラはエラーを検出できずに実行時に例外が発生する。

Java 5.0以降ではenum型が実装されたので PlayCard クラスの代わりenum型を使って以下のように列挙型Suitを簡潔に書ける。

public enum Suit {
  CLUBS, DIAMONDS, HEARTS, SPADES
}

この Suit を使うように suitColor() を書き直すと下記のようになる。
これならば引数には列挙Suitしか取らなくなるので、不正な引数を与えた場合にコンパイルエラーとなる。

String suitColor(Suit suit) {
  switch (suit) {
  case CLUBS:
  case SPADES:
    return "black";
  case DIAMONDS:
  case HEARTS:
    return "red";
  default:
    throw new AssertionError("Unknown " + suit);
  }
}

enum型の実体

enum はコンパイルすると java.lang.Enum クラスを継承したクラスに変換される。Java VM からすれば enum は単なるクラスである。
Enum定数宣言(列挙子の並び)をセミコロンで終わらせた後に、通常のクラスと同じように変数やメソッドを記述できる。

swtich文での使用

enum型の定数をswitch文に使用できる。先に出てきた suitColor(Suit) メソッドのswitch文でenum型Suitを使っている。caseラベルでEnum型名を付けずにEnum定数名を単独で使っている。
Enum定数を直接書けるのは、そのEnum定数を定義しているEnum型の中とswitch文のcaseラベルだけである。

EnumMap、EnumSet

enum型をキーとするMapとしてEnumMap、enum型用のSetとしてEnumMapがある。
下記のコードは上で定義した列挙型 Day のすべての要素すべてをイテレーションするfor文と、特定の範囲をいてレーションするfor文である
すべての要素はの取得には Enum#values()を、特定の範囲の取得にはEnumSetのstaticメソッド range() を使用している。

public static void iterationTest() {
  // すべての定数を表示
  for (Day d: Day.values()) {
    System.out.println(d.ordinal() + ":" + d);
  }

  System.out.println();

  // 指定した範囲の定数を表示
  for (Day d: EnumSet.range(Day.TUESDAY, Day.THURSDAY)) {
    System.out.println(d.ordinal() + ":" + d);
  }
}
出力
0:SunDAY
1:MONDAY
2:TUESDAY
3:WEDNESDAY
4:THURSDAY
5:FRIDAY
6:SATURDAY

2:TUESDAY
3:WEDNESDAY
4:THURSDAY

参考記事:Java Press Vol.38 続報 J2SE 5.0 実践チュートリアル
参考ページ:Java列挙型メモ(Hishidama's Java enum Memo)

拡張for文(for-each)

配列やコレクションの要素すべてを参照する(変更はしない)処理を書く場合、拡張for文で簡単に書くことができる。 要素の文字列長の合計を返すメソッドは、拡張for文を使うと以下のようになる。

コレクションの場合
int totalLengthOfStrings(Collection coll) {
  int result = 0;

  for (String s : coll) {
    result += s.length();
  }
}
配列の場合
int totalLengthOfStrings(String[] strings) {
  int result = 0;

  for (String s : strings) {
    result += s.length();
  }
}

拡張for文を使えるのは配列とIterableインタフェースを実装するクラス。
CollectionインタフェースはIterableインタフェースを拡張している。

参考記事:Java Press Vol.38 続報 J2SE 5.0 実践チュートリアル

February 26, 2012

ボクシング/アンボクシング

基本データがからそのラッパークラスへの自動変換がボクシング(boxing)で、ラッパークラスから基本データがへの自動変換がアンボクシング(unboxing)。
以下のコードではボクシング/アンボクシングを使ってコードを簡素化している。push()でListに追加するところでボクシング変換、pop()の値を返すところでアンボクシング変換が行われている。

import java.util.*;

class IntStack { // 5.0 version
  private List<Integer> elements;

  public IntStack(int initialCapacity) {
    elements = new ArrayList<Integer>(initialCapacity);
  }

  public void push(int e) {
    elements.add(e);
  }

  public int pop() {
    if (elements.size() == 0) {
      throw new EmptyStackException();
    }
    return elements.remove(elements.size() - 1);
  }
}

以下のような場面でボクシング/アンボクシング変換が行われる。

代入

Integer x = 1; // ボクシング
int y = x; // アンボクシング

基本データ型とその基本データ型に対応するラッパークラスとの間の変換が行われるのであって、以下のようにshortとIntegerの間では変換されない。変換するには明示的にキャストを入れる必要がある。

Short s = 1;
int y = s;  // コンパイルエラー

メソッド呼び出し

class UnboxingParameter {
  public static void main(String[] args) {
    showInt(new Integer(10));
    showInt(new Integer(20));
  }

  public static void showInt(int i) {
    System.out.println("int value = " + i);
  }
}

演算

ラッパークラスに対して演算子を直接適用できる。ただし、演算のたびにラッパークラスのインスタンスが作られるので多用すべきではない。

Integer i = 1;
i++;
i = i + i;

フロー制御文の条件

if や for などのフロー制御文の条件にBoolean型を指定できる。

switch

switchの条件にInteger、Short、Byte、Characterを使用できる。

Integer i = ...;
...
switch (i) {
  case 0:
    ...
  case 1:
    ...

}


参考記事:Java Press Vol.38 続報 J2SE 5.0 実践チュートリアル

LV99でもRajaは強かった #FF11

昨日、LSメンバーがグロウベルグのRajaをやっているのを手伝った。
が、オタオタするだけでほぼ手伝いにならずorz

12人くらいいたが、それでもRajaは強かった。
負けはしなかったが戦闘不能者は出た。

死闘エリアのHNMはLV99でも全然油断できいない強さだ。

アノテーション その2

標準メタアノテーション

標準メタアノテーションには以下の4つがある。

  • Target
  • Retension
  • Documented
  • Ingerited

Targetアノテーション
アノテーションがどの種類の要素に適用できるかを示す。
メンバーのvalue() の戻り値は java.lang.annotation.ElementType 型の配列で、java.lang.annotation.ElementType の定数は以下になる。

説明
TYPE クラス・インタフェース・enum・アノテーションの宣言
FIELD フィールドの宣言(enum定数を含む)
METHOD メソッドの宣言
PARAMETER メソッドのパラメータの宣言
CONSTRUCTOR コンストラクタの宣言
LOCAL_VALIABLE ローカル変数の宣言
ANNOTATION_TYPE アノテーション型の宣言
PACKAGE パッケージの宣言

下記のコード例では型にしか使用できないアノテーションを定義している。
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

@Target(ElementType.TYPE)
public @interface Copyright {
  String value();
}

Retensionアノテーション
記述されたアノテーション情報がどこまで反映されるかを示す。
メンバーのvalue() の戻り値は java.lang.annotation.RetentionPolicy 型で、以下の値である。

説明
SOURCE ソース上だけに記録される。
CLASS クラスファイルにもアノテーションの情報が記録される。ただしそのクラスをJVMにロードしても、JVMにはアノテーションの情報はロードされない。Retensionアノテーションを指定しなかった場合のデフォルト。
RUNTIME クラスファイルに情報が記録され、さらにクラス使用時にはJVMにも情報がロードされる。リフレクションAPIを利用してアノテーション情報を読み取るためにはこの種別を指定しなければならない。

Documentedアノテーション
アノテーション情報がjavadocコマンドなどで作成されたドキュメントに反映されなければならないことを示す。
このアノテーションはマーカーアノテーションである。

Inheritedアノテーション
クラス、または非staticなメソッドに付けられるアノテーションで、アノテーションがサブクラスに自動的に継承されることを示す。 このアノテーションはマーカーアノテーションである。

参考記事:Java Press Vol.37 J2SE 5.0 実践チュートリアル
参考ページ:7. アノテーション (3) | TECHSCORE(テックスコア)

February 25, 2012

アノテーション その1

アノテーションはクラスやメソッド、パッケージにメタデータを付加する注釈。
アノテーション自体はプログラムの処理に影響を与えないが、ツールが読み取って利用する。ソースコード中にアノテーションを書いても、そのアノテーションを利用するツールを利用しなければ何も意味がない。

標準アノテーション

java.langパッケージに定義されているアノテーション。

@Override
メソッドがスーパークラスのメソッドをオーバーライドしていることを示す。
オーバーライドされていないメソッドにこのアノテーションを付けるとコンパイルエラーとなる。
@Deprecated
メソッドの使用が推奨されないことを示す。
@SuppressWarnings
コンパイラが出す警告メッセージを抑制する。
"@SuppressWarnings" の後ろに括弧で囲って抑制する警告を書く。波括弧で複数書くこともできる。抑制できる警告はコンパイラの実装に依存する。
下記のコードでは1行目のSuppressWarningsアノテーションは複数の警告を指定している。抑止している警告はシリアライズに関する警告とfinally節に関する警告。
指定できる警告については参考ページに説明がある(公式な情報ではないと思うが)。
@SuppressWarnings({"serial", "finally"})
public class GenericsSample implements Serializable {

  public <U> List<U> foo(U element) {
    @SuppressWarnings("unused")
    List<U> unUsedList;

    @SuppressWarnings("unchecked")
    List<U> list = (List<U>)new ArrayList<Object>();
    try {
      list.add(element);
    } finally {
      return list;
    }
  }
}

アノテーションの定義

アノテーションの定義はまずあればメタアノテーション(アノテーションに対するアノテーション)、次に "@interface" 、その後ろにアノテーションの名前、最後に中括弧で囲って本体(メンバなど)を書く。
アノテーションはクラスやインタフェースと同じ型の1つであり、publicなアノテーション型は同名のソースファイルに記述する必要がある。
また、以下の制限がある。

  • アノテーション型は、暗黙にjava.lang.annotation.Annotationインタフェースを拡張しているので extends を書くことはできない。
  • メソッドは、パラメータを持つことはできない。
  • アノテーション型はジェネリックスを使用してパラメータ化することはできない。
  • 型パラメータを持つメソッドを定義することはできない。
  • メソッドには、throws節は書けない。
  • メソッドの戻り値型は基本データ型(char,byte,short,int,long,float,double),String,Class,enum型,アノテーション型か、これらの型の配列でなければならない。

マーカーアノテーション型
メンバのないアノテーション。OverrideアノテーションとDeprecatedアノテーションもこれにあたる。
下記はマーカーアノテーション型の例として、将来変更になるかもしれないという意味のマーカーアノテーションの定義。

/**
* Annotation with this type indicates that the specification of the
* annotated API element is preliminary and subject to change
*/
public @interface Preliminary { }
使用する場合は "@Preliminary" か "@Preliminary()" となる。

単一メンバアノテーション
メンバ(メソッド)を1つだけ持つアノテーション。SuppressWarningsアノテーションがこれに当たる。
下記は単一メンバアノテーション型の定義の例

/**
 * Associates a copyright notice with the annotated API element
 */
public @interface Copyright {
  String value();
}
メンバの名前が value の場合、アノテーションを使うときにメンバの名前を省略して値だけ書くことで済ますことができる。
@<アノテーション名>(<値>)
省略しないで書くことも当然できる。省略しない完全な文法で書くとこうなる
@<アノテーション名>(<メンバ名>=<値>)

複数のメンバを持つアノテーション
メンバが複数ある場合は、使用時にメンバーを省略することはできず、下記のように <メンバ名>=<値> をカンマで区切って書く。

@RequestForEnhancement(
  id = 286874,
  synopsis = "Privde time-travel functionality",
  engineer = "Mr. Peabody",
  date = "4/1/2004"
)

メンバのデフォルト値
下記のようにdefaultという予約語でメンバのデフォルト値を設定できる。

// Annotation type declaration with defaults on some members
public @interface RequestForEnhancement {
  int id(); // No default - must be specified in each annotation
  String synopsis(); // No default - must be specified in each annotation
  String engineer() default "[unassigned]";
  String date() default "[unimplemented]";
}

参考ページ:
7. アノテーション | TECHSCORE(テックスコア)
Java警告抑止方法メモ(Hishidama's Java SuppressWarnings Memo)
Java Annotations: An Introduction - Developer.com

参考記事:Java Press Vol.37 J2SE 5.0 実践チュートリアル

February 24, 2012

詐欺か、運用の失敗か #kabu

AIJ投資顧問:企業年金2千億円消失…123社分の大半 - 毎日jp(毎日新聞)

と、こんなニュースがあったけど、今日の東証にはほとんど影響なかった。
金余りの海外勢が買い続け、国内の投資かも「下がったら買う」というスタンスで、9600円台を回復。強い!!

こういう投資詐欺って被害者がかわいそうとか、正直言って思わない。
テレ東のニュースでどこかの年金基金の人が匿名でインタビューに答えていて、
「年200%とか240%とかって。ありえないですよね?w」
と語っていた。
「年200%」とかいう説明を真に受けて運用を任せたのだとしたら、この前の「偽物語」のガハラさんじゃないけどだまされたほうが悪い。
まあ、まだ最初からだますつもりだったのか、まじめに運用してたけど失敗しただけなのかはまだわからんが。でも2100億円ほとんどなくなってるって、まともに運用していたとは考えづらいな。

安川電機とかそれなりに名の知れた企業の年金基金も金を出していたようだ。そういうところには200%なんて吹かしたりせずに、それなりの説明してたんかなー?まあ安川電機の場合は運用総額の2%というから致命的な問題にはならないし。
#とはいえ大事な積立金が消えたのだから当事者の人にしたら腹立つだろう。

来週の週刊誌、経済誌の続報が楽しみ。
#不謹慎?

ジェネリクス(Generics)その3

型の互換性

List<Integer> list = new ArrayList<Integer>();

これはOK。List<Integer> と ArrayList<Integer>の関係は、1.4まで List と ArrayList の関係と同じ。

ArryaList<Integer> list = new ArrayList<Object>();  // コンパイルエラー

これはNG。ArryaList<Integer> と ArrayList<Object> の間にはスーパークラス/サブクラスの関係はない。

もし後者の代入が許されるとすると、
・宣言から、変数listの要素はInteger型しか許されない。
・変数listが実際に参照しているArrayList<Object>から、listにはObject型、つまりDobule型でもString型でも何でも要素として許される。
という矛盾が起こる。

ワイルドカード

要素の型が1つに決まっていないListを使いたい場合、型パラメータに?を与えて List<?> のように記述する。この?をワイルドカードと呼ぶ。

List<?> list;  // 要素の型は限定されない
Map<String, ?> map;  // 値の型は限定されない。

List<?>型の変数には List<Object> も List<Integer> も List<String> も、どの型の要素を持つListでも代入できる。

List<?> list;
list = new ArrayList<Object>();
list = new ArrayList<String>();
list = new ArrayList<Integer>();

ワイルドカードも extends と super で制限することができる。
extendsであれば指定したクラスとその子孫のクラス、superだと指定したクラスとその先祖のクラスに制限できる。
下記のコードにあるように、<C2>と<? extends C2> には違いがある。<C2> とした場合、型パラメータにはC2しか入れられない。C2のサブクラスを入れようとしてもコンパイルエラーとなる。

import java.util.ArrayList;
import java.util.List;

class C1 {};
class C2 extends C1 {};
class C3 extends C2 {};

public class Foo {
  public void method() {
    List<C2> list1;
    list1 = new ArrayList<Object>();  // コンパイルエラー
    list1 = new ArrayList<C1>();  // コンパイルエラー
    list1 = new ArrayList<C2>();
    list1 = new ArrayList<C3>();  // コンパイルエラー
    
    List<? extends C2> list2;
    list2 = new ArrayList<Object>();  // コンパイルエラー
    list2 = new ArrayList<C1>();  // コンパイルエラー
    list2 = new ArrayList<C2>();
    list2 = new ArrayList<C3>();
    
    List<? super C2> list3;
    list3 = new ArrayList<Object>();
    list3 = new ArrayList<C1>();
    list3 = new ArrayList<C2>();
    list3 = new ArrayList<C3>();  // コンパイルエラー
  }
}

参考記事:Java Press Vol.37 J2SE 5.0 実践チュートリアル

タスクが実行時のエラー

関連する以前の記事:batファイルを常に管理者権限で実行する

自分で作ったタスクを実行しようとしたら、エラーになって以下のようなメッセージが出た。

「タスク スケジューラ サービスはタスクを実行しようとしましたが、タスクの定義にある制約の1つのためタスクを実行できませんでした。(0x80041324)」

ググって調べたら、情報があった。

【DOS】 AT コマンドエラー 0x80041324|だいなりのブログ

これは、タスクのプロパティの条件タブで
「コンピュータをAC電源で使用している場合にのみタスクを開始する。」
にチェックが入っていたからだった。
確かにエラーが起きたときはACアダプタを付けずにバッテリーで使用していた。
チェックを外すとバッテリーで使用しているときもタスクを実行できた。

February 23, 2012

ジェネリクス(Generics)その2

総称メソッド(generic method)

メソッドだけにジェネリクスを適用する場合、戻り値の前に型変数を書く。
型変数のスコープはそのメソッド内になる。
下記のコードでは swap() が総称メソッドになる。クラスで宣言した型変数Tのスコープはクラス内、総称メソッド swap() で宣言した型変数Uのスコープはメソッド内である。

public class Foo<T> {
  private T t;

  public T getT() { return t; }

  public void setT(T t) { this.t = t; }

  public static <U> void swap(U[] a, int i, int j) {
    U temp = a[i];
    a[i] = a[j];
    a[j] = temp;
  }

  public static void main(String args[]) {
    String[] strArray = new String[] { "a", "b", "c", "d", "e" };

    Foo.<String>swap(strArray, 1, 3);  // 完全な文法による呼び出し

    Foo.swap(strArray, 0, 2);  // 型推論により省略した呼び出し

    for (String str : strArray) {
      System.out.println(str);
    }
  }
}

総称メソッドの呼び出しは17行目のようにメソッドの前に型を書くのが完全な文法の書き方だが、19行目のように省略することができる。これは型推論という機能によるものである。

有界の型パラメータ(bounded type parameter)

型パラメータを特定のクラスを継承している、あるいは特定のインタフェースを実装しているものに制限することができる。以下のように記述する。
#bounded=有界の:数学の用語らしい。

<T extends Foo & Bar & Baz>

extendsの後にクラスは最大1個で、必ず最初でなければならない。インタフェースは&を使って複数書くことができる。
上の例では、Fooがクラスならば型パラメータTはFooを継承し、BarとBazを実装するように制限される。またFooがインタフェースならば型パラメータTはFoo、Bar、Bazを実装するように制限される。すべてインタフェースの場合でも implements ではなく extends を使用する。

extendsを使わずに "<T>" と宣言された型パラメータは、"<T extends Object>" と同じである。
"<T>" と宣言された場合、型変数TはバイトコードではObject型たが、 "<T extends Foo>" という宣言ならば型変数TはFoo型となる。

参考記事:Java Press Vol.37 J2SE 5.0 実践チュートリアル

February 22, 2012

揺篭のアートマをゲット #FF11

昨日、ミザレオのカニNM「Karkatakam」を倒して揺篭のアートマを手に入れた。
やっとのことで赤弱点付けた。大変だった^^;
20回以上倒したと思う。くじけそうになったこともあったが、金策にはなったので続けられた。エバリエントケープという装備品をたまに落として、これが結構いい値段で売れたのだ。

ミザレオはあとアートマ1個、ジェイド1個でコンプリートだ。
どいつだ?どのNMだ?

February 21, 2012

ジェネリクス(Generics)その1

業務でJavaを使っていたときは1.4を使っていたので5.0で追加された以下の機能はよくわからない。

  • ジェネリクス
  • アノテーション
  • 拡張for文
  • ボクシング/アンボクシング
  • enum
  • staticインポート
  • 可変長パラメータ

これらの機能について、昔のJava Pressの記事(Vol.37,38 J2SE 5.0 実践チュートリアル)の記事の内容を自分なりにまとめてみた。
#genericsは「ジェネリクス」と読みたいけど、genericは「ジェネリック」と読みたい。「ジェネリック医薬品」とか言うし。統一感ないな^^;

総称型(generic type)

「総称型=パラメータされた型(parameterized type)」なんだろうか?同じと言っている人もいれば、総称型に型引数を与えたものをがパラメータ化された型だという人もいる。
Oracleのサイトのチュートリアルには

An invocation of a generic type is generally known as a parameterized type. ジェネリック型の呼び出しは、通常、パラメータ化された型として知られています。
とあるから、そういうことなんだろうか。まあ、あまり深く考えないことにしよう^^;

総称型の宣言は、クラス名の後に1個以上の型パラメータ(type parameter)を"<>"で囲んだ型パラメータリストを書く。
型パラメータリストに書いた型変数(type variable)をそのクラス内・インタフェース内で使用できる。
#parameter=引数、パラメータ

class クラス名<型変数[,型変数,...]> { ... }
interface インタフェース名<型変数1[,型変数2,...]> { ... }

型変数は一般的な以下のようにアルファベット1文字の名前が使われる。

名前意味
E Element。コレクションの要素。
K Key。Mapのキー。
V Value。Mapの値。
T,S,U,V Type。一般的な型。
複数ある場合にはTの近傍の文字を使う。

イレイジャ

総称型をコンパイルしてできたバイトコードにはジェネリクスに関する情報は含まれていない。
これはコンパイラが型変数をObject型として適切にキャストを行うバイトコードを生成するため。
このようなコンパイラの処理をイレイジャ(erasure)と呼ぶ。

ジェネリクスの制約

1.型変数に対して基本データ型を指定することはできない。

List<int> list = new ArrayList<int>();  // コンパイルエラー

2.型変数のオブジェクトを直接生成することはできない。

E e = new E();  // コンパイルエラー

3.型変数Eの配列を生成することはできない。

E[] array = new E[10];  // コンパイルエラー

4.メソッドの戻り値として型変数の配列を返すようにしても Object の配列にとなる。

5.型変数はstaticメンバとstatic初期化子には適用できない。

class GlobalStack<E> {
  private static List<E> stack = new ArrayList<E>();  // コンパイルエラー
  
  public void push(E e) { stack.add(e); }
  public E pop() {return stack.remove(0); }
}

6.イレイジャの結果、メソッドのシグネチャが同じになるメソッドは定義できない。

class Foo<T, S> {
  public void method(T t) {};  // コンパイルエラー
  public void method(S s) {};  // コンパイルエラー
}

7.型変数が異なる同じインタフェースを複数実装することはできない。

// コンパイルエラー
class Foo implements Bar<Integer>, Bar<String> { 
}

参考記事:Java Press Vol.37 J2SE 5.0 実践チュートリアル
参考ページ:
Generic Types (The Java™ Tutorials > Learning the Java Language > Generics)
Java総称型メモ(Hishidama's Java Generics Memo)
キュー構造をJavaで実装してジェネリック型を理解する (2/3) - @IT

2012開幕戦予想布陣 #albirex #jubilo

新潟は4-4-2で
ツートップはミシェウ、ブルロペ
サイドハーフが左がアラン・ミネイロ、右は亜土夢
ボランチが本間、菊地
DFは左からキム・ジンス、大井、大輔、村上
だった。
矢野復帰で3トップの可能性も巷では噂になっているが、2/18時点では一貫して4-4-2で3トップの練習は行われていないそうだ。

ジュビロでは左サイドハーフに松浦が入っていた。
福岡で1年通してやって成長したのかな。
背番号11の期待の高さを物語る。2008年の入れ替え戦の時みたいなキレキレのドリブルからのシュートをまた見たいよ。
FWは山崎に続いて金園までケガしたけど、まだ阿部、押谷がいるし心配ないかな。

あとディビッドソン純マーカスの記事もあった。MLSのバンクバーでやっているそうだ。ほー。

February 20, 2012

サーブレット・JSPメモ013:データソース・JNDIの利用

Tomcatでデータソース・JNDIを利用してデータベースに接続する場合、META-INF/context.xml に以下のように記述する(データベースはMySQL)。
Eclipseで動的WEBプロジェクトの場合、Server.xml にそのWEBアプリのContext要素があるので、そちらに Resource要素を書いてもよい。

context.xmlの例
<Context>
    <Resource name="jdbc/mysql" auth="Container"
        type="javax.sql.DataSource"
        username="java" password="password"
        driverClassName="com.mysql.jdbc.Driver"
        url="jdbc:mysql://localhost/java_sample_db" />
</Context>

name は任意の名前。この名前を使ってデータソースを取得する。
auth を "Application" とすると認証はアプリ側で行うことになる。
username と password はデータベースに接続するためのユーザ名とパスワード。
driverClass はJDBCドライバのクラス名。
url は getConnection() で直接コネクションを取得するときのURLと同じ。

サンプルコード

package websample;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

public class DataSourceTest extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		response.setContentType("text/plain");
		response.setCharacterEncoding("UTF-8");
		PrintWriter out = response.getWriter();

		try {
			InitialContext initialContext = new InitialContext();
			DataSource dataSource
				= (DataSource) initialContext.lookup("java:comp/env/jdbc/mysql");
			Connection conn = dataSource.getConnection();
			out.println("success: connection=" + conn);

		} catch (SQLException e) {
			throw new ServletException(e);
		} catch (NamingException e) {
			throw new ServletException(e);
		}
	}
}

javax.naming.InitialContext はJNDIを利用する際の窓口で、ファイルシステムにたとえるとルートディレクトリである。

関連する以前の記事:MySQLメモ002:JDBCによる接続

参考ページ:JavaによるWebアプリケーション入門

サーブレット・JSPメモ012:Eclipseで開発している場合のjarファイルを置く場所

動的WEBプロジェクトでWEBアプリを開発している場合、
そのWEBアプリだけで使うjarファイルは、

<プロジェクト>/WebContent/WEB-INF/lib

に置く。
すべてのWEBアプリで使うjarファイルは

<Tomcatのフォルダ>/lib

に置く。ここにあるjarファイルは、プロジェクトのビルドパスの Apache Tomcat v6.0 に入る。

February 19, 2012

log4jの導入

いまさら log4j を導入してみた。1.3は "discontinued branch"、2.0 は "experimental branch" ということで1.2を導入。
以前はログといえば定番のlog4jだったけど、最近は logback とか SLF4J とか色々あるらしいし、どうなんだろう。
#SLF4Jというのはインタフェース?

  1. 下記から 1.2.16 をダウンロード
    Apache log4j 1.2 - Download Apache log4j 1.2
  2. ダウンロードしたzipファイルから log4j-1.2.16.jar を取り出す。
  3. プロジェクトのコンテキストメニューの「ビルド・パスの構成」:ライブラリタブ>「外部Jarの追加」で上記のjarファイルを追加する。
  4. 設定ファイル log4j.xml か log4j.properties をクラスパスの通っているところに置く。
    Eclipse の場合、srcフォルダの直下に置く。ビルド時にsrcフォルダからclassファイルのフォルダにコピーされるので。

log4j.xml のサンプル

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">

<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>

<appender name="FILE" class="org.apache.log4j.FileAppender">
  <param name="File" value="log.txt" />
  <layout class="org.apache.log4j.PatternLayout">
    <param name="ConversionPattern"
           value="%d{yyyy-MM-dd HH:mm:ss.SSS} %p:%r:%c:%m%n" />
  </layout>
</appender>

<category name="logtest">
  <priority value="debug" />
  <appender-ref ref="FILE" />
</category>

</log4j:configuration>

ログの書式設定の中で、%d の後ろの波カッコ内で SimpleDateFormat のパターン文字列を使って時間の書式を指定できる。
書式を指定しない場合は "2012-02-19 15:22:15,403" のような書式になる。

category要素のname属性にはログを出力する範囲をパッケージ名で指定する。
たとえば name="logtest" とした場合、logtestパッケージのクラスからのログは出力され、さらに logtestの子孫のパッケージ(logtest.sub, logtest.sub.sub, ...)のクラスからのログも出力される。

Tomcat6 でLog4j を使う方法は、なんか jar ファイルを自分で作ったりしないといけないようなので、深く調べない。
#逃げてばっかだなw
設定だけでできる、というようなことを書いてあるところもあるが、昔の話か?

参考ページ:
Javaの道:Log4J(1.インストール)
Javaの道:Log4J(2.基本操作)
Log4J徹底解説~使い方(1)
Eclipse/3.1/FAQ - ピノキヲ IT Wiki
IBM FileNet P8
Tomcat 6.0 の標準ログを Log4j に変更 | MOYO Laboratory

PreparedStatementでワイルドカードを使うときの注意

PreparedStatement でワイルドカードを含んだ

SELECT * FROM ACCOUNT WHERE NAME LIKE '<入力値>%'

というSQLを実行しようと思い、

String sql = "SELECT * FROM ACCOUNT WHERE NAME LIKE '?%'";

PreparedStatement ps =  connection.prepareStatement(sql);
ps.setString(1, keyword);
ResultSet rs =  ps.executeQuery();

として実行したら以下のようなエラーが出た。

java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).

?はシングルクウォートで囲ってしまうとプレースホルダとしては機能しなくなるそうだ。
正しくは以下のどちらかのようにすればいいらしい。

String sql = "SELECT * FROM ACCOUNT WHERE NAME LIKE ? || '%'";

PreparedStatement ps =  connection.prepareStatement(sql);
ps.setString(1, keyword);
ResultSet rs =  ps.executeQuery();
String sql = "SELECT * FROM ACCOUNT WHERE NAME LIKE ?";

PreparedStatement ps =  connection.prepareStatement(sql);
ps.setString(1, keyword + "%");
ResultSet rs =  ps.executeQuery();

実際に試すと後者はうまくいくが前者はダメだった。
MySQLの問題?

参考ページ:
Java: PreparedStatement で like を扱う時の注意点 - sardineの日記
PreparedStatementのLIKE条件 | MOYO Laboratory

February 17, 2012

サーブレット・JSPメモ011:DB接続するWEBアプリでリロード時に致命的なエラーが出る

参考サイト:MemoryLeakProtectionとJDBC - 人類みんなごくつぶし

サーブレットの入門書のサンプルアプリをEclipse上で動かしていたら、ソース修正によりオートリロードが発生した時にコンソールに

致命的: The web application [/hogehoge] registered the JBDC driver [com.mysql.jdbc.Driver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.
というエラーが出た。
「致命的」とか言ってるしなんだろうと思ってググッたら、上記のページに行き当たった。
DBCP というもののバグで別にアプリがまずいわけじゃないらしい。
#DBCP = DataBase Connection Pool でも気になるならWEBアプリの終了時に以下のようなコードでドライバーを外せばエラーはでなくなるとのこと。

Enumeration drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
    Driver driver = drivers.nextElement();
    DriverManager.deregisterDriver(driver);
}

MySQLメモ002:JDBCによる接続

JDBCドライバのダウンロード

以下からダウンロード。
MySQL :: Download Connector/J

動的WEBプロジェクトへのJDBCドライバの導入

プロジェクトの WebContent/WEB-INF/lib フォルダを選択し、
コンテキストメニューでインポートを選択し、
インポート・ソースの選択で一般>ファイルシステム
としてドライバのjarファイルをインポートする。

サンプルアプリ

package appsample;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class DBSample {

  /**
   * DBへのコネクションを取得する。
   */
  public static Connection getConnection()
      throws ClassNotFoundException, SQLException {

    Class.forName("com.mysql.jdbc.Driver");

    // ホスト名:localhost データベース名:java_sample_db
    // ユーザ:java パスワード:password
    Connection conn = DriverManager.getConnection(
        "jdbc:mysql://localhost/java_sample_db",
        "java", "password");
    return conn;
  }

  public static void main(String[] args) throws Exception {

    String updateSql
      = "UPDATE ACCOUNT SET MONEY=? WHERE NAME=?";
    Connection conn = null;
    PreparedStatement ps = null;
    Statement stmt = null;

    try {
      conn = DBManager.getConnection();
      ps = conn.prepareStatement(updateSql);

      // PreparedStatementを使用した更新
      ps.setInt(1, 6000);
      ps.setString(2, "ボブ");
      int count = ps.executeUpdate();

      // 更新件数の表示
      System.out.println("update count=" + count);

      // 検索
      stmt = conn.createStatement();
      String selectSql = "SELECT * FROM ACCOUNT";
      ResultSet rs = stmt.executeQuery(selectSql);

      while (rs.next()) {
        System.out.println(
          "ID=" + rs.getInt("ID")
          + ",NAME=" + rs.getString("NAME")
          + ",MONEY=" + rs.getInt("MONEY"));
      }

    } finally {
      if (ps != null) {
        try {
          ps.close();
        } catch (Exception e) {
          // nop
        }
      }
      if (stmt != null) {
        try {
          stmt.close();
        } catch (Exception e) {
          // nop
        }
      }
      if (conn != null) {
        try {
          conn.close();
        } catch (Exception e) {
          // nop
        }
      }
    }
  }
}

参考ページ:JavaでJDBCを用いてMySQLへ接続する (前編) - devel-log.tar.gz

V字回復って楽観的過ぎないか #kabu

日経平均、終値は9384円 半年ぶり高値 - ビジネス・経済:朝日新聞デジタル

年初に今年の高値を1万円とか1万1千円とか言っているアナリストがたくさんいた。自分はとても信じられなかった。
たしかに日本の株価は200日移動平均を超えて上がっているが、それでも自分の考えは変わっていない。懐疑的・悲観的なままだ。
今の株価の上昇は各国の金融緩和による金余りが原因であって日本企業の先行きが明るいと見られているわけじゃない。

来年度は今年度の震災・タイの洪水のような特殊要因がなければそりゃ収益は大幅に改善するだろう。
しかし、「V字回復」ってのはそう簡単じゃない。
日本の輸出産業はあらゆるジャンルで中国勢・韓国勢とぶつかって、負け続けている。今の日本製品に価格競争力が全くないからどうしようもない。

パナソニックはテレビ事業の採算悪化、三洋電機の買収などで7800億円の大赤字を出した。三洋を買って強化したリチウムイオン電池事業で攻勢をかけるというが、すでに買収時と比べて三洋の価値は大きく下がっている。それにリチウムイオン電池では韓国勢がどんどんシェアを伸ばしている。とてもこれからの収益のドライブになるとは思えない。

鉄鋼業界では日本メーカーが圧倒的に強かった自動車用の鋼板に韓国メーカーが進出してきている。それだけ韓国メーカーの品質が上がってきているのだ。
「日本メーカーはいいものを作ってるのだから売れるはず」なんてもう幻想だ。

最近の円安傾向で輸出企業が助かるという話もあるが、日本は原発事故による火力発電用燃料の輸入増加で貿易収支は赤字である。国全体で見れば円高はプラスに働いていたことになる。
これが円安になったら輸出による売り上げが増えても原油・LNG・鉄鉱石などのエネルギー・素材価格が上がる。少なくとも言われているような「円高は日本経済にとって圧倒的にプラス面の方が大きい。」ということはないと思う。

それに電力の問題。このまま原発停止が長引けば、早晩、東電だけでなく他の電力会社も大幅な値上げを避けられない。その結果、多くの製造業が海外に出ることか、廃業するかの決断を迫られるだろう。
#電炉メーカーとかめっき工場とか、特に電気を多く使う業種・工場は国内じゃとてもやっていけないよ。。。

このまま株価が上がるとしても1万円まではかなりある。
1万円に届く前にまた業績予想の下方修正がどんどん出てきて株価は下げると予想している。
もし1万円に届くとしたら、可能性としては原発の再稼動が予想以上にスムーズに進んで電気料金の値上げの影響が最小限に抑えられるとか、そんな感じだろうか。

February 16, 2012

PHPメモ010:変数操作関数

bool isset(<変数>)
変数に値がセットされており、それがNULLでないことを調べる。

bool empty(<変数>)
変数が空であるかを調べる。
以下の値は空とみなされる。
・空文字列
・整数の0
・0.0(浮動小数点数の0)
・"0"(文字列の0)
・NULL
・FALSE
・空の配列
・クラスの中で宣言されているが値がセットされていない変数

void unset(<変数>)
変数を破棄する。

サンプルコード
$b = 0;
$c = 'hello';

echo '$a'
  . (isset($a) ? "は${a}です" : 'には値が代入されていません') . "。\n";
echo '$aは空' . (empty($a) ? 'です' : 'ではありません') . "。\n";

echo '$b'
  . (isset($b) ? "は${b}です" : 'には値が代入されていません') . "。\n";
echo '$bは空' . (empty($b) ? 'です' : 'ではありません') . "。\n";

echo '$c'
  . (isset($c) ? "は${c}です" : 'には値が代入されていません') . "。\n";
echo '$cは空' . (empty($c) ? 'です' : 'ではありません') . "。\n";
サンプルコードの出力
$aには値が代入されていません。
$aは空です。
$bは0です。
$bは空です。
$cはhelloです。
$cは空ではありません。

void var_dump(<変数>)
変数に関する情報をダンプする。

bool settype(<変数>, <型文字列>)
変数の型を<型文字列>で指定した型にする。

サンプルコード
$text = 'hello';
$num = 10.0;

var_dump($text);
var_dump($num);

settype($num, 'int');
var_dump($num);
サンプルコードの出力
string(5) "hello"
float(10)
int(10)

February 15, 2012

サーブレット・JSPメモ010:web.xmlのjsp-property-group要素

web.xmlのjsp-config要素の子要素にjsp-property-group要素がある。これを使って複数のJSPに一括で設定をすることができる。
url-pattern要素でURLのパターンから設定するJSPを指定する。
include-prelude、include-code要素には、共通するヘッダ・フッタを指定する。
include-prelude要素に共通部分(pageディレクティブ、taglibディレクティブなど)をまとめたヘッダ用JSPファイルを指定すればいいことありそうだ。たとえば使用するタグライブラリを変更する場合、ヘッダ用JSPのtaglibディレクティブの修正だけで済み、個々のJSPは変更なしで済む。

<jsp-config>
  <jsp-property-group>
    <url-pattern>/products/*</url-pattern>
    <page-encoding>UTF-8</page-encoding>
    <scripting-invalid>false</scripting-invalid>
    <is-xml>false</is-xml>
    <include-prelude>/common/products_header.jsp</include-prelude>
    <include-code>/common/products_footer.jsp</include-code>
  </jsp-property-group>
</jsp-config>
参考ページ:@IT:Java TIPS -- 個別のJSPページでJSTL宣言を省略する

サーブレット・JSPメモ009:includeディレクティブとincludeアクションの違い

includeディレクティブと標準アクションの<jsp:include>はどちらもファイルをインクルードするものだが、大きな違いがある。

includeディレクティブ
静的なインクルード:JSPソースからJavaソースに変換されるときに利用される。
インクルードできるのはHTMLファイル、JSP。サーブレットは不可。
インクルードする対象にパラメータを渡すことはできない。

includeアクション(標準アクション<jsp:include>)
動的なインクルード:Javaソースへの変換でRequestDispatcher#include()に変換され、リクエストに対しての実行時にインクルードされる。
インクルードできるのはHTMLファイル、JSP、サーブレット
インクルードする対象に<jsp:param>アクションを使ってパラメータを渡すことができる。

February 14, 2012

サーブレット・JSPメモ008:init(),destroy()のオーバーライド時の注意

init() と destroy() はそれぞれサーブレットの初期化時・終了時に呼ばれる。
init() には引数がないものと ServletConfig を引数に持つものがある。
前者の場合、スーパークラスのinit()を呼ぶ必要はないが、後者ではスーパークラスの init(ServletConfig config) を呼ぶ必要がある。
呼ばないと、もしかしたら厄介な問題になるかもしれない。
たとえば getServletContext() を呼ぶと例外が発生する。super.init(config) を呼び忘れていることに気がつかず結構悩んだ。
destroy() も同様で、必ずスーパークラスの destroy() を呼ぶ必要がある。

public void init(ServletConfig config)
    throws ServletException {
  super.init(config);
  
  // super.init(config) を呼んでいないとここで例外が発生する
  ServletContext context = getServletContext();
}

public void destroy() {
  super.destroy();

  // super.init(config) を呼んでいないとここで例外が発生する
  ServletContext context = getServletContext();
}

Edyが楽天Edyに

電子マネー「Edy」が「楽天Edy」に名前変更&ロゴも変更 - GIGAZINE

結構前に発表された話でいまさらだが。
発表直後、「Edy終わった」みたいな意見を結構ネットで見かけた。
「Edy」は決済サービスで、どこのお店からも等距離・中立というイメージがあった。
でも「楽天」っていうのがEdyの前に付くとその中立というイメージが崩れる。
まあわからんでもない。小売店はEdyを導入するともれなく「楽天」という言葉がくっついてきて、なんか手数料払った上に楽天の宣伝させられてるみたいで嫌な感じだろうなw

SONY傘下だったときから毎年多額の赤字を垂れ流し、累積債務に耐えられなくなって楽天に引き取ってもらった。
そして楽天傘下になったものの、相も変わらず毎年赤字。
楽天は「黒字化なんて無理。せめて名前に『楽天』を付けて宣伝にでも使わなきゃやってられん。」という結論に至ったんだろう。
Edyは大手コンビニならほぼ使えて便利だと思うのだが、なぜにここまで儲からない事業になってしまったのか。SONYとしてはEdyの事業は赤字でもいいからFelicaチップで儲けようと思ってたのかなあ。
そこらへんを詳しく取材した記事とかあったら読んでみたい。

手元にあるプリペイド型電子マネーとしては
・Edy(ヨドバシのクレジットカードに付属)
・SUICA
・WAON(イオンカードに付属)
の3つ。
首都圏の大手コンビニならSUICA使えるし、自分が利用したことがある店でEdyしか使えないところってゲオくらいだ。
Edyなくなってもあんまり困らんなあ。
#ファミマでWAON使えるのか。

February 12, 2012

サーブレット・JSPメモ007:サーブレットのシングルインスタンス・マルチスレッドモデル

サーブレットは通常、最初にそのサーブレットへのリクエストがあるとインスタンス化され、init()が呼ばれる
1つのサーブレットはインスタンスが1つ作られてメモリに常駐し、同じサーブレットのリクエストに対しては同じインスタンスが利用される。
よってprivateな変数も複数のリクエスト間で共有される。読み取り専用データや定数以外はサーブレットのフィールドにすべきではない。

1つのサーブレットのインスタンスは1つで、マルチスレッドで動作する。
下記表はサーブレット・JSPの変数・属性がスレッドセーフかどうかを表している。

スレッドセーフ
ローカル変数
インスタンス変数×
static変数×
リクエスト属性
セッション属性×
アプリケーション属性×
ページ属性(※)

※:ページ属性はJSPのページスコープの属性。暗黙オブジェクトの pageContext に設定する。

サーブレット・JSPメモ006:コンテキストパス

JSPで同じWEBアプリケーション内へのリンクを張る場合、URLは

<a href="<%= request.getContextPath() %>ServletA">ページA</a>
<a href="<%= request.getContextPath() %>sub/B.jsp">ページB</a>
のように記述すれば、コンテキストルートからの相対パスとなる。
リンク先のURLを相対パスを固定値で書くとリンク元のJSPの場所が変わると相対パスも変わるのでリンク先URLも変更しなければならないが、上記のように getContextPath() を使えば変更する必要がない。

February 11, 2012

サーブレット・JSPメモ005:フォワード・インクルード・リダイレクト

フォワード

RequestDispatcher dispatcher
  = request.getRequestDispatcher("/ForwardServletB");
dispatcher.forward(request, response);

・request から RequestDispatcher を取得した場合、getRequestDispatcher()の引数は request のパスからの相対パス("/"ではじまらない)か、コンテキストルートからの相対パス("/"で始まる)。
・context から RequestDispatcher を取得した場合、RequestDispatcher()の引数のパスはコンテキストルートからの相対パス/"で始まる)のみ。
・フォワードしてもブラウザのURL欄はフォワード元のURLのまま。
・フォワード元のサーブレットは出力の一切をフォワード先に任せる。フォワード元サーブレットがresponseに書き込んでもフォワード時にレスポンスのバッファがクリアされるので、クライアントに返されるレスポンスにフォワード元サーブレットが書き込んだものは含まれない。

インクルード

RequestDispatcher dispatcher
  = request.getRequestDispatcher("/ForwardServletB");
dispatcher.include(request, response);

・インクルード元もインクルード先もresponseに出力することができる。

リダイレクト

response.sendRedirect(request.getContextPath() + "/test.html");

・引数のパスは絶対URL("http://www.google.com/"のような)かサーバールートからの相対パス。
・クライアントに一度処理を戻すので通信回数が増える。またリクエストスコープで値を渡すこともできない。

February 10, 2012

サーブレット・JSPメモ004:GETリクエストのパラメータの文字化け

Tomcat5以降ではGETリクエストにおいてURLでエンコードされたパラメータのデコードは、doGet()で

request.setCharacterEncoding("UTF-8");	// UTF-8の場合
とやっても無視されて ISO8859-1 が使われる。
※POSTは指定した文字エンコーディングでデコードされる。

setCharacterEncoding()が効くようにするには server.xml で

<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1"
 redirectPort="8443" />
に useBodyEncodingForURI="true" を加えて
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1"
 redirectPort="8443" useBodyEncodingForURI="true" />
と変更すればよい。

request.setCharacterEncoding(<文字コード>) の呼び出しは、requestからパラメータを取得する前にしなければならない。
doGet() や doPost() の中だけではなく、たとえばフィルタで

value = request.getParameter("key");
とやったら、この後の doGet() や doPost() で request.setCharacterEncoding(<文字コード>) を呼んでも ISO8859-1 でデコードされてしまう。

参考ページ:Tomcat5/6のGETリクエストで文字化け - @”かたち開発の開発日記”

「FXは中産階級のパチスロ」か? #fx

2週間くらい前の週刊アスキーの岡田斗司夫さんの連載で頭に残った言葉が2つある。

・「FXは中産階級のパチスロ」
FXについては、まあ体験的に同意w
ここのところの豪ドル高で含み益が出ているけど、今までのトータルの収支は考えたくもないほどのマイナスだ。
収支がプラスの人もそりゃいるだろうけど、マイナスの人の方が圧倒的に多いだろう。
#銀行やファンドのトレーダーではなく個人で自分の金を運用している人の場合。

FXや株の売買で生活できるほど稼げる人は、特殊な才能の持ち主だと思う。
テレビですごい勝っているデイトレーダーの人を見たことあるが、なんか感情がないみたいだった。6面くらいの液晶ディスプレイを見続けて、機械のように素早く正確にキーボードを叩いていた。取引の時だけそんな感じで普段は普通なのかもしれないけど、そういうふうに切り替えられるとしてらそれはそれで特殊な才能だろう。
スウィングトレードでも、
 儲かっている時は「もっと上がる」と思う。
 損をしている時は「きっと反転する」と思う。
みたいに自分にとって好ましい未来を信じて、最終的にはトータルで損している人が多いんじゃなかろうか。
根拠のない楽観的な予想を排除して冷静に論理的にトレードできる人ってそんなにいるとは思えいない。
というか、それができる人はきっとFXや株以外のことでも大概のことはうまくできそう。
自分はそういう特殊な能力ないけど、甘い夢を抱きながら破産しない程度に続けていきますw


・「頭のおかしい人は、例外なく論理的」
「例外なく」っていう点は違うのではと思った。
○チガイには
(1)論理なしの○チガイ。
(2)俺的論理持ち○チガイ。
(3)論理的に正しい○チガイ。
の3パターンがあるような気がする。

(1)は知性の足りない人。まあ動物みたいなもの。
(2)は客観的には間違ってるけど本人は論理的に正しいと固く信じているタイプ。たとえばマツダの工場で暴走して人をはねまくった人はこれじゃないかな。
(3)は論理的には正しいけどその論理から導かれた結論が社会常識とかけ離れているので○チガイ扱いされる。
「早すぎた天才」という可能性もある。たとえばガリレオは当時の社会情勢・科学レベルからして多くの人から「こいつ頭おかしいんじゃねえの?」と思われていただろう。
世の中の○チガイは(1)と(2)がほとんどで、「論理的な頭のおかしい人」はレアなんじゃないかなあ。

February 07, 2012

サーブレット・JSPメモ003:開発環境その2:WTP

関連記事:サーブレット・JSPメモ001:開発環境:Eclipseの設定

Context要素

WTPでは、WEBアプリケーションの設定を記述するContext要素は

<ワークスペース>\Servers\<サーバ名>-config\server.xml

に書き込まれる。

Tomcat5以降ではContext要素を

<WEBアプリケーションのフォルダ>/META-INF/context.xml

に書くことが推奨されているが、WTPでは上記のように server.xml に書き込まれる。
試しに server.xml のContext要素をカットし新規作成した /META-INF/context.xml をベーストした。そしてWEBアプリケーションを「サーバーから実行」してみたが、404になった。
WTP Tomcat FAQというサイトの3.9を見ると、サーバービューでサーバーを開いてサーバー・オプションの「XMLファイルを分割してモジュールコンテキストを公開」というのにチェックを入れればいいような気がしたが、それでもダメだった。
Context要素をserver.xmlから出してcontext.xmlだけに書くやり方はわからない。未解決のまま。

Tomcatの実行環境

WTPにおいてTomcatの実行環境は

<ワークスペース>\.metadata\.plugins\org.eclipse.wst.server.core\tmp0

にある。
"tmp0" の数字部分は変わることもあるらしい。

プロジェクト毎のファイルは

<ワークスペース>\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\<プロジェクト名> …(1)

にコピーされる。
動的WEBプロジェクトでは "<プロジェクトのフォルダ>\WebContent" の下にWEB-INFフォルダ、HTMLファイル、JSPファイルなどがあり、実行時にはこのWebContent配下が(1)にコピーされる。
WebContentというフォルダはWTP(動的WEBプロジェクト)のフォルダである。動的WEBプロジェクトの作成ウィザードの中で設定したディレクトリで(デフォルトが WebContent で、別のフォルダ名に変更可能)、Tomcat(WEBアプリ)の設定のどこかに WebContent というのが書いてあるわけではないし、実際のWEBアプリの構造上に WebContent というフォルダがあるわけでもない。

参考ページ:
Eclipse Web開発環境メモ(Hishidama's Eclipse WTP Memo) Eclipsにおける 動的WEBプロジェクトとTomcatプロジェクトの違い | OKWave

February 06, 2012

サーブレット・JSPメモ002:tomcat-users.xml

Tomcatのホーム画面からStatusやManagerをクリックするとユーザー認証を求められる。
そのユーザーは conf/tomcat-users.xml に記述する。


<tomcat-users>
  <role rolename="manager"/>
  <user username="admin" password="admin" roles="manager"/>
</tomcat-users>

managerのほかにadminなどのロールがある。この2つのロールは"built-in"ロールらしい。それぞれの詳しい説明をドキュメントに探したが見つけられなかった。

Eclipseの設定でTomcat Manager の設定があるが、設定してもWTPから起動した場合はTomcat Managerを使えない。バグ?
設定の場所は以下。

メニューの ウィンドウ>設定
-設定ダイアログで Tomcat>Tomcat アプリケーションマネージャー

設定されているURLを開いても404だし、ユーザ名とパスワードを入力して「tomcat-users.xmlにユーザーを追加」ボタンを押しても tomcat-users.xml は変更されない。
参考サイトにあるように server.xml と tomcat-users.xml に手動で必要な記述を追加すればTomcat Managerを使える。しかしEclipse にそれらしい項目があるのになあ。

参考ページ:Eclipse WTP で、Tomcat manager起動-Oboe吹きプログラマの黙示録

不可解な山村先発、不安定なGK権田:オリンピック最終予選シリア戦 #soccer

シリア 2-1 日本 :スコア速報 - ロンドン五輪 男子サッカーアジア予選 : nikkansports.com

なんというか、見てて悲しくなった。縦ポンして、競って、取られる。こんなチームじゃ仮に予選突破しても本番で勝てない。

守備陣は不要なファールが多いし、GKは下手だし。
2失点はどちらもGKに大いに責任がある。特に1点目。大迫に当たってちょっとコースが変わったかもしれないが、それでも手が届くところだ。それを胸で取りに行って失敗してる。2点目もキャッチじゃなくて弾きに行ってれば防げたのでは。
あとボランチ山村が最悪。関塚監督はなぜ山村にこだわるの?J1で試合に出ている本職ボランチがいるのに、大学生のCB、それもケガ空けの選手を使うのか。

攻撃もとてもほめられた出来ではない。プレーの精度が低い。結局清武がいないとダメか。
大迫は何なんだ。山崎に代わって入って、いきなり自分のゴールにヘディングシュートorz
大迫より斉藤学を見たかったなあ。
自分は以前から大迫は高校時代の活躍のせいで過大評価されていると思っていたが、昨日の試合でその思いはより強くした。多くの人が既に言っているけど、鹿島の先輩のQBKの人に姿がダブって見える。あの人ほどの実績ないけど。
今回、原口はニュースになったあのバカなことしたせいなのか呼ばれなかったが、原口>大迫だと思う。他にも大迫よりはマシな22歳以下のFWいるよ。
永井だけだ。昨日の試合でよくやったと言えるのは。

ピッチコンディションとか清武不在とか、言い訳にならない。負けるべくして負けたんだ。
まったくもっていまさらだが、関塚監督の能力に疑問符。
清武、山崎はマレーシア戦もダメそうだし、「マレーシア戦で大量得点して得失点差でシリアを逆転」なんて楽観的なことはとても考えられない。

#しかし、山崎骨折はジュビロにとっても痛いなあ;

トラックバック先:単純に弱い-シリア戦 | 蹴球密林 | スポーツナビ+

サーブレット・JSPメモ001:開発環境

サーブレット・JSPの勉強のための環境を作った。インストールしたのは以下。

  • Tomcat 6.0.35
  • Eclipse 3.7.1 Indigo Windows 32bit ベース / Pleiades All in One 3.7.1.v20110924

Eclipse

Androidアプリ開発用とは別にもう1つEclipseをインストールした。
使ったのは「Pleiades All in One 3.7.1」のJREなし版。日本語化やプラグインで手間はかけたくなかったが、JDKは既にインストールされているので。

Tomcat

Tomcat 6.0.35 のインストーラー版でインストール。TomcatをWindowsのサービスとして使うためのもののようで、startup.bat などの起動や終了用のバッチファイルは付いていない。

このままだとTomcatを起動するとエラーのポップアップメッセージが出てくる。
起動はできていてブラウザで http://localhost:8080 を開けばTomcatの画面が出てくるが、起動のたびにエラーのポップアップが出てくるのは精神上良くない。
参考サイト2にあるように、tomcat6w.exe のプロパティの互換性タブで「管理者として実行する」にチェックを入れるとポップアップは出なくなる。

Eclipseの設定

#サーバーとTomcatはどっちが先に設定するんだったかなあ。どっちからでもいいのか、自信がない。

・JREの設定
メニューのウィンドウ>設定
-設定ダイアログで Java>インストール済みのJRE>追加>標準VM
JREホーム:C:\Program Files\Java\jdk1.6.0_24

・サーバーの設定
メニューのウィンドウ>設定
-設定ダイアログで サーバー>ラインタイム環境>追加>Apache Tomcat v6.0
パスと名前を設定。

・Tomcatのパスの設定
メニューのウィンドウ>設定
-設定ダイアログで Tomcat
Tomcatバージョン:バージョン 6.x
Tomcatホーム:C:\applications\Apache Software Foundation\Tomcat 6.0

・サーバービューの表示
メニューのウィンドウ>ビューの表示>サーバー

・サーバーの追加
「サーバー」ビュー上で右クリック、新規>サーバー
Tomcat v6.0 サーバー を追加

・JSPの文字コードの設定
メニューのウィンドウ>設定
-設定ダイアログで WEB>JSPファイル
エンコード:Windows環境ではデフォルトは「Windows-31J」。「UTF-8」などに変更した。

参考ページ:
1.Eclipse を使用しての Java サーブレット・プログラム開発
2.Tomcat Application System Error アクセスが拒否されました。 - 日々情報収集...
eclipse3.3 利用ガイド(J2EE アプリケーション開発編)

February 05, 2012

#FF11 悪烈・粉砕のアートマをゲット

昨日の夜、ウルラガンで悪烈・執拗・粉砕のアートマ取りをするというシャウトがあった。
執拗は持ってたけど他の2つはなかったので参加した。
主催者は夜の7時くらいから9時くらいまでシャウトし続けて10人集めた。俺なら心折れてる。まったく頭が下がる。

まずガーゴイルNMから。沸いていたので赤突いて倒して悪烈のアートマをゲット。
次にダイアマイトNMの所に行ったが取られていたので先に鉄巨人の方へ。こちらも赤突いて問題なく粉砕のアートマをゲット。
それからダイアマイトの所に戻ったがまた取られた。でもアラ組ませてもらい倒した。
ここまでの3戦、赤弱点は全部ライデンスラストだったw

これで終わりからと思ったら「三日月形の緋色のジェイド」を持っている人がいたのでそれもやることに。
なかなか釣ることができず他のPTに取られたがアラ組んでもらった。よかったよかった。
しかし自分はダイタルウェイヴで死んでアートマ取得失敗;;
侠者の薬使わなければならなかったのか。
もったいないことをしたorz

February 02, 2012

Androidアプリ開発メモ061:独自のAlertDialog

関連する記事:Androidアプリ開発メモ046:スタイルとテーマ

AndroidManifest.xmlでテーマを設定するやり方と、レイアウトをXMLファイルで定義してAlertDialog.Builder#setView()でセットするやり方がある。

テーマを設定して背景色を変える

AlertDialogの背景色を設定したテーマを作り、それをAndroidManifest.xml のapplicaaction要素またはactivity要素にセットする。

ダイアログを出すメソッド
/** レイアウトファイルにおいてButton要素のonClick属性に設定されているメソッド。 */
public void showAlertDialogMethod1(View v) {
	Log.v("TEST", "showAlertDialogMethod1():v.getTag()=" + v.getTag());
	MyDialogListener listener = new MyDialogListener();
	AlertDialog.Builder myDialogBuilder = new AlertDialog.Builder(this);
	myDialogBuilder.setTitle("タイトル")
		.setMessage("メッセージ")
		.setPositiveButton("Yes", listener)	// ボタン押下の処理が必要なければ引数listenerはnullでよい
		.setNeutralButton("Maybe", listener)
		.setNegativeButton("No", listener)
		.setCancelable(false);
	AlertDialog myAlertDialog = myDialogBuilder.create();
	myAlertDialog.show();
}

色の定義のファイル res/values/color.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
	<color name="red">#ff0000</color>
	<color name="green">#00ff00</color>
	<color name="blue">#0000ff</color>
	<color name="yellow">#ffff00</color>
	<color name="magenta">#ff00ff</color>
	<color name="cyan">#00ffff</color>
	<color name="pink">#ffc0cb</color>
	<color name="khaki">#f0e68c</color>
	<color name="skyblue">#87ceeb</color>
	<color name="saddlebrown">#8b4513</color>
</resources>

テーマ・スタイルを定義したファイル res/values/styles.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
	<style name="MyTheme" parent="@android:style/Theme.Black">
		<item name="android:alertDialogStyle">@style/AlertDialog</item>
	</style>
	<style name="AlertDialog">
		<item name="android:fullBright">@color/red</item>
		<item name="android:fullDark">@color/green</item>
		<item name="android:topBright">@color/blue</item>
		<item name="android:topDark">@color/yellow</item>
		<item name="android:centerBright">@color/magenta</item>
		<item name="android:centerDark">@color/cyan</item>
		<item name="android:centerMedium">@color/pink</item>
		<item name="android:bottomBright">@color/khaki</item>
		<item name="android:bottomDark">@color/skyblue</item>
		<item name="android:bottomMedium">@color/saddlebrown</item>
	</style>
</resources>

スタイルの定義のitem要素がよくわからない。なんとかBrightとかなんとかDarkとかなんとかMediumとか、それぞれどういう意味なんだか。
上記の設定・コードでアプリを作ってAVD上で出たボタン付きのAlertDialogは下のイメージのようになる。

上からタイトル、メッセージ、ボタンのAlertDialogでは
タイトル部分の背景はtopDarkで指定したyellow、メッセージ部分の背景はcenterDarkで指定したcyan、ボタンの部分の背景はbottomMediumで指定したsaddlebrown。
メッセージ、ボタンのAlertDialogでは
メッセージ部分の背景はtopDarkで指定したyellow、ボタンの部分の背景はbottomMediumで指定したsaddlebrown。
タイトル、リストのAlertDialogでは
タイトル部分の背景はtopDarkで指定したyellow、リスト部分の背景はbottomBrightで指定したkhaki。
タイトル、ラジオボタン付きリスト、ボタンのAlertDialogでは
タイトル部分の背景はtopDarkで指定したyellow、リストの部分の背景はcenterBrightで指定したmagenta、ボタンの部分の背景はbottomMediumで指定したsaddlebrown。
他のitemについては何の設定なのか不明。AlertController.java のソースをちょっと見てみたけどわからない。lightとかdarkってのがあるのでバックライトの点灯状態によって色が変わるとか、あと選択されているときとされていない時とかいろいろ考えたが、どちらも実際の動きを見た限りでは違うような気がする。

setView()で独自のレイアウトにする

独自のダイアログのレイアウトをXMLファイルで作成し、setView() でセットする。setView() の引数はリソースIDではなくビューである。
ビューはLayoutInflater#inflate()で作成する。
このやり方は自由度は高いがボタンの処理などを自前で実装する必要がある。下記のサンプルプログラムの実装で動きはするが、適切な方法かはわからない。

ダイアログを出すメソッド
/**
 * レイアウトファイルでbutton2のonClick属性に設定されているメソッド。
 * ボタンを押すとダイアログのEditTextに入力した値をActivityのTextViewにセットする。
 */
public void showAlertDialogMethod2(View v) {
	//ViewGroup dialogRootLayout = (ViewGroup)findViewById(R.id.dlg2LinearLayout1);
	//ViewGroup dialogRootLayout = (ViewGroup)findViewById(R.id.dlg2Layout2);
	// inflate()の第2引数、nullでいいんだろうか?上の2つのようななにかビューを指定すべき?
	View dialog2 = getLayoutInflater().inflate(R.layout.dialog2, null);
	AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
	dialogBuilder
		.setView(dialog2)
		.setCancelable(false);
	final AlertDialog myAlertDialog = dialogBuilder.create();
	
	final EditText dlg2EditText1 = (EditText)dialog2.findViewById(R.id.dlg2EditText1);
	
	// ダイアログのボタンの取得とリスナの設定
	Button dlg2Button1 = (Button)dialog2.findViewById(R.id.dlg2Button1);
	dlg2Button1.setOnClickListener(new View.OnClickListener() {
		@Override
		public void onClick(View v) {
			aTextView.setText(dlg2EditText1.getText());
			myAlertDialog.cancel();
		}
	});
	
	myAlertDialog.show();
}

ダイアログのレイアウトファイル res/layout/dialog2.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:id="@+id/dlg2LinearLayout1"
	android:orientation="vertical"
	android:background="@color/pink"
	android:layout_width="300dp"
	android:layout_height="200dp">
	<EditText
		android:id="@+id/dlg2EditText1"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content" />
	<Button
		android:id="@+id/dlg2Button1"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:text="OK" />
</LinearLayout>

参考ページ:Y.A.M の 雑記帳: Android AlertDialog の背景を変更する

Windows標準機能でZIPファイルを展開する

自分のPCでには圧縮・解凍ツールとしてLHMeltingとLhaplusが入っている。そのせいなのかエクスプローラからWindows7標準のZIP解凍機能を呼び出せない。呼び出せるかもしれないが、やり方がわからない。
#ZIPファイルをダブルクリックするとLHMeltingが立ち上がる。

Windows7標準のZIP解凍機能を使うには、コマンドプロンプトで

explorer <zipファイル名>

とすればよい。
これでエクスプローラがZIPファイルの中身を表示している状態で立ち上がり、あとは「ファイルをすべて展開」をクリックするして展開ウィザードを使うなり、ZIPファイル内のファイルを展開したい場所にドラッグ&ドロップするなりすればよい。

なぜWindows7の標準のZIP解凍機能を使うのかと言うと、Pleiades All in One 日本語ディストリビューションのインストール(解凍)は「 Windows 7 展開ウィザードまたは WinRAR を推奨します。」なので。展開時にパスが長すぎてエラーになる場合があるが、解凍ツールによってそのエラーを適切に返さないものがあるそうだ。そして前記の2つのツールはそのエラーをちゃんと返すと。

« January 2012 | Main | March 2012 »

May 2017
Sun Mon Tue Wed Thu Fri Sat
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
無料ブログはココログ

日本blog村

  • にほんブログ村 IT技術ブログへ
  • にほんブログ村 アニメブログへ
  • にほんブログ村 サッカーブログ アルビレックス新潟へ

好きな音楽家

メモ

XI-Prof