2011/09/23

"Strings in switch" in Java 7 (JSR 334)

Java 7で導入されたJSR 334には、「Strings in switch」がありますが、switch構文でString型も扱えるようになっています。それがどのようにコンパイルされるのかを調べてみました。



package a;
public class E {
  public static int a(String s){
    switch(s){
    case "a":
      return 1;
    case "b":
      return 2;
    default:
      return 3;
    }
  }
}



上記ソースをjavacでコンパイルして、javap -verboseしてみました。


Classfile /E:/tmp/java/java7/bin/a/E.class
  Last modified 2011/09/23; size 491 bytes
  MD5 checksum 525f1ebe51742f599543582cb206c23c
  Compiled from "E.java"
public class a.E
  SourceFile: "E.java"
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER

Constant pool:
   #1 = Methodref          #7.#18         //  java/lang/Object."<init>":()V
   #2 = Methodref          #19.#20        //  java/lang/String.hashCode:()I
   #3 = String             #12            //  a
   #4 = Methodref          #19.#21        //  java/lang/String.equals:(Ljava/lang/Object;)Z
   #5 = String             #22            //  b
   #6 = Class              #23            //  a/E
   #7 = Class              #24            //  java/lang/Object
   #8 = Utf8               <init>
   #9 = Utf8               ()V
  #10 = Utf8               Code
  #11 = Utf8               LineNumberTable
  #12 = Utf8               a
  #13 = Utf8               (Ljava/lang/String;)I
  #14 = Utf8               StackMapTable
  #15 = Class              #25            //  java/lang/String
  #16 = Utf8               SourceFile
  #17 = Utf8               E.java
  #18 = NameAndType        #8:#9          //  "<init>":()V
  #19 = Class              #25            //  java/lang/String
  #20 = NameAndType        #26:#27        //  hashCode:()I
  #21 = NameAndType        #28:#29        //  equals:(Ljava/lang/Object;)Z
  #22 = Utf8               b
  #23 = Utf8               a/E
  #24 = Utf8               java/lang/Object
  #25 = Utf8               java/lang/String
  #26 = Utf8               hashCode
  #27 = Utf8               ()I
  #28 = Utf8               equals
  #29 = Utf8               (Ljava/lang/Object;)Z
{
  public a.E();
    flags: ACC_PUBLIC

    Code:
      stack=1, locals=1, args_size=1
         0: aload_0       
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return        
      LineNumberTable:
        line 3: 0

  public static int a(java.lang.String);
    flags: ACC_PUBLIC, ACC_STATIC

    Code:
      stack=2, locals=3, args_size=1
         0: aload_0       
         1: astore_1      
         2: iconst_m1     
         3: istore_2      
         4: aload_1       
         5: invokevirtual #2                  // Method java/lang/String.hashCode:()I
         8: lookupswitch  { // 2

                      97: 36

                      98: 50
                 default: 61
            }
        36: aload_1       
        37: ldc           #3                  // String a
        39: invokevirtual #4                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        42: ifeq          61
        45: iconst_0      
        46: istore_2      
        47: goto          61
        50: aload_1       
        51: ldc           #5                  // String b
        53: invokevirtual #4                  // Method java/lang/String.equals:(Ljava/lang/Object;)Z
        56: ifeq          61
        59: iconst_1      
        60: istore_2      
        61: iload_2       
        62: lookupswitch  { // 2

                       0: 88

                       1: 90
                 default: 92
            }
        88: iconst_1      
        89: ireturn       
        90: iconst_2      
        91: ireturn       
        92: iconst_3      
        93: ireturn       
      LineNumberTable:
        line 5: 0
        line 7: 88
        line 9: 90
        line 11: 92
      StackMapTable: number_of_entries = 6
           frame_type = 253 /* append */
             offset_delta = 36
        locals = [ class java/lang/String, int ]
           frame_type = 13 /* same */
           frame_type = 10 /* same */
           frame_type = 26 /* same */
           frame_type = 1 /* same */
           frame_type = 1 /* same */

}



