Category: Develop

14.有用クラス -1.Math

14章 有用クラス
1.Math

import java.lang.Math

メンバー変数
static double E
    自然対数の底 e にもっとも近い double 値
static double PI
    円周とその直径の比 pi にもっとも近い double 値
メソッド
static double abs(double a)
    double 値の絶対値を返す
static float abs(float a)
    float 値の絶対値を返す
static int abs(int a)
    int 値の絶対値を返す
static long abs(long a)
    long 値の絶対値を返す
static double acos(double a)
    指定された角度の逆余弦 (アークコサイン) を、0.0 〜 pi の範囲で返す
static double asin(double a)
    指定された角度の逆正弦 (アークサイン) を、-pi/2 〜 pi/2 の範囲で返す
static double atan(double a)
    指定された角度の逆正接 (アークタンジェント) を、-pi/2 〜 pi/2 の範囲で返す
static double atan2(double y, double x)
    直交座標 (x, y) を極座標 (r, theta) に変換する
static double ceil(double a)
   引数の値以上で、計算上の整数と等しい、最小の (負の無限大にもっとも近い) double 値を返す
static double cos(double a)
    指定された角度(ラジアン)の余弦 (コサイン) を返す
static double exp(double a)
    オイラー数 e を double 値で累乗した値を返す
static double floor(double a)
    引数の値以下で、計算上の整数と等しい、最大の (無限大にもっとも近い) double 値を返す
static double log(double a)
    指定されたdouble値の自然対数値(底は e)を返す
static double max(double a, double b)
    2つのdouble値のうち大きい方を返す
static float max(float a, float b)
    2つのfloat値のうち大きい方を返す
static int max(int a, int b)
    2つのint値のうち大きい方を返す
static long max(long a, long b)
    2つのlong値のうち大きい方を返す
static double min(double a, double b)
    2つのdouble値のうち小さい方を返す
static float min(float a, float b)
    2 つの float 値のうち小さい方を返す
static int min(int a, int b)
    2つのint値のうち小さい方を返す
static long min(long a, long b)
    2つのlong値のうち小さい方を返す
static double pow(double a, double b)
    1番目の引数を、2番目の引数で累乗した値を返す
static double random()
    0.0以上で、1.0より小さい正の符号の付いたdouble値を返す
static double rint(double a)
    引数の値にもっとも近く、計算上の整数に等しいdouble値を返す
static long round(double a)
    引数にもっとも近いlongを返す
static int round(float a)
    引数にもっとも近いintを返す
static double sin(double a)
    指定された角度(ラジアン)の正弦(サイン)を返す
static double sqrt(double a)
    double値の正しく丸めた正の平方根を返す
static double tan(double a)
    指定された角度(ラジアン)の正接(タンジェント)を返す
static double toDegrees(double angrad)
    ラジアンで計測した角度を、相当する度に変換す
static double toRadians(double angdeg)
    度で計測した角度を、相当するラジアンに変換す
 
sample)Mathを用いて最大値と最小値を求める
import java.io.*;

class Test {
    public static void main(Stirng args[ ]) {
         float a[ ] = { 10.5f, 2.4f, 32.4f ,-4.1f, 5.0f };
         float minimum = Float.POSITIVE_INFINITY;      //floatで扱える最大値に初期化
         float maximum = Float.NEGATIVE_INFINITY;      //floatで扱える最小値に初期化

         forint i = 0 ; i < a.length ; i++ ){
              minimum = Math.min(minimum, a[i]);
              maximum = Math.max(maximum, a[i]);
         }

         System.out.println("最小値は" + minimum + "です");
         System.out.println("最大値は" + maximum + "です");

   }
}

C:\Java\>java Test
最小値は-4.1です
最大値は32.4です

C:\Java\>

13.ガーベージコレクター

13章 ガーベージコレクター 
1.ガーベージコレクターとは
 ガーベージ(garbage)とは、不要なデータのことである。不要になったデータを集めて処理する機能のことをいう。例えば、C++言語ではあるクラスのインスタンスを作成したら、プログラムでdeleteしないと不要データがいつまでもメモリー上に残ることになる。このことをメモリリークという。
 また、削除してしまったインスタンスを参照したりするとエラーになりOSなどによってはそのまま暴走してしまうといったバグも発生する可能性がある。
 しかし、javaではインスタンスを作成しても削除する必要がない。不必要になったインスタンスはこのガーベージコレクターがすべて処理してくれるからである。
