LoginSignup
1
5

More than 1 year has passed since last update.

Java Silver 5章 クラス定義とオブジェクトの生成・使用

Posted at

クラスとインスタンス

クラスの宣言

【装飾子】 class クラス名 {}
 コンパイラして作成されるクラスファイルは定義したクラス名が付く
 インスタンス化して初めてメモリ領域が確保される

メンバの宣言

メンバはクラス、またはオブジェクトが持つ変数、メソッドを指す
スキャン 2021-09-09 8.50.png

メンバ変数の種類
・インスタンス変数:オブジェクト毎に存在する変数
・static変数   :クラスに対して存在する変数

インスタンス変数の宣言
【装飾子】 データ型 インスタンス変数名;

メソッドの定義
【修飾子】戻り値の型 メソッド名(引数リスト){}

インスタンス化

データ型 変数名 = new クラス名();

左辺で変数を宣言(変数はあくまで参照先を示すだけの参照型データ)
右辺で参照先であるオブジェクト(実体)を作成

呼び出し方

/*
クラス宣言 クラス名 Employee
・static変数名id
・メソッド名 setId() 引数:int i をidに代入する
       getId() retun
*/

//クラス宣言
class Employee {
  int id; //メンバ変数を宣言

 //メソッド宣言 
 //返り値の型(void:返り値なし) 引数(int i;数値型の引数あり)
  void setId(int i) {
    id = i;
  }
 //返り値の型(int:数値) 引数(なし)
  int getId() {
    return id;
  }
}
public class Main {
  public static void main(String[] args) {
    Employee a = new Employee(); // Aさん用オブジェクトを作成
    a.setId(100);   // IDをセットするメソッドを呼び出す
    Employee b = new Employee(); // Bさん用オブジェクトを作成
    b.setId(200);   // IDをセットするメソッドを呼び出す
    System.out.println("Aさん: " + a.getId()); // IDの表示
    System.out.println("Bさん: " + b.getId()); // IDの表示
  }
}

変数のスコープ

メンバ変数:クラス定義の直下で宣言される変数
      有効範囲(スコープ)はクラス内
      宣言した時点でデフォルト値に初期化される(配列と同様)

ローカル変数:if文やfor文などのブロック内やメソッドの引数リストで宣言している変数
       スコープはブロック内
       明示的な初期化が必要

コンストラクタ

インスタンス化した時に最初に呼び出されるブロックを設定できる

コンストラクタの条件
・名前がクラス名と同じ
・戻り値を持たない(戻り値宣言もなし)
・必要に応じて引数を受け取る

new コンストラクタ名(引数リスト){}

コンパイルの際、コンストラクタが定義されていない場合デフォルトコンストラクタが作成される
デフォルトコンストラクタ
・引数をもたない
・実装は空({}に何も記述されない)

オーバーロード

複数のコンストラクタを定義する事ができる
名前が同一であるため、区別するために引数の並び、データ型、数が異なる

class Test {
  void myPrint(){ System.out.println("myPrint()"); }  //引数なし
  void myPrint(String s) { System.out.println("myPrint(String s)"); } //引数:文字列型の変数s
  void myPrint(int a) { System.out.println("myPrint(int a)"); } //引数:数値型の変数a
  void myPrint(int a, int b){ //引数:数値型aとb
    System.out.println("myPrint(int a, int b)"); }
}
public class Main {
  public static void main(String[] args) {
    Test t  = new Test(); // Testクラスのインスタンス化
    //引数の指定でメソッドを区別している
    t.myPrint();
    t.myPrint(100);
    t.myPrint(100, 200);
    t.myPrint("yamamoto");
  }
}

オーバーロードの悪い例

class Test {
  String myPrint(int a, String b) { return "test"; }     
  String myPrint(int a, int b) { return "test"; }        
  String myPrint(String a, int b) { return "test"; } 
  //変数
  //void myPrint(int a, String b) { } 

  //変数名は違うがデータ型,並び同じなのでNG
  //String myPrint(int x, String y) { return "test"; }  
}

ポイント
・それぞれ別々に定義されたメソッドとして扱われる
・オーバーロードされたメソッドは戻り値の有無、データ型の違いなどの制限がない
・どのメソッドが呼び出されるかは呼び出し時に指定した引数によってコンパイラが判断する
・異なる修飾子を指定できる

可変長引数の宣言

メソッドの引数の数を可変に扱える

class Test {
  public void method(String s, int... a) {
    System.out.println(s + " サイズ : " + a.length);
    for(int i : a){
      System.out.println("  第 2 引数の値  :" + i);
    }
  }
}
public class Main {
  public static void main(String[] args) {
    Test obj = new Test();
    int[] ary = {10, 20, 30};
    obj.method("1 回目 ");         obj.method("2 回目 ", 10);
    obj.method("3 回目 ", 10, 20); obj.method("4 回目 ", ary);
    //obj.method("5 回目 ", null);
  }
}
1 回目  サイズ : 0
2 回目  サイズ : 1
  第 2 引数の値  :10
3 回目  サイズ : 2
  第 2 引数の値  :10
  第 2 引数の値  :20

//呼び出しす際に配列を引数にすることも可能
4 回目  サイズ : 3
  第 2 引数の値  :10
  第 2 引数の値  :20
  第 2 引数の値  :30

引数にNullを引き渡す例

class Test {
  public void method(String... val) {
    String size = "";
    size += val == null ? "" : val.length;
    System.out.println(val + " : " + size);
  }
}
public class Main {
  public static void main(String[] args) {
    Test obj = new Test();

    //可変長引数は配列でデータを受け取る
    obj.method("A", "B");  //String[] = {A , B}
    //String[] = null 文字列Nullなのか参照型データnullなのかわからない
    obj.method(null); 

    obj.method((String[])null); //キャストして配列型に
    obj.method();
    obj.method((String)null); //キャストして参照型に
  }
}