案の定ハッシュ値を使っていて、次のような流れで処理していることが判ります。

  1. ローカル変数2を-1で初期化し(60~61行目)、
  2. 引数のString型のハッシュ値を取得し(63行目)、
  3. 1つ目のlookupswitchでハッシュ値が同値なら、さらにString.equals()で評価し(64~84行目)、
  4. 評価結果をローカル変数2に数値を代入して(0または1)(75、76、82、83行目)、
  5. 2つ目のlookupswitchで、ローカル変数2の値に応じた処理を行う(84~97行目)

2つのlookupswitchを使って条件分岐しているのは意外でした。

2011/09/19

娘の減圧症について

■はじめに
我が家では夫婦ともダイバーで経験本数は共に200本以上で、そこそこの経験と知識を有しています。
そして、娘(10歳)の希望で、PADIのジュニアオープンウォーターダイバーの講習を受けさせました。
結果、PADIの基準以内でダイビングしたにも関わらず、娘は減圧症を起こしました。
以下、減圧症を起こした経緯と治療内容を記述します。

■海洋実習のログ(1日目)
学科試験に合格し、2011/09/10(土)に神奈川県小田原市石橋で海洋実習を受けました。
以下、ダイビングログですが、PADIの基準に収まる正しいダイビングが行われていたようです。

◆1本目
気温32℃、水温25~27℃
最大水深12m、平均水深8m
潜水時間30分、エア消費190→70気圧
◆休憩
72分
◆2本目
気温32℃、水温26~27℃
最大水深12m、平均水深5m
潜水時間36分、エア消費190→50気圧
最後に水深3mで6分間遊ぶ(安全停止)


■海洋実習終了直後(1日目)
2本目終了後、2時間後に耳の激痛を訴え、救急車で東海大学医学部付属病院に運ばれ、「急性中耳炎」と診断されました。
またそのころから足のシビレと痛みを訴え始めたため、救急科の医師さんより「減圧症」を疑われたのですが、上記ログを見せると「減圧症は考えにくいので様子を見よう」となり、そのまま帰宅しました。

■三保耳鼻咽喉科で受診(2日目)
◆2011/09/11(日)
潜水医学に詳しいという三保耳鼻咽喉科で、耳を診てもらいました。
診断結果は以下です。
  • 鼻の細菌が耳抜きにより、中耳に押し込まれ、急性中耳炎になったと考えられる。全治約1週間。
  • 急性中耳炎の後に、滲出性中耳炎(聞こえは悪いけど痛くない状態)が続き、全治3~4週間。
  • 滲出性中耳炎は、潜水医学を知らない近所の耳鼻科でも治療可能。
  • 耳抜きが悪かった時に起こるような内出血(中耳気圧外傷)は見当たらず、耳抜きはうまくできていた模様。
当時、足のシビレと痛みもあったのですが、様子見でよいだろうと親は考え、その先生に相談しませんでした。後になってみると、その時に相談すればよかったと後悔しています。

■みなと赤十字病院(3~8日目)

◆2011/09/12(月)
娘が足のシビレと痛みを強く訴えるようになり、学校にも歩いて行きたがらない様子だったので、みなと赤十字病院の小児科で診てもらいました。
触診で異常が見当たらず。重いタンクを背負ったことによる脊椎の損傷か?とのこと。

◆2011/09/13(火)
MRIで脊椎周りを撮影。

◆2011/09/16(金) 午前
MRIの結果、異常は見当たらず。救急科に回され、受診するも不明。神経内科を呼んでも不明。
救急科より、潜水医学に詳しい東海大学医学部付属病院に問い合わせていただきました。

  • 減圧症は確定診断ができない(レントゲンや触診などでは減圧症を特定できない)ので、特殊な治療を受けて経過を見るしかない
  • 急性中耳炎よりも減圧症の治療を優先するべき
上記理由により、高圧酸素治療(高気圧酸素療法)の設備を備えている近くの横浜労災病院に行くように勧められました。
もし地理的に東海大学医学部付属病院に近ければ、そこを勧められていたと思われます。

