メンバ変数宣言時の初期化=コンストラクタによる初期化
適当にわけのわからない処理を生産してたらよくわからないことになってハマったのでメモっておく。
上記の実行結果は以下のようになる。
parent null
ChildInitAtMemberDeclを逆コンパイルすると以下のようになる。
class ChildInitAtMemberDecl extends ParentInitAtMemberDecl { ChildInitAtMemberDecl() { childStr = null; } protected void init() { super.init(); childStr = "child"; } public String getChildStr() { return childStr; } private String childStr; }
見て分かる通り、メンバ変数宣言時に初期化 = コンストラクタで初期化となる。
ChildInitAtMemberDeclの初期化手順は以下のようになる。
- ChildのコンストラクタでParentのコンストラクタを呼ぶ
- ParentのコンストラクタからChildでオーバーライドしたinitが呼ばれる
- super.initでparentStrに文字列をセット
- Childのinitに処理が戻り、childStrに文字列をセット
- Parentのコンストラクタに処理が戻る
- Childのコンストラクタに処理が戻り、childStrにnullをセット
まあ、(前記事に引き続き)最初からこんなコーディングするなという話……。
Java6,7で可変長引数を持つメソッドをオーバーロードしている際にコンパイル結果が違う時がある
コンパイル結果の違うソース
上記のソースをJDK6のjavac、JDK7のJavacでそれぞれコンパイルすると、結果が違うことがわかる。
JDK6
D:\dev\Java>javac.exe CompileResultDiffTest.java D:\dev\Java>
JDK7
D:\dev\Java>javac.exe CompileResultDiffTest.java CompileResultDiffTest.java:6: エラー: testの参照はあいまいです。Compil eResultDiffTestのメソッド test(int,Object...)とCompileResultDiffTestのメソッド test(Object...)が両方適合します test(0, "a"); ^ エラー1個 D:\dev\Java>
同じクラスの可変長引数をもつメソッドをオーバーロードしているメソッドで
他に用意されている引数が可変長引数のクラスにオートボクシング出来る場合に
Java7ではあいまいエラーとして解釈するようになった?
そもそもそんなオーバーロードするなという話でもあるが……。
eclipse側の問題
問題はeclipse側のコンパイラ。
eclipseのコンパイラがJDKのコンパイラと別のモノだというのは下記サイトとかにある。
http://www.myeclipseide.jp/blog/2009/06/eclipse-jdt.html
http://feather.cocolog-nifty.com/weblog/2004/08/eclipsej2sdk.html
eclipseでコンパイルする際にどのJDKバージョンに従うかは、設定(Java>コンパイラ)でコンパイラー準拠レベルを設定すればよい。
しかし、コンパイラー準拠レベルの設定にかかわらず、上記ソースのコンパイル結果は以下のようになる。*1
バージョン | 曖昧エラー発生有無 |
---|---|
eclipse3.7(Indigo) | あいまいエラーは発生しない |
eclipse4.2(Juno) | あいまいエラーが発生する |
そのため、Java7を使って開発するけど、eclipseはどんなバージョンでも構わない という場合に
Indigoを使って書いたコードが、Junoでコンパイル通らない、という状況が発生する場合があるので、
気をつけたほうが良いかもしれない。
*1:Indigo以前のバージョンは試していない。
Eclipse開発環境設定メモ
とりあえずインストールするもの
Java7 : http://java.com/ja/download/
Java6 : http://java.com/ja/download/manual_v6.jsp
Java7 : http://www.oracle.com/technetwork/java/javase/downloads/jdk7u9-downloads-1859576.html
Java6 : http://www.oracle.com/technetwork/java/javase/downloads/jdk6u37-downloads-1859587.html
- plaiades platform
英語わかんないので、Pleiadesを入れる。pluginは後で自分で入れるし、JREはさっき入れたのでplatformのJREなし版を選ぶ。
せっかくなのでJunoにした。
http://mergedoc.sourceforge.jp/index.html
Eclipse pluginのインストール
とりあえずデフォルトで新規ソフトウェアのインストールからインストールできるもの
その前にインストールウィンドウ開いたら「必須ソフトウェアを……」の項目を外す。
- Junoを選択して以下をダウンロード
コラボレーション → Eclipse EGit
一般用ツール → Marketplace Client
プログラミング言語 → Eclipse Java 開発ツール、Eclipse XML エディターおよびツール
Marketplaceからインストールできるもの
必須。Marketplaceから「FindBugs」で検索してインストール。
必須。Marketplaceから「Checkstyle」で検索してインストール。
その他
- Explore It
platformじゃないPlaiadesに入ってるOpenExternalというのが見つからないので、代わりに。
一応更新サイトがあるのでこれにした。
http://blog.ozacc.com/archives/001549.html
Eclipseの設定
- エディタの色設定
黒背景にしたいのでEclipseColorThemeから好きなの選ぶ。
一応自分で作ったやつ。http://eclipsecolorthemes.org/?view=theme&id=12139
EPFファイルでダウンロードして、Eclipeseの[ファイル]-[インポート]-[設定]で取り込む。
- Javaのエディタ関連の設定
設定ウィンドウの[Java]から。
- [コンテンツ・アシスト]
- コンプリート機能により上書き
- [構文の色の指定]
- タスクタグ以外すべて太字解除
- [入力]
- 訂正位置で自動的に挿入 セミコロン
- [補完アクション]
- インポートの編成
gnulsもcolorlsもなく「ls --color」「ls -G」「set color」が使えない環境でlsを(無理やり)カラー化する
職場のサーバがSunOSなんだけどカラー化できるlsが入ってないので困った。
というわけで、"-F" オプションでファイル名のあとに付加される記号から、ディレクトリ/実行ファイル/シンボリックリンク/それ以外が判別できるのでそれをperl -peで置換して無理やり色を付けることにした。
ls -F | perl -pe "s/(\S+)\/( |\Z)/^[[01;34m\1^[[0m\/\2/g ; s/(\S+)\*( |\Z)/^[[01;32m\1^[[0m\*\2/g ; s/(\S+)( \-> |@)/^[[01;36m\1\2^[[0m/g"
"^["の部分はCtrl+V→Esc(またはCtrl+[)で入力。
色変えることを考えたりするとこんな感じになる?
set di=01;34 set ex=01;32 set ln=01;36 ls -F \!* | perl -pe "s/(\S+)\/( |\Z)/^[[${di}m\1^[[0m\/\2/g ; s/(\S+)\*( |\Z)/^[[${ex}m\1^[[0m\*\2/g ; s/(\S+)( \-> |@)/^[[${ln}m\1\2^[[0m/g"
これを.aliasとかに突っ込む。オプションも普通に使えるようになるはず。
eclipseの動的Webモジュールのバージョンを3.xから2.xに下げる方法
ちょっとつまづいたのでメモ。
java1.6設定で作った動的Webプロジェクトを、1.5を使うように変更しようとしたら、プロジェクト・ファセット設定画面で変更できなかった。
「動的Webプロジェクトをアンインストールできません」とかなんとか。
こういうときはプロジェクトの設定ファイルを直接弄ってしまえばいいっぽい。
eclipseを一旦終了して、
プロジェクトルート\.settings\org.eclipse.wst.common.project.facet.core.xml を編集する。
JREのバージョン設定
<installed facet="jst.java" version="5.0"/>
JavaSE6なら6.0に。
動的Webプロジェクトのバージョン設定
<installed facet="jst.web" version="2.5"/>
保存したらeclipseを起動して、プロジェクトのクリーン(と再ビルド)を行う。
MySQLのLIKE句の検索対象に文字列型と整数型を連結した場合の注意
今日知ったこと。
CREATE TABLE emp ( id INT AUTO_INCREMENT PRIMARY KEY , name VARCHAR(40) NOT NULL );
とかいうテーブルの時に、下のSELECT文のLIKE句はケース依存になる。
SELECT id, name, CONCAT(emp, id) FROM emp WHERE CONCAT(emp, id) LIKE '%a%'
A5M2などでWHERE句を外したSELECT文を実行してみると、CONCAT(emp, id)のカラムがバイナリで表示された。整数型と文字列型を結合したらこうなるのか?ってことでリファレンスよく読んだらちゃんと書いてあった。
http://dev.mysql.com/doc/refman/5.1/ja/string-functions.html
(一部抜粋)
CONCAT(str1,str2,...)
引数を連結した結果であるストリングを戻します。ひとつ以上の引数を持つ場合があります。すべての引数が非バイナリ ストリングである場合、結果は非バイナリ ストリングになります。引数がひとつでもバイナリ ストリングを含む場合は、結果はバイナリ ストリングになります。数値の引数はそれに等しいバイナリ ストリング形態に変換されます。それを避けたい場合は、次の例のように、明示的なタイプ キャストを使用することができます :
SELECT CONCAT(CAST(int_col AS CHAR), char_col);
キャストの他にも、
SELECT id, name, CONCAT(emp, id) FROM emp WHERE UPPER(CONCAT(emp, id)) LIKE UPPER('%a%')
とかでも回避できる。あんまりきれいじゃないですね。ちなみに、
SELECT id, name, CONCAT(emp, id) FROM emp WHERE CONCAT(emp, 1) '%a%'
これはバイナリ型にならずにケース非依存で検索できた。なぜ?