Java7の実験。

正式リリースも近いのでいじってみた。
文法上の変更や新しい記法などを中心に、いざソースを読む際にちょっと困ったりしないような視点でみてみました。

AutoCloseable

どうでもいいけど、Closableじゃないんだね。
http://oxforddictionaries.com/noresults?dictionaryVersion=region-uk&isWritersAndEditors=true&noresults=true&page=1&pageSize=20&q=closeable&searchUri=All&sort=alpha&type=dictionarysearch


って該当なしにされるんだけど・・・まぁいいか。
コンパイルは対応していなくてもコードアシストレベルではeclipseが現状でも頑張ってくれるし。



匿名なのでわかりにくいかもしれないけど・・・
try(ここで初期化) {
} catch(Exception e) {
}


といった文法
catchは省略不可っぽい。
(匿名インナークラスの場合throws宣言なしでも不可。インナークラスなんかをちゃんと定義してやれば可能)

   try (
       AutoCloseable ac1 = new AutoCloseable() {

         @Override
         public void close() throws Exception {
           System.out.println("ac1 close");
         }
       };
     )  {

        //処理

   } catch(Exception e) {
     System.out.println("catch");
   } finally {
     System.out.println("try finally");
   }

結果

ac1 close
try finally


どうやら、finally前でcloseされるようだ。
というわけで、finallyでそのリソースは使用できないようですね。
※catchや、finallyだとそもそもスコープ外。場合によっては中でtry-catchブロックが必要になることもあるかと。


以下のように外側で変数定義だけ済ましておくなんてのはコンパイルエラー

   AutoCloseable ac1 = null;
   try (ac1 = new AutoCloseable() {

     @Override
     public void close() throws Exception {
       System.out.println("ac1 close");
     }
   };)  {
   } catch(Exception e) {
     System.out.println("catch");
   } finally {
     System.out.println("try finally");
   }

ちなみに、以下のようにtryの中での変数への代入に関してもコンパイルエラー
エラー: 自動クローズ可能なリソースac1に値を代入することはできません

   try (AutoCloseable ac1 = null)  {
     ac1 = new AutoCloseable() {
       @Override
       public void close() throws Exception {
         System.out.println("ac1 close");
       }
     };
   } catch(Exception e) {
     System.out.println("catch");
   } finally {
     System.out.println("try finally");
   }


複数のリソース初期化にも対応

   try (
       AutoCloseable ac1 = new AutoCloseable() {

         @Override
         public void close() throws Exception {
           System.out.println("ac1 close");
         }
       };
       AutoCloseable ac2 = new AutoCloseable() {

         @Override
         public void close() throws Exception {
           System.out.println("ac2 close");
         }
       };
     )  {
   } catch (Exception e) {
     e.printStackTrace();
   } finally {
     System.out.println("try finally");
   }

結果

ac2 close
ac1 close
try finally

だそうで、開いたのと逆に閉じていくという鉄則どおりの挙動ですね。




んじゃまぁ、例外が発生した場合どうなるのか?
両方とも例外が発生した場合

   try (
       AutoCloseable ac1 = new AutoCloseable() {

         @Override
         public void close() throws Exception {
           System.out.println("ac1 close");
           throw new Exception("close exception");
         }
       };
       AutoCloseable ac2 = new AutoCloseable() {

         @Override
         public void close() throws Exception {
           System.out.println("ac2 close");
           throw new Exception("close exception");
         }
       };
     )  {
   } catch (Exception e) {
     e.printStackTrace();
   } finally {
     System.out.println("try finally");
   }
ac2 close
ac1 close
java.lang.Exception: close exception
       at java7.autoclose.AutoCloseMain$2.close(AutoCloseMain.java:20)
       at java7.autoclose.AutoCloseMain.main(AutoCloseMain.java:24)
       Suppressed: java.lang.Exception: close exception
               at java7.autoclose.AutoCloseMain$1.close(AutoCloseMain.java:12)
               ... 1 more

と、Suppressedが追加されていますね。
最初を主として、その後はsuppressedとして追加されていくようです。
例外が発生しても残りのclose処理はちゃんと実行されていきます。