class GarbageTest{
      public static void main (String args[ ]){
         
String str1 = new String("abc);
          String str2 = new String("ABC);

          str2 = str1;       // "ABC"という文字列はどこからも参照されなくなり、ガーベージコレクトの対象となる
         
System.out.println(str1);
          System.out.println(str2);
     }
}

C:\java>javac *.java

C:\java>java GarbageTest
abc
abc

C:\Mjava>

2.ガーベージコレクターの実行
 Java Virtual Machine(JVM)は、インスタンスの生成が行われた時など、メモリーを厳守監視している。これにより後でどのメモリー(インスタンス)が参照されていて必要なのか、あるいはもう参照されなくなって不必要になったのかを調べることができるようにしている。
 しかし、不必要になったデータを探すのは、アプリケーションが大きくなればなるほど、時間がかかる処理になる。したがってJVMはデータが不必要になったらすぐにガーベージコレクトを行うのではなく、何もしていないときにガーベージコレクトを行うようにしている。
 実際にガーベージコレクトが行われるタイミングはJVMの実装に任されており、プログラマやユーザがそのタイミングを関知しなくても良いことになっている。 
 Javaのメリットはプラットフォームを(OS)を選ばないことである。パソコンのようなメモリーの比較的豊富なプラットフォームで実行している分にはメモリーのことをそれほど意識しなくても良いのだが、携帯電話など比較的リソースの乏しいプラットフォームでJavaを実行する場合は、メモリーをできるだけ少なくして使用したい場合がある。このような場合、ガーベージコレクトをJVMに任せていてはメモリーが足りなくなってしまう。
 もちろんメモリーを使用したい時に残りのメモリーが足りなくなればJVMはガーベージコレクターを起動させるが、もし時間的に余裕がない場合、実行されてしまっては困る。そこで、プログラマがガーベージコレクタを起動させるタイミングを指定することができる。それには、Systemクラスのgc( )メソッドを使用する。

 それには、Systemクラスのgc( )メソッドを使用する。
 このメソッドはガーベージコレクタを起動させてほしいとJVMに伝えるだけで、いつ実行させるかはJVM次第である。よくJavaの解説書のこのメソッドの説明に「ガーベージコレクタを実行する」とあるが、これは間違いである。あくまでもできるだけ早くガーベージコレクタを実行させてほしいとJVMに要求するだけである。
2.finalize
 C++にはデストラクタがある。デストラクタとはコンストラクタの逆でインスタンスが破壊される時に呼ばれる関数である。しかし、Javaにはデストラクタがない。これは、Javaのインスタンスの破壊はガーベージコレクタに任されていて、インスタンスがいつ破壊されるかわからないためである。しかし、これでは不便なことがある。例えばファイルを開いた場合はファイルをクローズするとか、通信ポートを開いたらそれを閉じるといったメモリー以外のリソースを解放したい場合である。このような場合は、Objectクラスのfinalize( )メソッドをオーバーライドする。finalize( )メソッドはガーベージコレクタによって、メモリが解放される前に呼び出されるメソッドである。このメソッドをオーバーライドしその中でリソースの解放を行う。このfinalize( )メソッドもいつ呼ばれるかは保証されていない。インスタンスが参照されなくなったことが確認され、実際にそのインスタンスが占有していたメモリーを解放される間のどこかで実行されることが保証されているだけである。また、ガーベージコレクタが不要になったインスタンスを発見し、まだfinalize( )メソッドを実行していない場合、SystemクラスのrunFinalize( )メソッドを実行することで、finalize( )の実行を促すことができる。しかしFinalize( )メソッドを実行することでFinalize( )メソッドを実行するのではなく実行するタイミングはJVMの判断に任されている。 
 

6.オブジェクト指向とは

 

6章 オブジェクト指向とは
1.オブジェクト指向とクラス
 「オブジェクト指向」では、処理は二の次である。一番に考えるのはオブジェクトである。オブジェクトというのは「モノ」であり、実際に存在するもののことをいう。クラスとオブジェクトは等価。オブジェクトには決められた仕事や処理が決まっている。これがクラスで定義するメンバーメソッドである。
例)色鉛筆は実際に存在するものである。したがって、オブジェクトつまり「色鉛筆クラス」になる。(色鉛筆構造体)色鉛筆には様々な色があるメンバー変数として「色」「芯の長さ」を決める。
class Color{
    
int R;
    
int G;
    
int B;
}

class ColorPen{
    Color color;
    
int  length;
}

色鉛筆は、絵を描くことができる。メンバーメソッドを定義する。 
class Color{
    
int R;
    
int G;
    
int B;
}

class ColorPen{
    Color   color;
    
int    length;

     void draw( ){
       :
       :
    }
}

 オブジェクト指向では、このように「モノ」と「それを扱う関数(メソッド)」が一緒にクラスとして定義されているので、「色鉛筆で食べ物を食べる」というミスは文法的に書けないことになっている。

 整理すると「オブジェクト指向」では「モノ(データ、デバイスなど)を第1優先に考える」という分析・設計・実装方法である。

 
2.継承
 色鉛筆は鉛筆の一種であると考えられる。鉛筆でも絵を描くことができるが、色は黒一色である。色鉛筆では様々な色で絵を描くことができる。
class Color{
    
int R;
    
int G;
    
int B;
}

class Pencil{
    
int    length;

     // 黒で絵をかく
     void draw( ){
       :
       :
    }
}

class ColorPen extends Pencil{
       Color color;

// int  length; スーパークラスで定義されているので、ここでは定義しない

     // colorで絵をかく
    void draw( ){
       :
       :
    }
}

 このように定義すると「鉛筆クラスは鉛筆クラスの一種」という意味になる。このように、既存のクラスの一種であるクラスを定義することを「継承」という。色鉛筆クラスには「長さ」定義されていないが、鉛筆クラスで定義されているの
で、色鉛筆クラスにも「長さ」が定義されていることになる。

