2015年8月20日木曜日

Javaのアクセス修飾子の使い分け

Javaではアクセス修飾子として可視性の低い順から
  • private: そのクラスからしか見えない
  • package-private(default): 何も指定しない場合。パッケージ内のクラスからしか見えない
  • protected: パッケージ内のクラスと子クラスから見える
  • public: どこからでも見える
がある。これらをどのように使い分けるか個人的な考えを纏めておく。あくまで個人的な指針で正しい考えとは限らない。

その前にアクセス修飾子のことから離れて、継承について考えを纏めてみる。
継承はなるべく使わない方が良い。継承を乱用するとちょっと機能を追加するのに新しいサブクラスを作成したりして、多くのクラスに機能が分散してしまう。
継承が無用と言うわけではない。使う場合は予め継承を前提とした設計を行い計画的に使う必要があるということ。心構えとしては「使わない」程度でちょうど良い。

継承を使う場合としては
  • フレームワークを使用する場合。AndroidでActivityを継承するなど。
に限ったほうが良い。もちろんinterfaceを実装する場合は別である。

このようにクラスは継承しないという前提。
また可視性は最低限に抑えたほうが良いという原則。
 Javaでは継承したクラスのメソッドをオーバライドする場合、またはinterfaceのメソッドを実装する場合には元の可視性より低い可視性は指定できないというルール。
以上をもとに各アクセス修飾子を検討する。

まずトップレベルのクラスまたはインターフェイスに付くアクセス修飾子はpackage-private(つまり何も指定しない)かpublicのどちらかである。
基本的にはpackage-privateで良い。 他のパッケージに見せる、つまり外部パッケージへのインターフェイスとなるクラスにのみpublicを付けるようにする。これは慎重に最低限に抑えるべきである。一度他のパッケージに公開したクラスは削除したり、メソッドを変えたりすると多大な影響を他に及ぼすため非常にやっかいなことになる。
つまりトップレベルのクラスの宣言は
class some_class {
...
}
とアクセス修飾子は付けなくて良い。

以下にクラス内のメンバに対するアクセス修飾子について考える。

private

private指定されたメンバはそのクラスからしか見えない。
クラス外に公開するメンバ以外は全てprivateを指定する。

package-private(default)

アクセス修飾子を付けないとこの可視性になる。これはパッケージ内のクラスからしか見えない。
クラス外に公開するメンバは基本的にこれにすること。
但しinterfaceを実装した場合は例外である。interfaceのメソッドは全てpublicでなければならない。Javaでは親の可視性より低い可視性は指定できないので、interfaceを実装した場合はそのメソッドはpublicとなる。
また継承した場合、package-privateより大きい可視性をもつメソッドをオーバーライドする場合も同様である。

protected

protected指定されたメンバはpackage-privateの可視性に加えてサブクラス(子クラス)からも見えるようになる。
継承を使用しないという前提に立つと、この修飾子を使用することは殆ど無い。例外としてフレームワークからの親クラスのメソッドをオーバーライドする場合、親クラスでの可視性がprotectedであった場合ぐらいである。

public

public指定されたメンバはどこからでも見える。
上述したようにinterfaceを実装した場合はそのメソッドにpublicを指定する。また親クラスのメソッドをオーバーライドする場合、親クラスでの可視性がpublicであった場合もpublicを指定する。
その他、複数のパッケージを使用するような比較的大きい規模のプログラムでは他のパッケージに対してのインターフェイスとなるメソッドにはpublicを指定する(クラス自体もpublicとする)。これは他のパッケージとの依存関係を作るので慎重に最低限に抑えるべきである。安易にpublic指定したメソッドを変更すると他のパッケージなど広範囲の影響を及ぼしてしまう。
mainメソッドは以下のようにpublicにする必要がある。
public static void main(String argv[])

2015年7月8日水曜日

LinuxでのAndroid Emulator使用時のHardware Accelerationの設定

LinuxでAndroid Emulatorを使用する場合、Hardware Accelerationを設定すると起動にかかる時間やレスポンスが改善する。Hardware AccelerationにはGraphics AccelerationとVM(Virtual Machine) Accelerationがある。ここではVM Accelerationの設定方法を示す。
基本的には http://developer.android.com/tools/devices/emulator.html#acceleration に載っていることと同じ。

VM Accelerationを行うには
  • CPUがhardware virtualizationをサポートしていること。
egrep -c '(vmx|svm)' /proc/cpuinfo
とし1以上が返ってくればCPUは対応している。
  • BIOSでhardware virtualization supportがイネーブルになっていること。

が条件となる。

LinuxではKVMをインストールすることでVM Accelerationが可能になる。インストール方法は https://help.ubuntu.com/community/KVM/Installation を参考に行った。

インストールするモジュールは(Ubuntuの場合)
qemu-kvm, libvirt-bin, ubuntu-vm-builder, bridge-utils

sudo apt-get install qemu-kvm libvirt-bin ubuntu-vm-builder bridge-utils
等でインストールする。

