メモ置き場

メモ置き場です.開発したものや調べたことについて書きます.

[tex: ]

Javaの勉強(1)

Javaの研修が始まったので,自分のためにもまとめておく.
何回かに分けて書こうと思う.

最近はZynqをさわれていないし更新頻度も落ちてしまった.
けれども,ありがたいことにブログを見に来てくれている人たちが一定数いるみたいです.励みになります.頑張って更新していきます.

オブジェクト指向とは

Javaとはオブジェクト指向な言語の一種である.オブジェクト言語の3大要素として

がある.

カプセル化

カプセル化は,クラスの持つフィールド(変数や関数=メソッド)へのアクセスを制限して,意図しない使い方やバグを防ぐといった考え方.getterやsetterといったメソッドを用意することで,意図した使い方だけをさせることができる.

継承

すでにあるクラスを使って新しいクラスを定義すること.継承されるクラスを親クラスとかスーパークラス,継承して新しく作られたクラスを子クラスやサブクラスなどという.Javaではサブクラスは1つのスーパークラスしか持つことができない,つまり多重継承は禁止されている.

ポリモフィズム

Javaを勉強していて一番便利だなと思った考え方のうちの一つ.あるクラスAをスーパークラスとしたサブクラスが複数B1, B2, B3, ...あるとする.それぞれのサブクラスのインスタンスb1, b2, b3, ...はスーパークラスとして扱うことができ,さらにスーパークラスが持っているメソッドを使うことができる.
わかりにくいので,実装例をみるのが早いと思う.今後の記事で別にまとめる予定.

クラス

Javaはクラスを定義しクラス間でメッセージをやり取りすることで動作していく.MyClassというクラスを新しく定義したい場合,クラス名と同じ名前で拡張子が.javaのファイルを用意する.

class MyClass{
    private int number;
    
    public int getNumber(){
        return number;
    }

    public void setNumber(int number){
        this.number = number;
    }
}

のような形になる.C++のやつと大して変わらない.thisとかprivateとかは後述.

インスタンス

クラスが実際に使われるには,メモリ上にクラスの情報を格納する領域を確保してその上にデータを詰めていく必要がある.実際にメモリ上に確保されたクラスをインスタンスと言い,メモリに確保することをインスタンス化という.クラスを実際に使うにはインスタンス化する必要がある.インスタンス化にはnew演算子を使う.インスタンスには名前をつけて,メソッドなどを参照することができる.

public class Main{
    public static void main(String[] args) {
        MyClass myClass = new MyClass();
    }
}

newでインスタンス化したものをMyClass型の変数myClassに代入している.インスタンスを参照するデータ型は参照型と呼ばれる.参照型はインスタンスが存在しているメモリ領域を指し示していると理解している.

注意として,インスタンスのコピーはnaiveな方法ではできない.

public class Main{
    public static void main(String[] args) {
        MyClass myClass = new MyClass();
        MyClass myClass2 = myClass;
    }
}

追加した参照変数myClass2とmyClass変数は同じインスタンスを指しているので注意.インスタンスをコピーするにはcloneを実装する必要がある.

プリミティブ型変数と参照型変数

参照型変数はインスタンスへの参照を持つ.代入を行うと参照がコピーされインスタンスはコピーされない.ヒープ領域に確保される.
参照型変数とは違って,intやdoubleなどはprimitive型変数と呼ばれる.プリミティブ型変数への代入は値のコピーが行われる.またメモリのうちスタック領域に確保される.

コンストラク

クラスをインスタンス化するときに呼ばれるメソッドのこと.クラスメンバの初期化などをコンストラクタで行うことが多い.コンストラクタをクラス定義に書いていない場合はデフォルトコンストラクタが暗に定義されれ実行される.コンストラクタに引数を持たせることも可能.

オーバーロード

同名のメソッドでも,引数の型や数(シグネチャという)を変えることで複数定義することができる機能.どの処理になるかはシグネチャで決まる.オーバーライドとは異なるので注意.

staticメンバ

クラスのメンバは普通,インスタンスに依存したものになる.次のようなクラス

class MyClass{
    private int number;

    public MyClass(int number){
        this.number = number;
    }
    
    public int getNumber(){
        return number;
    }

    public void setNumber(int number){
        this.number = number;
    }
}

を次のインスタンス化すると

public class Main{
    public static void main(String[] args) {
        MyClass myClass1 = new MyClass(1);
        MyClass myClass2 = new MyClass(2);

        System.out.println(myClass1.getNumber()); // 1が表示される
        System.out.println(myClass2.getNumber()); // 2が表示される
    }
}

myClass1とmyClass2でnumberというメンバの値は異なる.このようにインスタンスに依存したメンバはインスタンスメンバという.

それとは別に,クラス固有のメンバを定義することができる.それをstaticメンバという.クラス定義でstatic修飾子をつければ良い.

class MyClass{
    private int number;
    private static int staticNumber = 100;

    public MyClass(int number){
        this.number = number;
    }
    
    public int getNumber(){
        return number;
    }

    public void setNumber(int number){
        this.number = number;
    }

    public static int getStaticNumber(){ //staticメンバ変数にアクセスするメソッドはstaticにする.staticにしていないとコンパイルエラー
        return staticNumber;
    }

    public static void setStaticNumber(int staticNumber){ // staticメソッドで書き換え.
        MyClass.staticNumber = staticNumber;
}

staticメンバはクラス固有なので,インスタンス化しなくても呼び出すことができる.

public class Main{
    public static void main(String[] args) {
        System.out.println(MyClass,getStaticNumber()); // 100が表示される

        MyClass myClass1 = new MyClass(1);
        MyClass myClass2 = new MyClass(2);

        System.out.println(myClass1.getStaticNumber()); // 100が表示される
        MyClass1.setStaticNumber(200);
        System.out.println(myClass2.getStaticNumber()); // 200が表示される        
    }
}

staticメンバといったクラス固有の情報は,パーマネント領域という部分にロードされるらしい*1

アクセス修飾子

privateとかpublicとかの事.メンバがクラス以外からアクセスできるかどうかを指定するためにつける.

  • private

同一クラス内からのみアクセス可能.

  • public

どのクラスからもアクセス可能

  • protected

同一クラスと同一パッケージ内からのアクセス可能.パッケージについては後述.また継承先のサブクラスからもアクセス可能

  • 修飾なし

同一クラスと同一パッケージ内からのアクセス可能.

パッケージ

似たような機能を持つクラスをまとめたものがパッケージ.ディレクトリみたいな感じ.パッケージはネストすることが可能.packageとクラス定義の前に書く.

package pkg1;
public class PackageClass {
    ....
    ....
}

パッケージ名は小文字と数字の組み合わせとするのが習慣となっている.またパッケージの階層構造は「.」で書く.パッケージを書かないクラスはデフォルトパッケージに入る事になる.

パッケージの参照

コンパイラなどにどのパッケージを参照するかを教えてあげる必要がある.

  • クラスのパスで指定する
pkg.MyClass tmp = new pkg.MyClass();
  • 同一パッケージの中

特に指定しなくても勝手に探してくれる

  • importで指示した場所
import pkg.subpkg.SubClass;
SubClass sub = new SubClass();
  • java.langパッケージ

Java側で準備してくれているパッケージ.Stringとか.

*1:ロードのタイミングはわからない