ThrowableにはaddSuppressedと、getSuppressedが追加されています(protectedのコンストラクタも)
   try (
       AutoCloseable ac1 = new AutoCloseable() {

         @Override
         public void close() throws Exception {
           System.out.println("ac1 close");
           throw new Exception("close exception");
         }
       };
       AutoCloseable ac2 = new AutoCloseable() {

         @Override
         public void close() throws Exception {
           System.out.println("ac2 close");
           throw new Exception("close exception");
         }
       };
     )  {
   } catch (Exception e) {
     e.printStackTrace();
     System.out.println("ここからgetSuppressed");
     Throwable[] suppressed = e.getSuppressed();
     for (Throwable throwable : suppressed) {
       throwable.printStackTrace();
     }
   } finally {
     System.out.println("try finally");
   }
ac2 close
ac1 close
java.lang.Exception: close exception
       at java7.autoclose.AutoCloseMain$2.close(AutoCloseMain.java:20)
       at java7.autoclose.AutoCloseMain.main(AutoCloseMain.java:24)
       Suppressed: java.lang.Exception: close exception
               at java7.autoclose.AutoCloseMain$1.close(AutoCloseMain.java:12)
               ... 1 more
ここからgetSuppressed
java.lang.Exception: close exception
       at java7.autoclose.AutoCloseMain$1.close(AutoCloseMain.java:12)
       at java7.autoclose.AutoCloseMain.main(AutoCloseMain.java:24)
try finally

マルチキャッチ

