Javaでは、匿名クラスから、ローカル変数にアクセスする際には、final宣言することが必須となる。
public class Test {
public static void main(String[] args) throws InterruptedException {
int sum = 0;
Thread t = new Thread() {
@Override public void run() {
sum = sum + 1;
}
};
t.start();
t.join();
System.out.println("sum = " + sum);
}
}
これは、コンパイルできない。sumがfinal宣言されていないからだ。これはJavaのメモリモデルの仕様から来ている。ローカル変数はスレッドのプライベートなメモリ空間に置かれるので、別のスレッドからは直接アクセスできない。このため、匿名クラスからのアクセスにあたっては、匿名クラスのオブジェクトに値がコピーされる。コピー後に値が変更されても、もちろん反映されない。それじゃわけが分からなくなるから、finalを必須にしようというわけだ。でも、もちろんfinal付けたら、今度は、sum = sum + 1なんてことはできなくなる。でも、これはScalaでは出来るんだよね。
import System.out
object Test {
def main(args: Array[String]) {
@volatile var sum = 0
def bar() {
sum = sum + 1
}
val t = new Thread() {override def run() {sum = sum + 1}}
t.start()
t.join()
System.out.println("sum = " + sum)
}
}
なんで? と思ったら、この場合は、IntRefというクラスのオブジェクトがsumの値を保持するようなコードが吐かれる。なので、@volatileも必要だ。ローカル変数に@volatileなわけですよ。Javaでも苦しまぎれに、こんなことならできる。
public class Test {
public static void main(String[] args) throws InterruptedException {
final int[] sum = {0};
Thread t = new Thread() {
@Override public void run() {
sum[0] = sum[0] + 1;
}
};
t.start();
t.join();
System.out.println("sum = " + sum[0]);
}
}
でも、これってスレッド安全性の観点からは、同期化されていないからマズイよね。しかしながらJavaの場合はローカル変数にvolatileは付けられないから、マルチスレッドで使用するなら、synchronizedで囲まないといけないことになるな。
Ubuntu 8.04は、どうもキーボードまわりの挙動がおかしい。Emacsで、ファイルの先頭に飛ぶ時は、Shift + Alt + <を押すんだけど、これが入らない。初期状態では、キーボードのレイアウトオプションで。Shlft + Altがlayout switchに割り当てられているので、このチェックを外してやればいいんだけど、これが再起動ごとに元に戻るようで、毎度毎度、このオプションを変更しないといけなくて、かなりつらい。せめて、CUIでできないもんだろうか。
P.S. ここにあった情報をもとに、こんなスクリプトを作った。
#!/bin/bash gconftool-2 -s /desktop/gnome/peripherals/keyboard/kbd/options -t list --list-type=string "[]" gconftool-2 -s /desktop/gnome/peripherals/keyboard/kbd/options -t list --list-type=string "`echo -e "[grp\tgrp:lwin_toggle]"`"
自分のキーボードには、Winキーは無いので、これでレイアウトチェンジを抑制。元のドキュメントにはセッションの設定に入れれば自動で実行されるとあるんで、システム=>設定=>セッションで追加してみたんだけど、ダメだった。.bashrcに入れておくとok(シェル起動の度に実行されちゃうけど)。タイミングの問題なんだろうか。
Scalaはダックタイピング的なことができる。
import Console._
case class Foo {
def hello() {
println("Foo hello.")
}
}
case class Bar {
def hello() {
println("Bar hello.")
}
}
object Test {
def test(o: {def hello()}) {
o.hello()
}
def main(args: Array[String]) {
test(Foo())
test(Bar())
}
}
FooとBarは、同じ継承ツリーには無いけど、Compound typeである{def hello()}に適合する(hello()というメソッドがありさえすれば良い)ので、test()に渡すことができる。もちろん、これってバイトコードを見るとリフレクションになるから、遅いけど。
これの面白いところは、いわゆる静的型付けの無いダックタイピングと違って、型チェックされるところだ。意図的にFooのhello()をタイプミスしてみると、
case class Foo {
def hell() {
println("Foo hello.")
}
}
ちゃんとコンパイル時に、エラー検出されるのだ。
shanai@shanai-laptop:/tmp$ scalac test.scala
test.scala:21: error: type mismatch;
found : Foo
required: AnyRef{def hello(): Unit}
test(Foo())
^
one error found
静的型付け大好き人間にとっては、これは結構シビれる。
CPUベンチのとんでもない差は何? 整数演算性能が2倍になってるんですけど。
というか、こういうのってシステムコール呼び出しなんて計ってないよね。多分dhrystoneっぽい感じの演算性能だと思うんだけど、OS関係無いじゃん。使われてるHDBENCH cloneを見ると、ソースからmakeするみたいだから、ディストロに付属しているコンパイラの性能差ってことか。にしても、えらい違いだな。
ちゃんとバージョンアップで、メモリ使用量が減って、速くなっている。こういうのが本来のOSの進化であるはずだよな。
システム => 設定 => キーボードで、レイアウトタブを選ぶと、なぜか私の環境では、レイアウトが2つ登録されていたので、1つ削除して、デフォルトのチェックを入れた。
すると、ctrl caps入れ替えで、caps LEDが点灯/消灯する問題も、VMWare使用中にShift alt ctrlが効かなくなる件も起きなくなったようだ(少なくとも今日1日、起きていない)。
と思ったら、VMWareの問題は、さっきまた起きた。ダメか。
marsさんとこにあった「Genericsの奥深さをちょっと覗いてみたよ」が、おもしろい。
Generic methodの型パラメータを、throws節にバインドできるとは知らなかった。肝は、
static void rethrowAny(Throwable t) {
RethrowDemo.<RuntimeException>rethrowInternal(t);
}
@SuppressWarnings("unchecked")
static <T extends Throwable>: void rethrowInternal(Throwable t) throws T {
throw (T) t;
}
かな。チェック例外への対処はコンパイル時に行われるから、Genericsを使って「これはRuntimeExceptionだからね〜」とだまして、InterruptedExceptionを渡す。throw (T) t;のキャストは、所詮はイレージャだから、コンパイル時のチェックのみで、実行時には消えてなくなってしまい、別にcheckcastされるわけではない。かくして、throws節無しで、チェック例外がスローできてしまうわけだ。
バイトコードを見ると、instanceof使っているんだけど、ということは、複数のcase classが継承関係にある場合、親の方が先のcaseに書かれると、マズイんじゃないだろうか。早速テスト。
abstract class Tree case class Child extends Tree case class Child2 extends Child
shanai@shanai-desktop:~/scala$ scalac CaseClass.scala
CaseClass.scala:3 error: implementation restriction: case class Child2 and case class Child cannot be combined in one object
case class Child2 extends Child
^
one error found
なるほど、出来ないようになっているわけですか。caseクラス同士は、継承関係にあってはいけないようですな。
ScalaByExampleで、末尾再帰にしてみろとのことだったので、してみた。
def factorial2(n: int) : int = {
factorialIter(1, n)
}
def factorialIter(sum: int, n: int) : int = {
if (n == 1) sum else factorialIter(sum * n, n - 1)
}
で、バイトコードを見てみる。
public int factorialIter(int, int); Code: Stack=3, Locals=3, Args_size=3 0: iload_2 1: iconst_1 2: if_icmpeq 16 5: iload_1 6: iload_2 7: imul 8: iload_2 9: iconst_1 10: isub 11: istore_2 12: istore_1 13: goto 0 16: iload_1 17: ireturn
おぉ、ループになってますな。
P.S. Scala的には、こうかな。
def factorial2(n: int) : int = {
def factorialIter(sum: int, n: int) : int = {
if (n == 1) sum else factorialIter(sum * n, n - 1)
}
factorialIter(1, n)
}
値段がネックと見ているようだけど、どうだろう。値段的には元がとれる話だと思うんだけど。それより実際に使ってみて不満なのは、つけてすぐが暗いこと(大分改善されたけど、まだまだ)、不良品があるとショックなこと(長寿命品だからね。これまで10個くらい買ったけど、1個は不良品で1か月ほどで壊れた)、器具を痛めることがあること(うちのランプシェードは塗装が、ひび割れてしまった。どうやら紫外線が多いようで、樹脂を痛めるようだ)。
なんか駒鳥が、雛鳥を回って平等に餌を与える、みたいな説明を昔聞いた覚えがあるんだけど、Wikipediaによると、全然違うじゃん。嘆願書の署名を円状に書くっていうの、日本の歴史の教科書でも見た覚えがあるな。
VMWareの中で動いているゲストOSは問題無いんだけど、外のアプリケーションでことごとくshift, alt, ctrlが使えなくなる。
この問題みたいだ。まだ根本解決は見つかっていないけど、自分の環境では、ここに書いてあるsetxkbmapの実行で、回避できている。あと、Ctrl+Alt+Enterによる全画面表示をしなければ、大丈夫のようだ。
JJUG 2008 Springで取り上げた、Swing Application Frameworkの話を公開しました。サンプルやNetBeansの操作動画も一緒に掲載しましたので、当日参加できなかった方でも、読むだけで内容は大体分かるかと思います。
Linux AMD64版は、Eclipse上でのprofileができなかった。スタンドアロンでは問題無し。CPUプロファイルで行番号が出ないのは仕様なんだろうか。まぁ、F7でのジャンプは機能したから、大きな問題は無いんだけど。NetBeansは6.0までの対応みただけど、6.1で動くかどうか、明日試してみよう。
P.S. NetBeans6.1はダメだった。
なぜかdsaだとつながらず。rsaに変更したらつながった。
朝、机の上の置いておいたHDDが落とされているのを発見。昇天されていました。停止状態だから、意外と平気かと思ったけど、異音がしてシンドルモータが回らない状態。打ちどころが悪かった模様。教訓:机の端にHDDを置いてはいけない。
ちょっとOCして3.8GHz駆動。メモリも8GBに増設した。
syslogを見ると、
May 2 21:37:11 shanai-laptop automount[6860]: >> missing codepage or helper program, or other error May 2 21:37:11 shanai-laptop automount[6860]: >> (for several filesystems (e.g. nfs, cifs) you might May 2 21:37:11 shanai-laptop automount[6860]: >> need a /sbin/mount.helper program) May 2 21:37:11 shanai-laptop automount[6860]: >> In some cases useful info is found in syslog - try May 2 21:37:11 shanai-laptop automount[6860]: >> dmesg | tail or so
sudo apt-get install nfs-commonで解決。入ってないのかよ。nfsって、もう一般的じゃないんだろうか。
LANG=C xdg-user-dirs-gtk-update
とりあえずTab Mix Plusはベータが動くので、自分が使っている拡張で動作しないのは、Google Browser Syncだけだった。
正直なところ、最近ブックマークって固定的なんで(ブログはブログリーダだし、それ以外はGoogle Notebookに記録)、ブックマーク同期自体は、それほど重要性が無いんだけど、パスワードがね。全部Google Browser Syncが覚えてくれているから、やっぱり使えないと面倒なこと、この上ない。
GMailFSでファイルを送っていたら、アク禁くらってしまった。送っていたのは、せいぜい100kBくらいのファイルが10数個。大きなファイルを何度も送るとアク禁になると聞いていたので、注意はしていたんだけど、まさか、こんな少量でもダメとは。まぁ24時間で自動復旧するんで、大きな問題はないんだけど。








