【Java初心者向け】クラスについて

プログラミング

ここではJava初心者に向けたクラスについて記載します。

クラスとは

クラスとは下記の2つを定義できるものという定義があります。

データ… メンバ変数のこと
処理…メソッドのこと

この2つをまとめてクラスの『メンバ』と呼びます。

クラス内にのみ、メンバ変数(データ)とメソッド(処理)を宣言できるということです。

クラス宣言の書式

アクセス修飾子 class 任意のクラス名{
       ~クラスのブロック~
 }

class:予約語
任意のクラス名:アクセス修飾子が「public」の場合、ファイル名と同名でなくてはならない
~クラスのブロック~ :メソッドの宣言文、メンバ変数の宣言文

※クラスの宣言をしないと、メンバ変数(データ)、メソッド(処理)を定義できません。
つまり、クラス宣言は必須ということです。

アクセス修飾子

・public
・なし
・private(ネストクラスのみ)

メソッドの宣言文

メソッド…処理をひとまとめにしたもの

書式
アクセス修飾子 static修飾子 戻り値の型 任意のメソッド名(引数の型 引数名){
  ~処理~
  return 戻り値;
}

アクセス修飾子

・public
・protected
・なし
・private

static修飾子

・static
・なし

戻り値の型

・値の型
・戻り値をなしとする場合は「void」を使用する

引数の型 ・引数名

引数の型は、 変数の型
引数名は、変数名
引数はカンマ区切りで複数指定可、引数なしとする場合、「()」と表記します。

注意
戻り値がない場合、不要(戻り値ありとした場合は必須)
戻り値を戻し、メソッド呼び出し文に戻る(以降の処理は実行できない)
⇒到達不能コードとなりコンパイルエラー

メソッドの特性

メソッドの宣言文はその名の通り宣言(=定義)のみのため宣言を記述しただけでは、
処理は実行できません。
メソッド宣言文内の処理を実行するにはメソッドの呼び出し文が必要です。

メソッド呼び出し文の書式イメージ

① 戻り値なしのメソッド呼び出し/戻り値を受け取らないメソッド呼び出し
 メソッド名(引数の値);
② 戻り値ありのメソッド呼び出し(戻り値を受け取る)
例)
メソッドの戻り値の型 変数名 = メソッド名(引数の値);

メソッドの動作
① 引数を受け取る (例:原料)
② 処理を実行する (例:原料を元にパンを作る) 
③ 戻り値を戻す (例:パンを返す)

エントリポイント

最初に呼び出されるメソッドのことです。
Javaのコンソールアプリでは、mainメソッドがエントリポイントにあたります。

mainメソッドの定義
アクセス修飾子 …public
static修飾子  …static
戻り値   …void
引数の型    …String配列型
メソッド名   …main

※Javaコマンド クラス名
→指定したクラスのmainメソッドを実行せよという命令文

メンバ変数

変数
ローカル変数…メソッド宣言ブロック内で宣言された変数
メンバ変数…クラス宣言ブロック内で宣言された変数

メンバ変数宣言文の書式
アクセス修飾子 static修飾子 変数の型 変数名;

例)
public class Test{
  public int val = 0; (メンバ変数)
  public static void main(String[] args){
  int val = 0; (ローカル変数)
  }
}

※ローカル変数とメンバ変数は同名であっても参照の際に区別ができるため、コンパイルは通ります。
※メンバ変数は宣言時に初期化しない場合、初期値で初期化されます。

メンバ参照

メンバの参照
メンバ変数…メンバ変数の値の参照
メソッド…メソッド呼び出し

■非staticなメンバの参照
宣言文にstatic修飾子が付与されていないメンバ

■メソッドの呼び出し文の書式
インスタンスのアドレス値.メソッド名(引数の値);

※『.』はオペランドを使用した参照の演算(左辺の値を使って右辺を参照する)です。

※引数の値は
・カンマ区切りで複数指定可
・宣言文の引数の型・数・並びと同一にすること

■メンバ変数の値の参照の書式
インスタンスのアドレス値.メンバ変数名;

■staticなメンバの参照
 宣言文にstatic修飾子が付与されているメンバ

■メソッドの呼び出し文
クラス名.メソッド名(引数の値);

■メンバ変数の値の参照  
クラス名.メンバ変数名;

インスタンスとは

クラス…設計図
インスタンス…設計図を基に作られた実体

というように例えられます。
現実のもので例を挙げると車の設計図(クラス)に例えられます。

※ここでの話は非staticなメンバについての話になります。