マルチキャッチは

} catch (IOException | AssertionError e) {

まさかのパイプ。変数名は最後のみというのがポイント。
てっきりセミコロン区切だと思っていたのに・・・

数値表現

//数値表現に_を入れて、区切を意識させられる
BigDecimal currency = new BigDecimal(123_456_789);
System.out.println(currency);
//123456789

//2進を16進の0xのように、0bで表現可能
int bit = 0b10101;
System.out.println(bit);
//21

ジェネリクスまわり

型推論の進化
基本的には右辺を書いてからアシストで左辺を定義ってコーディングなのでちょっと困るような・・・・

List<String> l = new ArrayList<>();
l.add("test1");
l.add("test2");
for (String string : l) {
        System.out.println(string);
}

JDBC4.1

さて・・・今まで見ないことにされていたRowSetだけど・・・
やはり今回も気にしない方向で、AutoCloseable対応位のつもりでいればいいかも?
http://download.java.net/jdk7/docs/technotes/guides/jdbc/jdbc_41.html

その他

後は細かいクラスやNIOやスレッドまわりは適宜。
switchでStringってのも記述に関しては新しくないので問題ないと思うので
きっとこのあたりだけ押さえておけばひとまずは困らないのかなぁ・・・なんて。

LED常夜灯

小さい子供がいると、常夜灯つけっぱなしなわけですが、
そももそこいつがすぐ切れる(気がする)わけで、どうにかしたい。
と。


そんなこんなでいっつもLEDのを買って打ちのめされるわけです。
1灯はごみだし、なら3灯!ってこれまた全然お話にならないわけですが、
ついに本命というべき10ルーメンが出ました。


早速試したところ、明るいです。
少なくとも、「光っている」ではなく、部屋を照らしているというパフォーマンスはあります。
感じとしては、ナツメより、若干暗く、でも色合いが白っぽいため、思いのほか明るく感じられます。
これなら十分実用に耐えるパフォーマンスです。というわけで紹介。



娘の皮疹

下の娘は、皮疹で、ほっぺとかがすぐぐずぐずになっちゃって、
結構かわいそうな感じで結局病院でステロイド系の薬を塗って一気に直して・・・
でもまぁ結局また出ちゃう。みたいな感じでした。


まぁ1歳になればよくなるよ〜とは言われるんですが、
大体において気にはなっちゃうもんですよね。こういうのって。


それで色々ボディーソープとかも低刺激だったりと色々試していたんですが、
「アトピコ」がいい。という情報を仕入れて嫁が買ってきたのが、「アトピタ」でした。

おい!ちがうじゃねぇか!?って物だったんですが、
まぁ頃になるともはやどれ使っても一緒だなって思いと、しばらく使わないとわからんし・・・
って事でずっと使ってました。結果は推して知るべし。


んでようやく先日に「アトピコ」に変えてみたのですが、
これがまぁ〜ずいぶんと違うわけですよ。
そりゃね薬塗ったりするほどの効果はないですが、それでも他のものたちと比べると大違い。


どうせ一緒だよなんて思わずにすぐ買いなおしておくべきでした。
というわけでおすすめです。


まぁそれぞれを使用していたときに比べて、どんどん月齢があがってたってのも原因かもしれないですけどね。



アトピコ スキンケアシャンプー 400ml
大島椿
売り上げランキング: 7968

mockitoでカバレッジ

さて、powermockと併用でstaticメソッドも試験でき、privateやらfinalなんかも試験できるようになる。
ということで、魔のカバレッジ100%を目指せ指令が出てもおかしくない昨今。


ところでカバレッジ計測できるんですかね?
という疑問。

Limy(サイト落ちてる?)

日本語プロジェクト http://sourceforge.jp/projects/sfnet_limy-eclipse/
から引っ張ってきて、
ant.batにパス通してeclipse立ち上げなおせばなんとかいけた

EclEmma

http://www.eclemma.org/

でもちゃんとできるっぽい。


ちなみに、privateメソッドなんてのは試験をしなくてもいい程度のメソッドだ。
って考えなんですけど、どうなんですかね。世間的には。
※まぁカバレッジ100%って・・・なんていいだす人は別としてですけど。

mockito(とpowermock)でstaticメソッドの試験

そんなこんなでかれこれ1年半位後回しにしちゃっていた、クラスメソッドのテストについて。
powermockを利用してテストする事とします。
http://code.google.com/p/powermock/


以前のサンプル
Mockitoの実験(モックを用いた単体テスト) - mokkouyou2001の日記


まぁ、題材は大体おんなじですというか流用です。


新しい部分としては、
計算結果に通貨記号を付与して返すメソッド追加。
(通貨記号はなぜかDaoのクラスメソッドとして実装されます)

package logic;

import dao.SettingsDao;

public class CalcLogic {
 /**
  * 設定の税率で金額を求め、送料を付与して返す。
  *
  * @param price
  *            金額
  * @return 合計金額
  */
 public int calcPrice(int price) {
   // インラインでインスタンスを取得しているのでMoc化できない。
   // SettingsDao settingsDao = new SettingsDao();
   // メソッド化

   SettingsDao settingsDao = getInstance();
   return (int) Math.floor(price * (1 + settingsDao.getTaxRate()))
       + settingsDao.getTransportation();
 }

 /**
  * 設定の税率で金額を求め、送料を含んだ料金に関して、文字列表現を返す(通貨記号を付与する)。
  *
  * @param price
  *            金額
  * @return 合計金額(通貨記号付きの文字列表現)
  */
 public String calcDispPrice(int price) {
   return calcPrice(price) + SettingsDao.getCurrencySign();
 }

 /**
  * 設定情報取得Daoを返却する。
  *
  * @return
  */
 protected SettingsDao getInstance() {
   return new SettingsDao();
 }
}


通貨記号を返すクラスメソッド追加
ここにあるのは何で?というのは気にしない。きっと一度だけ起動時に初期化みたいなことがされるんじゃないかな。ということで。

package dao;

public class SettingsDao {
 /**
  * DBより税率を取得して返す。
  *
  * @return 税率
  */
 public double getTaxRate() {
   return 0.5;
 }

 /**
  * DBより送料を取得して返す。
  *
  * @return 送料
  */
 public int getTransportation() {
   return 500;
 }

 /**
  * 通貨記号を返す。
  * @return 通貨記号
  */
 public static String getCurrencySign() {
   return "円";
 }
}

そんでもって、テストはこんな感じ
以前のメソッドのテストも残っています。

package logic;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

import dao.SettingsDao;
//PowerMock利用
@RunWith(PowerMockRunner.class)
//SettingsDaoに対して利用
@PrepareForTest(SettingsDao.class)
public class CalcLogicMockItTest {
 @Test
 public void testTestCalcPrice() {
   CalcLogic logic = spy(new CalcLogic());
   SettingsDao dao = spy(new SettingsDao());

   when(dao.getTaxRate()).thenReturn(0.03);
   when(dao.getTransportation()).thenReturn(200);

   when(logic.getInstance()).thenReturn(dao);
   int calcPrice = logic.calcPrice(200);
   assertEquals(406, calcPrice);
 }
 @Test
 public void testTestCalcPriceStatic() {
   CalcLogic logic = spy(new CalcLogic());

   //SettingsDaoに対して利用する宣言
   //全メソッドに対してスタブを利用する宣言(設定を忘れると呼び出し結果でnullが返ったりする)
   //ミスで呼ばれたりすると困るような重要なメソッドがあるような場合には保険になるかも
   PowerMockito.mockStatic(SettingsDao.class);
   //設定をしたメソッドにだけスタブを利用する宣言
   //明示的に出来て便利だが、ミスで実メソッドが呼ばれて困る事があるかも
   //PowerMockito.spy(SettingsDao.class);

   when(SettingsDao.getCurrencySign()).thenReturn(" JPY");

   when(logic.calcPrice(200)).thenReturn(2999);
   //特定の引数に意味が無いような場合、以下にしておくとどん引数でもという条件となる
   //when(logic.calcPrice(anyInt())).thenReturn(2999);

   String calcPrice = logic.calcDispPrice(200);

   assertEquals("2999 JPY", calcPrice);

   //以下モックに対する検証
   //getCurrencySignが2回呼ばれたことを検証(1回しか呼ばれないので当然失敗する)
   PowerMockito.verifyStatic(times(2));
   SettingsDao.getCurrencySign();
 }
}

ひさびさのSDベンチ

IS01の書き込み遅いと常々思っていて、いまさらながらにmicroSDのせいじゃないか?
と思い当たったので購入してみてベンチをとってみた。

Windows上でフォーマットだと・・・・というのが多いので
http://www.sdcard.org/jp/consumers/formatter_3/


を利用してフォーマット。

PLANEX Xperia対応 ハイスピードClass6 microSDHCカード 8GB (SDHCアダプタ&トリスター携帯万能Lite/抹消プロダウンロード付) PL-MicroSDHC8

IS01で使っていた件の。


                                                                                                                                            • -

CrystalDiskMark 3.0.1 x64 (C) 2007-2010 hiyohiyo
Crystal Dew World : http://crystalmark.info/

                                                                                                                                            • -

* MB/s = 1,000,000 byte/s [SATA/300 = 300,000,000 byte/s]

Sequential Read : 15.737 MB/s
Sequential Write : 11.548 MB/s
Random Read 512KB : 15.601 MB/s
Random Write 512KB : 1.794 MB/s
Random Read 4KB (QD=1) : 4.670 MB/s [ 1140.0 IOPS]
Random Write 4KB (QD=1) : 0.021 MB/s [ 5.1 IOPS]
Random Read 4KB (QD=32) : 4.674 MB/s [ 1141.1 IOPS]
Random Write 4KB (QD=32) : 0.029 MB/s [ 7.0 IOPS]

Test : 50 MB [I: 0.0% (0.0/7780.0 MB)] (x3)
Date : 2011/03/04 21:47:07
OS : Windows 7 Home Premium Edition [6.1 Build 7600] (x64)

まさかのそんな遅くないトラップ。




Transcend microSDHCカード 8GB Class6 永久保証 TS8GUSDHC6

ベンチ取る前にすでに注文していた新しいヤツ。好成績

Transcend microSDHCカード 8GB Class6 永久保証 TS8GUSDHC6
トランセンド・ジャパン (2008-11-28)
売り上げランキング: 245

                                                                                                                                            • -

CrystalDiskMark 3.0.1 x64 (C) 2007-2010 hiyohiyo
Crystal Dew World : http://crystalmark.info/

                                                                                                                                            • -

* MB/s = 1,000,000 byte/s [SATA/300 = 300,000,000 byte/s]

Sequential Read : 18.886 MB/s
Sequential Write : 17.918 MB/s
Random Read 512KB : 18.577 MB/s
Random Write 512KB : 1.462 MB/s
Random Read 4KB (QD=1) : 3.361 MB/s [ 820.6 IOPS]
Random Write 4KB (QD=1) : 0.014 MB/s [ 3.5 IOPS]
Random Read 4KB (QD=32) : 3.463 MB/s [ 845.5 IOPS]
Random Write 4KB (QD=32) : 0.025 MB/s [ 6.2 IOPS]

Test : 50 MB [I: 0.0% (0.0/7639.0 MB)] (x3)
Date : 2011/03/04 21:55:30
OS : Windows 7 Home Premium Edition [6.1 Build 7600] (x64)





CrystalDiskMarkの調子が悪いのでバージョン落としてみた。

001HTで使ってたSanDsikのClass4 8G

                                                                                                  • -

CrystalDiskMark 2.2 (C) 2007-2008 hiyohiyo
Crystal Dew World : http://crystalmark.info/

                                                                                                  • -

Sequential Read : 14.035 MB/s
Sequential Write : 6.039 MB/s
Random Read 512KB : 12.878 MB/s
Random Write 512KB : 4.753 MB/s
Random Read 4KB : 0.981 MB/s
Random Write 4KB : 0.600 MB/s

Test Size : 50 MB
Date : 2011/03/04 22:53:37

結構速いと思っていたんだが
シーケンシャルは遅いが、まさかのRandam好成績とか。

Transcend SDHCカード 8GB Class10 永久保証 TS8GSDHC10

ついでに買ったSDHC

Transcend SDHCカード 8GB Class10 永久保証 TS8GSDHC10
トランセンド・ジャパン (2010-03-05)
売り上げランキング: 44


class10が泣く結果に・・・

                                                                                                  • -

CrystalDiskMark 2.2 (C) 2007-2008 hiyohiyo
Crystal Dew World : http://crystalmark.info/

                                                                                                  • -

Sequential Read : 17.659 MB/s
Sequential Write : 12.389 MB/s
Random Read 512KB : 17.044 MB/s
Random Write 512KB : 1.699 MB/s
Random Read 4KB : 2.895 MB/s
Random Write 4KB : 0.063 MB/s

Test Size : 50 MB
Date : 2011/03/04 23:38:27


ちなみにK200Dで連射20枚行かないあたりでどんどん遅延。そしてついには書き込み失敗。
悲惨。ってもまぁJPEG+RAWなんだけどね。

SanDisk EXTREMEIII SDHCメモリーカード 4GB SDSDRX3-4096-903

参考までに

SanDisk EXTREMEIII SDHCメモリーカード 4GB SDSDRX3-4096-903
サンディスク (2007-10-01)
売り上げランキング: 51098

                                                                                                  • -

CrystalDiskMark 2.2 (C) 2007-2008 hiyohiyo
Crystal Dew World : http://crystalmark.info/

                                                                                                  • -

Sequential Read : 20.006 MB/s
Sequential Write : 17.484 MB/s
Random Read 512KB : 19.618 MB/s
Random Write 512KB : 3.197 MB/s
Random Read 4KB : 3.725 MB/s
Random Write 4KB : 0.036 MB/s

Test Size : 50 MB
Date : 2011/03/04 23:56:02

K200Dでの連射。10枚以降は1秒/枚位になってしまうもののそれ以上の遅延や失敗はなし。
JPEGのみにしちゃえばさらに問題なし。

SanDisk SDHCカード Extreme SDHC UHS-1 Class10 8GB SDSDX-008G-J95

この結果はどうなのかなぁ・・・

SanDisk SDHCカード Extreme SDHC UHS-1 Class10 8GB SDSDX-008G-J95
サンディスク (2011-03-02)
売り上げランキング: 23237

                                                                                                  • -

CrystalDiskMark 2.2 (C) 2007-2008 hiyohiyo
Crystal Dew World : http://crystalmark.info/

                                                                                                  • -

Sequential Read : 20.006 MB/s
Sequential Write : 18.465 MB/s
Random Read 512KB : 19.530 MB/s
Random Write 512KB : 3.718 MB/s
Random Read 4KB : 3.274 MB/s
Random Write 4KB : 1.063 MB/s

Test Size : 50 MB
Date : 2011/03/30 19:14:47

ISO-2022-JPでのバイト数

ISO-2022-JPの場合、マルチバイト文字の境界(開始と終了)で3byteずつ消費します。

あ=3+2+3=8byte
ああ=3+2+2+3=10byte
あああ=3+2+2+2+3=12byte
あaあ=3+2+3+1+3+2+3=17byte


文字数制限なのか、バイト数制限なのかはよくよく考える必要があります。
"".getBytes("ISO-2022-JP").lengthとすればちゃんと上記バイト数を取得してくれるので、
基本的には問題ないのですが、
なんとなく暗算で1000byte制限だから、半角で1000文字で全角で最大500文字ね〜なんてチェックだとはまります。


じゃぁ実際携帯キャリアはどうなの?最大文字数とかで表現していますけど
というのは調べていません。