■横浜労災病院(7日後~8日後)
◆2011/09/16(金) 午後
紹介状を持参して、横浜労災病院に移動し、救急科で受診しました。
やはり触診で異常が見当たらず減圧症を疑うしかないとのことで、高気圧酸素治療を受けるために、耳鼻科で両耳の鼓膜切開の手術を受けました。
鼓膜切開は10分間の麻酔の後に、穴をあける程度の簡単な手術ですが、数日~1週間くらい後に鼓膜は塞がるとのことです。
その後、神経内科の先生による触診により「減圧症の疑いが非常に濃厚」と初めて断言されました。

また高圧酸素治療の技師より「潜水水深や時間には問題は見られないが、タンクの空気の消費量が多すぎるのが気になる」という指摘も受けました。

◆2011/09/16(金) 夜
19:30~1:30の6時間、高圧酸素治療を受けました。
チャンバーといわれる特殊な設備の中に入って、1.8気圧に上げて20分間、0.9気圧に下げた状態で5分間酸素呼吸というのを何セットも繰り返す治療です。
治療後、娘に聞いてみると、「足のシビレと痛みを10段階で表すなら、治療前後で10→1に減った」とのことで、効果はありました。
ただ、深夜に治療が完了し、娘も眠い状態なので、翌朝に来るように言われました。

◆2011/09/17(土) 午前
当日は娘の小学校の運動会だったのですが、欠席し、横浜労災病院に向かいました。
神経内科の先生の問診および触診により「治療の効果は見られる。少し痛みが残っているが自然治癒されるだろう。でも再発防止のために1回高圧酸素治療を受けてください」と。

◆2011/09/17(土) 午後
2回目の高圧酸素治療を受け、治療後はすっかりシビレも痛みも消え去ったようです。
治療は完了の方向だが、念のために翌水曜日に再来院してくださいとのこと。

■高圧酸素治療(高気圧酸素療法)
高圧酸素治療は特に痛みなどを伴う治療ではありませんが、閉所に閉じ籠る治療なので、閉所恐怖症などを抱える方は治療を受けられないようです。

突発性難聴の患者さんの治療にも高圧酸素治療がよく使われるようです。

突発性難聴などの場合、高圧酸素療法による治療は2時間前後ですが、減圧症の場合は、4~6時間前後と長くなります。
病院関係者の話では、通常、減圧症の患者は「エア切れによる緊急浮上」「ダイビング終了後の安全停止ミス」「ダイビング後の高所移動」など明らかな理由があり、すぐ高圧酸素治療を受けるとのことです。

しかし今回の娘の場合はそのような明確な理由がなく、減圧症の疑いが強まるまでに時間を要してしまいました。症状が軽かったとはいえ、早期に高圧酸素治療を受ければ1回で済んだだろうとのことでした。
なお高圧酸素治療は保険が効きますが、それでも1回で25,000円もします。
ちなみに神奈川県で、高圧酸素治療の設備(チャンバー)を有する病院は以下です。
  • 東海大学医学部付属病院
  • 横浜労災病院
  • 北里病院

■あとがき
減圧症にかかった後は、次の点に留意する必要があるとのことです。
  • 3ヶ月間は、呼吸が乱れるような激しい運動は禁止。高所移動も禁止。
  • 6カ月~1年間は、ダイビングは見合わせること。
幸運にも娘は、急性中耳炎と減圧症を同時に患いながらも、海に対する情熱が冷めていないようで、親としてはその点では安堵しています。再発防止のために、現在、ダイビングのインストラクターおよびPADIにもエスカレートして相談しているところです。
最後になりますが、緊急の手話通訳派遣依頼にも応えてくださった横浜市聴覚障害者情報提供施設の方々、手話通訳の方々、丁寧にご説明してくださった医療関係者の皆さま、感謝の気持ちでいっぱいです。ありがとうございました。

2011/09/04

聴覚障害教育これまでとこれから

私は乳児~高校時代まで(2つの異なる)ろう学校で育ち、聾学校の先生を目指した時期があって、中学~高校の教員免許状を持っています。

