2012/10/10

[java]shallow copy

#(2012/10/13追記) System.arraycopy()についてよくわかってないことを書いてますが、後日調査しました。

NFCアプリを作るならば、NFCカードへのアクセスは避けられまい。
どうやってやるのか調べたところ(というほどでもないが)、MIFARE Ultralightの例があった。

なるほど、writePage()か。
いやいや、その前に「MifareUltralight」ってクラス名かい!
念のためにNfcAなどを見てみると、transceive()しかなかった。
うーん、それなら「Felica」クラスもあっていいと思うんだけどなぁ。


まあ、手段があるならいいや。
いつものようにバイト配列にコマンドを書いて送るだけだ。

・・・と思ったが、transceive()の引数はbyte[]だった。
長さの指定が無いということは、引数のlengthがそのままデータ長になるんだろう。
それだと、バッファとして用意したbyte[]にデータを突っ込むだけではだめだ。

 

他の人がどうやってるか知らないが、私はだいたい、NFC R/Wに対してWRITEバッファとREADバッファを1つずつ持つように作っている。
無線なので「同時読み書き」が発生しないからバッファは1つでも足りるのだけど、デバッグに便利だし、めんどくさいのでそうしている。
もったいないとは思うのだが、このくらいは許してくれる・・・と思っている。

そのバッファサイズは、FeliCaの最大にあわせて265byteにしている(たしか)。
プリアンブルとポストアンブルは固定だから4byteくらい削れるんじゃないの、といわれそうだが・・・・すまん、めんどくさかったのだ。


さて、本題だ。

私がR/Wに転送するときは、バッファにデータを詰めて、データとデータ長を渡すようにしている。
C/C++の配列にはデータ長がないので、ユーザが管理するのが普通だからだ。

しかし、transceive()はbyte[]のみで、lengthは渡せない。
これは困った。

Javaだとヒープに確保するんだから直前までサイズを固定しなければいいじゃないの、といわれそうだが、何となく慣れなくて・・・。
新しい革袋を用意すべきだとは思うのだが、私にはまだその準備ができていないのだ。

じゃあ、データを作った後になればサイズがわかるから、そのときにまた領域を確保してコピーすればいいやん、という考え方もあるが・・・もったいない。
ほら、我々の世代は「資源は有限、資源を大切に」と育てられた世代ではないか。
違うlengthを得るためだけにコピーするのは、心苦しい。
Genericとか、そんなしくみはいらず、とにかくバッファがほしいだけなんだけどなぁ。

 

と思って調べていると、JavaFAQというページがあった。
ここの「S006-Q09」に、こんな質問があった。

コピーした配列の要素を書き換えると元の配列でも書き換わってしまうのですが?

その回答が、こう。

配列をコピーした際に、配列の要素がコピーされていないからです。

 

おお、これこれ!
こういうのを期待していたんだよ。
shallow copyって、COWで書き込むまでのつなぎってイメージがあったけど、こういうときに使うものなのかな。


shallow copyなら、コピー先のnewはいらないんじゃないの?と思ってやってみた。

だめだった。
うーん、領域をコピーせんといかんのなら、なんか意味が無いなあ。

 

このnewは私に覚悟を問うているのかも。
「貴様に、これだけのメモリを確保する意気込みはあるのか」とか。
ないんだけど、ないんだけど・・・。

 

newすると当然うまくいくんだが、なんだかなぁ。
実際に使用するまでは、メモリ確保したふりをするだけだったらいいんだけど。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。