※クラスを基に複数のインスタンスを生成できます。
※インスタンスごとにメンバを持ちます。(それぞれが独立しています)

インスタンス化

インスタンス化とは…クラスを基にインスタンスを生成することです。

書式 
new クラス名();
※クラス名と記載していますが、本当はコンストラクタの呼び出し文です。
とりあえず、理解しやすいようにクラス名と認識して大丈夫です。

new クラス名(); と記載すると
・指定したクラスを基にインスタンスを生成
・生成したインスタンスのアドレス値を返す

※インスタンスのアドレス値は非staticなメンバの参照に使用するため
(基本的に)変数に代入します。

インスタンスのアドレス値の型は、インスタンス生成元のクラスです。
例)
インスタンス生成およびアドレス値の代入
Test test = new Test();

static・非static

非staticなメンバ…インスタンスのメンバ
staticなメンバ…クラスのメンバ

となります。

サンプルコード

// 生徒クラスの宣言文
public class Student{
  // String型のメンバ変数nameを宣言
  public String name;
  // int型のメンバ変数ageを宣言
  public int age;
  // メソッドの宣言文
  public void selfIntroduction(String message){
  // メンバ変数の値をメッセージとともに出力
  System.out.println(“名前は:” + name);
  System.out.println(“年齢:” + age);
  System.out.println(“一言:” + message);
  }
}

// 生徒クラスの宣言文
public class StudentMain{
// mainメソッドの宣言文
public static void main(String[] args){
  // Studentクラスのインスタンス化
  // (Studentクラスを基にインスタンスを生成し、
  // そのアドレスを返却する)
  Student taro = new Student();   Student jiro= new Student();
//生成したインスタンスのメンバ変数に値を代入
  taro.name = “太郎”;
  taro.age = “23”;
  jiro.name = “次郎”;
  jiro.age = “28”;
  //生成したインスタンスのメソッドを実行
  taro.selfIntroduction(“よろしくお願いいたします”);
  jiro.selfIntroduction(“次郎ですよろしく!!”);
  }
}

GC(ガーベジコレクション)

Javaはヒープ上のインスタンスが参照されなくなった時点で、
自動的に破棄します。この機能をGC(ガーベジコレクション)と呼びます。

例)
public class Test{
  public static void main(String[] args){
  Student taro = new Student(); // ①
  Student jiro = new Student(); // ②
  taro = jiro; //⇒「①」のインスタンスのGC発生 ※taroローカル変数のアドレス値を上書きしたため
  } //⇒「②」のインスタンスのGC発生 ※jiroローカル変数がスコープ外となるため
}

イメージ図

参照型(オブジェクト型)

インスタンスのアドレス値の型は、その特性から「参照型」と呼ばれます。
参照型(オブジェクト型) = クラス
※配列も参照型です。

API

APIとは…アプリケーションプログラミングインターフェースの略で、
Javaにおいては、クラス群を指します。
クラス群は、汎用的な機能を提供しています。

※JavaではAPIを「.jar」形式で提供することが多いです。
jarファイルとは…パッケージとクラスを圧縮したファイルのことです。

※APIはクラスファイルとして提供されているため、メンバ名などが不明です。
調査するにはインターネット上に公開されている「APIリファレンス」を使用して調べます。

Stringクラスの正体

JavaSEのAPIに含まれるクラス
SEはStandard Editionの略称で、メンバ変数としてchar配列型の変数を持ち、
メソッドとしてchar配列を操作する機能を持ちます。
そのため、結果として、Stringクラスは文字列を保持、操作することができます
これがStringクラスの正体です!

Stringインスタンス生成

Stringクラスのインスタンスは、new演算で生成する構文以外に、
「”文字列”」という構文で生成することができます。

書式  
“文字列”

上記は、「””」内に指定された文字列を、文字配列として保持するStringインスタンスを
「constant pool」に生成、または参照し、そのアドレス値を返す処理となります。

※new演算子を使用して作成したStringインスタンスはヒープ領域に格納されます。
※ constant poolに同じ文字配列を持つStringクラスのインスタンスが存在する場合、
そのインスタンスのアドレス値を返します。

イメージ図

Stringインスタンスが持つ文字配列の比較

「==」演算子を用いた比較は、値を比較します。
そのため、「str1 == str2」のような比較はインスタンスのアドレス値を比較してしまいます。

Stringインスタンスが持つ文字配列同士の比較方法は
Stringインスタンスの持つequalsメソッドを使用します。

equalsメソッドの宣言文

public boolean equals(Object o) 
引数のoは参照型ならどんな値でもOKです。(理由は後ほど)