Static変数とStaticメソッド

クラスで共有管理されるStaticメンバ
スキャン 2021-09-11 8.16.JPG

通常はインスタンス化するとその数だけ変数、メソッドが作成され領域が確保される
常に共有されるためインスタンス化しなくても呼び出しが可能

クラス名.static変数名
クラス名.staticメソッド名()

Staticメンバの宣言と呼び出し

class Test {
  int instanceVal = 100; 
  static int staticVal = 200; 
  void methodA() { System.out.println("methodA(): " + instanceVal); }
  static void methodB() { 
    System.out.println("methodB(): " + staticVal); }
}
public class Main {
  public static void main(String[] args) {
    // NG:testクラスがインスタンス化されていない(実体がない)
    //System.out.println(Test.instanceVal);   

    System.out.println(Test.staticVal);       // OK
    //Test.methodA();                         // NG:同じく実体がない
    Test.methodB();                           // OK
    Test obj = new Test();
    System.out.println(obj.instanceVal);      // OK
    System.out.println(obj.staticVal);        // OK
    obj.methodA();                            // OK
    obj.methodB();                            // OK
  }
}

staticメンバのクラス内でのアクセス

public class Test {
  int instanceVal;             // インスタンス変数
  static int staticVal;        // static変数

  //クラス内のメソッドでインスタンス変数にアクセス
  int methodA() { return instanceVal; }           // OK
  //クラス内のメソッドでstatic変数にアクセス
  int methodB() { return staticVal; }             // OK
  //クラス内のstaticメソッドでインスタンス変数にアクセス(インスタンス化が必要)
  //static int methodC() { return instanceVal; }  // NG
  //クラス内のstaticメソッドでstatic変数にアクセス
  static int methodD() { return staticVal; }      // OK
  //クラス内のstaticメソッドでインスタンス化した後、そのインスタンス変数にアクセス
  static int methodE() {                          // OK
    Test obj = new Test();  
    return obj.instanceVal;    
  }
}

イニシャライザ

クラスがロードされた時点で実行されるブロック
コンストラクタがインスタンス化した時点なのに対し、イニシャライザは最初に実行される

class Test {
  //static {}のブロックがクラスのロード時点で実行される
  static {
    System.out.println("Testクラス:static イニシャライザ");
  }
  Test() { 
    System.out.println("Testクラス:コンストラクタ");
  }
}

public class Main {
  //同じくstatic {}のブロックがクラスのロード時点で実行される
  static {
    System.out.println("Mainクラス:static イニシャライザ");
  }
  public static void main(String[] args) {
    //main()メソッドと、別クラスのメソッドではどちらの実行が先か…
    System.out.println("Mainクラス:main()メソッド");
    Test obj = new Test();
  }
}

実行順序
1.Javaコマンド実行時でMainクラスを実行
2.mainクラスのイニシャライザが実行
3.mainクラスのmain()メソッドが実行
4.Testクラスがインスタンス化
5.Testクラスのイニシャライザが実行
6.TestクラスのTest()メソッドが実行

Mainクラス:static イニシャライザ
Mainクラス:main()メソッド
Testクラス:static イニシャライザ
Testクラス:コンストラクタ

アクセス修飾子

他クラスからのアクセスを制限できる

class Employee {
  private int id;  // インスタンス変数にprivateを指定
  public Employee(int i) { id = i; } // コンストラクタにpublicを指定
  public int getId() { return id; } // メソッドにpublic修飾子を指定
}
public class Main {
  public static void main(String[] args) {
    Employee emp = new Employee(100);
    private指定されたメンバは他クラスからアクセス不可
    System.out.println(
      "private指定のインスタンス変数へアクセス : " +  emp.id);
    // public指定されたメンバは、他クラスからアクセス可
    System.out.println(
      "public指定のメソッドへアクセス : " + emp.getId());
  }
}

最終的にPrivate変数のidをMainメソッドで返している
1.Mainクラスのmain()メソッドを実行
2.Employeeクラスをインスタンス化
3.Employeeクラスのコンストラクタが実行 idにクラス作成時の引数を代入
4.emp.getIdを実行

同クラス内のPublicメソッドを経由する事で、他クラスからprivate変数を出力している。

カプセル化

オブジェクト指向では属性と操作を一体化させて表現することをカプセル化という
属性:インスタンス変数 操作:メソッドのこと

・推奨される設定
 インスタンス変数:private
 メソッド:public

外部から属性(変数)への直接的な操作を避け、操作(メソッド)経由でのみアクセスを許可する・・・データの隠蔽

値のコピーと参照情報コピー

基本データ型:値そのものを保持する(int,char,lonj,short,doubleなど)
参照型:データ領域の中の、値が設置されている場所を保持する

基本データ型は数値のコピーを操作するため元の値は変わらない
参照型は参照場所を渡し操作するため元の値が書き換わる

スキャン 2021-09-11 14.16.JPG

ガベージコレクタ

ガベージコレクタ(ゴミ収集人):JVM上で稼働しメモリ管理を行っており、プログラムが使用しなくなったメモリ領域を検出し解放する

オブジェクトからの参照を取り除けばガベージコレクタの対象となりメモリが解放される

参照を取り除く方法
・nullを代入

スキャン 2021-09-11 19.54.JPG

・参照変数を他のオブジェクトに割り当てる

スキャン 2021-09-11 14.21 ページ 2.JPG

5章の感想

基本的なクラスやインスタンスの仕組みは認識通りでしたが、やはりルールが細かいです。

1
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
5