 この場合、色鉛筆クラスからみて鉛筆クラスを「スーパークラス」、「基底クラス」あるいは「親クラス」といい、鉛筆クラスから見て色鉛筆クラスを「サブクラス」あるいは「子クラス」という。

 上のクラス図は、基底クラスとして「哺乳類クラス」、その子クラスとして「犬クラス」「猫クラス」そして「象クラス」を定義している。さらに「猫クラス」の子クラスとして「三毛猫クラス」「シャム猫クラス」を定義している。
 しかし、「犬クラス」の子クラスとして「盲導犬クラス」を定義することはあまりよくない。なぜならこの場合、動物の種類として継承しているため、そこに「警察犬」「盲導犬」といった機能で継承することになるからである。
 Javaでは、機能で継承させたい場合には、継承ではなくインターフェースという機能を使う。詳細は後述。

 
3.カプセル化
 クラスのメンバー変数、メンバーメソッドは誰が触っても良いものと、触るクラスを限定したい場合がある。誰が触っても良いものを「public」、自分と同じパッケージ内のクラスからもしくはサブクラスからしか触れられない物を「protected」、そして自分自身のクラスからしかさわれない物を「private」という。
 すべてのメンバー変数、メンバーメソッドをpublicにして、プログラマーたちが決め事としてさわらないようにと決めても良いが、中には決め事を守らないプログラマーもいるため、public、protected、privateを決めておけば文法的にコンパイラでチェックしてくれる。
 何故そんなことをするのだろう。これは、作ったプログラムの一部を部品化しやすいようにするためである。オブジェクト指向では、作ったプログラムを部品化しておき、別のプログラムを作る際に再利用できるようにする。例えばインターネットブラウザのプログラムを作った場合、ネットワーク関係の部品は、次に作るメーラーに再利用ができる。このように部品化したクラスやパッケージは使い方さえ知っていればそのソースコードを知らない人でも使うことができる。ところが、内部(ソースコード)を知らないプログラマーが出てくるとバグの原因になる。そこで、protectedであれば勝手なことはされなくて済む。
 基本的にメンバー変数はすべてprivateかprotectedにする。そして、参照するためのメソッドと代入するメソッドを用意する。このようなメソッドをアクセサメソッドと呼ぶ。なぜ、こんな面倒なことをするのか、理由は3つある。

 1、メンバー変数の型を「int」から「double」に変更しようとした場合、参照する場合と代入する場合の2つに影響してくる。publicな変数だとプログラムすべてに渡ってこの変数を参照する場所と代入する場所を探すのは面倒な作業である。それに対しメソッドを探すのは比較的容易だからである。
2、メンバー変数は他のクラスから参照しても良いが値を変更するのは×という変数があったとする。この場合、参照するメソッドはpublicに、代入するメソッドはportectedかprivateにすればよい。
3、マルチスレッドプログラムにした場合、複数のスレッドが同じ変数にアクセスする場合がある。例えば、あるスレッドがリストをソース中に、別のスレッドがそのリストを参照した場合、矛盾が生じてしまう。このような場合は「セマフォ」というリストを参照する権利を与え権利があるスレッドだけがリストを参照したりさわったりできるうようにする。あらかじめ参照するためのメソッドを用意しておけばセマフォの処理を組み込む場合もそのメソッドをちょっと直すだけなので簡単である。
 このように変数やメソッドにアクセスできるクラスを制御することで、あるクラスの部品のようにすることができる。部品のようになったクラスは別のプログラムを作るときにも利用できる。例えば、Javaでは標準でGUIや通信mその他さまざまなクラスがたくさん用意されており、通信をしたいと思えばそのためのクラスをファイル操作したければそのためのクラスをプログラマーが使用するだけだから、プログラムが簡単に書ける。また、携帯電話用のソフトを書きたければ携帯電話会社が公開しているクラス群が利用できる。
 また、通信をするためのクラスを利用しようと思った場合、通常その中身がどんなプログラムになっているのか、プログラマーは知る必要がない。つまり、通信をするためのクラスの中身はブラックボックスということになる。
 このように、中身を知らなくても部品のように使えるように設計することを「カブセル化」という。
 
4.ポリモーフィズム
 ポリモーフィズムとは、ギリシャ語で「多数の形態」という意味である。プログラムで「ポリモーフィズム」というと同じメソッドを定義することをいう。
 例に例えると「鉛筆クラス」の「絵を描くメソッド」と「色鉛筆クラス」の「絵を描くメソッド」は、若干機能がことなるが「絵を描くメソッド」というメソッドの名前は同じである。
 例えばint型の絶対値を求めるメソッドを「abs」と名づけると小数も扱えるようなメソッドを追加しようとした場合、「abs_float」と名前を変えなくてはならなかった。Javaではポリモーフィズムによって、引数が異なれば同じ名前のメソッドを複数定義することもできる。このように同じ名前のメソッド(またはコンストラクタ)を作ることを、メソッドをオーバーロードするという。