疎結合と密結合

プログラムは修正のしやすさの観点から疎結合にすべきです。

密結合…同じクラスやメソッドに複数の異なる処理を記述すること
異なる処理とは入力、出力、計算処理と同じ処理とします。

疎結合…同じクラスやメソッドに単一の処理を記述すること
単一処理とは、1.入力 2.出力 3.計算処理など別々の処理にします。

良いプログラムの条件
修正に強いプログラム
・冗長でない
・疎結合である

static

static修飾子はメンバに付与でき、staticなメンバは、クラスのメンバとなります。
staticなメンバはインスタンスの観点でみると、全インスタンスの共有物となります。

イメージ図

staticなメンバの注意点

staticなメンバはパーマネントにあるクラスのものなので参照する構文は  
クラス名.メンバ名となります。

ただし、staticなメンバは非static参照することが構文上可能です。

非推奨(コンパイル・実行ともに成功するが構文と動作が一致しません(NG))
・構文は非static参照
・動作はstatic参照

※非static参照…「インスタンスのアドレス値.メンバ名」の参照
※static参照…「クラス名.メンバ名」の参照

staticなメンバ変数の使い分け

・インスタンスごとに異なる情報を持ちたければ、非staticに、共通の情報を持ちたければstaticにする
・staticなメンバはインスタンスが不要のため、インスタンスが不要な場合はstaticにする

static・非staticなメソッド

staticなメソッド

メリット…メソッドを動作させる際、インスタンスが不要
デメリット…staticなメソッドから非staticなメンバをメンバ名だけで参照できません。

■メンバ名のみの参照
メンバ名だけでメンバの参照を行う構文は、
メンバ名のみで参照する処理を記述したメソッドが所属するインスタンス(非static)
もしくはクラス(static)のメンバを参照するという意味となります。

メンバ名のみの参照ルール

・非staticなメソッド内で、非staticなメンバをメンバ名のみで参照 →
・非staticなメソッド内で、staticなメンバをメンバ名のみで参照  →○(非推奨)
・staticなメソッド内で、非staticなメンバをメンバ名のみで参照  →×
・ staticなメソッド内で、staticなメンバをメンバ名のみで参照  →

staticなメソッドまとめ

・非staticなメソッド
インスタンスごとに動作する必要がある場合、非staticメソッドにする

・staticなメソッド
インスタンスごとに動作する必要がない場合、staticメソッドにする

アクセス修飾子

クラス・メンバに付与でき、クラス・メンバの参照範囲を決定します。

隠ぺい
アクセス修飾子「private」を使用して、外部のクラスからメンバを不可視にすることです。

カプセル化
隠ぺいされたメンバを他クラスからメソッドを通してのみ操作できるようにすることです。
→限定された機能のみを外部に提供する(読み込み、書き込みなど)

アクセサ
隠ぺいされたメンバを操作するメソッドをアクセサと呼ぶ
以下、代表例
getter…隠ぺいされたメンバ変数の値を返すメソッド(read)
setter…隠ぺいされたメンバ変数の値を更新するメソッド(write)
命名規則…getもしくはset+メンバ変数名(頭文字は大文字)

※重要
メンバ変数は(基本的に)隠ぺいし、必要に応じてアクセサを用意すること!
メンバ変数は(基本的に)カプセル化すること!!

具体例
銀行のシステムにおいて、残高(メンバ変数)を隠蔽し、残高照会機能(アクセサ)を外部に提供する。
残高を隠蔽しないと外部から残高を自由に変更できてしまい非常に危険ですからね。

オーバーロード

同一クラスに同一メソッド名でメソッドを宣言することを「オーバーロード」と呼びます。
コンパイル、実行ともにOKです。
なぜならメソッドを呼び出し文で区別できるので、メソッド呼び出し文は
「引数の型」「数」「並び」で区別できるためです。

OKな例

public void method(){~}
public void method(String val){~}
public void method(int ival,String val){}
public void method(String val,int ival){~}

NGな例

public void method(String abc){~}
public int method(String val){~}
public static void method(String val){~}

オーバーロードのメリット

引数は異なるが、同じ処理を持つメソッドを、
あたかも同一のメソッドであるかのように呼び出せます。

例)オーバーロードあり

System.out.println(“A”);
System.out.println(10);
異なるメソッドだが、同じ処理(引数の値を標準出力)している

オーバーロードなし
System.out.printlnString(“A”);
System.out.printlnInteger(10);

コンストラクタ

タイトルとURLをコピーしました