ラベル java の投稿を表示しています。 すべての投稿を表示
ラベル java の投稿を表示しています。 すべての投稿を表示

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[])

2012年1月14日土曜日

Android - Javaでの文字列から小数への変換

色々な国で使われるアプリだと小数点がコンマ(,)で表現されるところもあることを意識しましょう。主にヨーロッパとかロシア、南米ですね(参考)。

EditTextビュー等に入力された文字列を数値に変換する時に


String str = someEditTextView.getText().toString();
float v = Float.valueOf(str);

として値を取り出すとコンマが小数点だと認識されずに例外(NumberFormatException)が発生してしまいます。

小数点がピリオド(.)でもコンマ(,)でも正しく文字列を値に変換するには

String str = someEditTextView.getText().toString();
NumberFormat nf = NumberFormat.getInstance(); // デフォルトのロケールを使う
Number n = nf.parse(str);
float v = n.floatValue();

等としましょう。これならロケールに合わせてピリオドやコンマを正しく小数点と認識してくれます。

また値を入力するためのEditTextビューに

<EditText
    ...
    android:inputType="numberDecimal"
/>

と数字関係の文字のみ入力できるようにしている場合には

    android:digits="0123456789.,"

等と入力できる文字を指定してコンマも入力できるようにしましょう。

2011年12月25日日曜日

JavaのTimerとTimerTaskの罠

Androidアプリで定期的に行う処理を起動するのに

java.util.Timer



java.util.TimerTask

を使用してハマった件のメモ。

スマホの時刻を手動で一時的に先の時刻に変更すると(例えば今8時だったら9時とか)、時刻を元に戻したときTimerがまったく動かなくなる!

どうもTimer、TimerTaskはシステムの時刻を元に次に処理を起動する時刻を決めて、その時刻になったら処理を呼び出すという動作のようだ。そのため一時的に未来の時刻になるとその時刻を元に次に起動する時刻を設定してしまう。時刻を元に戻すとその未来の時刻まではうんともすんとも言わなくなってしまうようだ。

まあActivityのような画面に表示されているときだけ動作するものにはそれでも良いのだが、Serviceのようなバックグラウンドでずっと動くものには要注意である。
そういう場合は

Executors.newSingleThreadScheduledExecutor()
等で

ScheduledExecutorService

を作成しましょう。これなら上記の問題は無いです。