結局、就職活動を始める直前にソフトウェア開発が本当に好きだという自分に目覚めて教員にはならなかったのですが、今でもろう教育の状況はどうなってるんだろう、ろう学校の教員になった何人かの知人・友人たちは元気で頑張っているだろうかと、ふと気になることがあります。

また難聴児を持つ親御さんからも相談を受けることがあるのですが、たいていはうまくアドバイスできないんですよね。それで少しでも何か知っておきたいということで、知人に次の本を紹介してもらいました。

聴覚障害教育これまでとこれから―コミュニケーション論争・9歳の壁・障害認識を中心に
本の内容は知人のブログ「聴覚障害教育これまでとこれから」でよくまとめておられますが、私も読書して面白かったです。著者の脇中さんのご姿勢にも好感を抱き、特にBICSとCALPは勉強になりました。私はろう教育も含め何もかも詳しくないのですが、素人なりに感想を述べます。

脇中さんのように率直で、優れた自己表現をされる教員が、昔の聴覚口話法に疑問を持たれつつ、「日本手話と対応手話を区別する必要性を強く感じていない」としているところに「惜しいなぁ!」と感じました。私なら「日本手話と対応手話をしっかり区別し、双方の観点からのアプローチを考える」としたいなぁと。

断続的な引用になりますが、次の文章がありました(カッコ内は私の補足)。

音韻意識の形成のために2つの手話を包含する新しい方向性の追求が必要であると考えます。

日本語で考える習慣のない子どもは、習慣のある子どもと比べると、日本語の定着が難しいと思われるので、手話の早期導入を図りながらも、「(日本語の)音韻意識」の形成や定着に留意する必要があると考えます。

上記の考え方には、やはり違和感や疑問が湧き出てくるのを禁じ得ません。なぜなら、私の知る限り、日本語で考える習慣(日本語の音韻意識)が弱い子どもは、中・高校生以降でもその習慣が向上した例を見たことがないからです。逆に言うと、日本語の音韻意識が優れている子どもは、幼い時から優れていました。

今度は、自分を例に挙げます。幼い時期から日本語が正しく書けていて教育関係者などを驚かせたものですが、実は大学入学前までの私の自己表現力は-目を覆いたくなるほどではないが-ひどいものでした。こんな私でも、大学入学後に、このブログをご覧のように人並みの文章が書けるようになり、両親を驚かせたのも事実です。読書も作文も好きではない私が、なぜここまで改善できたのでしょうか。大学入学を機に、否応(いやおう)でも、日本語または手話を使って人に説明しなければならない機会が増え、推敲する時間が増えたからではないかと思うのです。

一方、学生時代も含め、日本語を含めた「学力」が私と同程度か少し劣っていても、私が足元に及ばないくらい優れた自己表現ができる方々が結構いらっしゃるのです!また日本語がマジョリティ言語とはいえ、日本語が苦手でもご本人の適応力によって、同僚が手話を覚えてくれ、楽しい職場生活を送られた例もあるのです。そのような方々のことも考えなければならないように思います。

以上、回り道をしましたが、

日本手話を用いた教育の場面において、日本語のCALPが育つかどうかを脇中さんは懸念されています。でも逆に、対応手話を使って音韻意識を形成させる試みも、多くの子どもにとっては上達する可能性がすこぶる低いのではないかと、私の経験から来る直感が感じています。(直感でゴメンなさい・・・)

つまり、日本語にしろ手話にしろ自己表現力の切磋琢磨は、ご本人の思考、推敲、あるいは、練習の蓄積によるものがあると思うのです。すなわち考えたり感じたりする力です。

子どもに合わせた教育を実践できるのが望ましいのですが、現実的に学校のようなクラス制では個別教育ができる部分があまりないだろうと思います。

考えたり感じたりする力の蓄積を、日本手話で育む子どもがいれば対応手話で育む子どももいると思うのですが、うまくいかなかった場合の人格形成のリスクを考えると、やはり後者の方が懸念されるべきではないかと警鐘を鳴らし続けていきたいです。