インストール後libvirtdのグループに自分を加える。
sudo adduser `id -un` libvirtd
その後一度ログアウトし、再びログインする。

端末で
virsh -c qemu:///system list
とし
 Id    名前                         状態
----------------------------------------------------

と表示されれば、インストールは成功。

EmulatorでVM Accelerationを行うには更に
  • Android SDK ToolsがRevision17以上
  • AVDがx86ベースのシステムイメージで作成されている
である必要がある。
この条件を満たすことを確認したらAndroid Studioのメニューの「Run」-「Edit Configurations...」で表示されたダイアログで「Emulator」タブの「Additional command line options」をチェックし、右側に
-qemu -m 512 -enable-kvm
と記述する。
後はこのx86ベースのEmulatorを立ちあげれば良い。

Emulatorが立ち上がるまで(ロック画面が表示されるまで)の時間を計測してみると

x86ベース、VM Acceleration無し 28秒
x86ベース、VM Acceleration有り 18秒
armベース 6分30秒

となった。
armベースは桁外れに遅い。

2015年7月6日月曜日

Android StudioでEmulatorが立ち上がらない時

LinuxでAndroid Studioを使用している時、Emulatorを立ち上げようとすると

NAND: could not write file /tmp/android-***/emulator-***

などというメッセージがでてEmulatorが立ち上がらない場合がある。

そのような時は /tmp ディレクトリがどうなっているか確かめる。

df -h で

Filesystem              Size  Used Avail Use% Mounted on
...
tmpfs                   256M  110M  147M  43% /tmp
...

等と出た場合はtmpfsでメモリ上に/tmpディレクトリがマウントされている。

Emulatorは500Mバイト以上のファイルサイズを/tmp/android-***ディレクトリ上に要求するので、上のようにサイズが256Mバイトだと容量が足りずあのようなエラーメッセージがでる。

解決方法としては/etc/fstabを編集して

tmpfs /tmp tmpfs rw,size=1024m 0 0

等とし、/tmpのサイズを1Gバイト以上にする。または上記をコメントアウトしてディスク上に/tmpディレクトリが存在するようにする。

ちなみに私は、/tmpは一時的なファイルが頻繁に書き込まれるディレクトリなので、SSDになるべく書き込みが少なくなるようにこの設定を行っていました。LinuxでSSDを使っている人は同じ罠にはまるかも?


Android Studioインストール時のエラー

Androidの新しい開発環境Android StudioをLinux(Linux Mint)にインストールしたら、以下のメッセージがでて進まない。

The following SDK components were not installed:
sys-img-x86-addon-google_apis-google-22 and
addon-google_apis-google-22

何度かリトライしてみたがダメ。
結局


  • ホームディレクトリの.AndroidStudio1.2を.AndroidStudio1.2.oldとリネーム
  • ホームディレクトリの.androidを.android.oldとリネーム
  • 念の為インストールしたandroid-studio以下のファイルも全部削除
  • AndroidStudioを再インストール。今度はインストールできた!

これでOK。
恐らく以前Eclipseで開発していた時から存在していた.androidがなにか悪さをしていた模様だが、何がダメだったのかはっきり分からず気持ち悪い。

2015年4月2日木曜日

国立 大学通りの桜の風景

画像を入れるテストを兼ねて国立の大学通りの桜の写真をアップ。


いい感じの時計と桜。駅から見て紀伊國屋の先のタバコ屋さんと瀬戸物屋さんの前辺りにあります。


あっという間に満開ですな。


国立高校近くの歩道橋の上から。


国立駅のホームから。

2015年3月21日土曜日

XILINX ILAの1ビットprobe(0 downto 0)にsignalを繋ぐ簡単な方法

XILINXのIP Core, ILAは1ビットのprobeを定義しても

    component ila
      port (
        clk : in std_logic;
        probe0 : in std_logic_vector(0 downto 0)
        );
      end component;

のように std_logic_vector になっている。

インスタンスに std_logic の信号を接続するときには

    signal probe0 : std_logic_vector(0 downto 0);

    probe0(0) <= some_signal;

    i_ila : ila
      port map (
        clk => clk,
        probe0 => probe0
      );

のようにしても良いのだけれど、probe0のsignal をいちいち定義するのも面倒。

知っている人には「何を当たり前のことを言っているんだ」かも知れないけど

    i_ila : ila
      port map (
        clk => clk_in,
        probe0 => (0 => some_signal)
      );

のようにすれば probe0 を定義しなくても直接 ILA のインスタンスに接続でき簡単。
意外とこういう接続方法ってやらないので、知っておくとちょっと便利な書き方です。

2015/4/2追記

probe0 => (0 => some_signal)
と書くとVivado 2014.4ではシミュレーション時エラーとなる。Synthesis, ImplementationはOK。

probe0(0) => some_signal
と書けばシミュレーション時も問題なく通る。シミュレーションもかけるならこちらの方が良い。