Javaについて、理解を深めるためにまとめる。
随時更新していく。
参考文献
☆中山清喬/国本大悟『スッキリわかるJava入門 第3版』
流れ
①ソースコードの作成
ソースファイルの拡張子は.java
②コンパイル
$ javac ソースファイル名①.java ソースファイル名②.java
$ javac Split.java SplitLogic.java
・コンパイラ(:ソフトウェア)を使って、ソースファイルをクラスファイルに変換させる
=クラスファイルの作成
・拡張子は.class
・バイトコード(ソースコードの命令をコンピュータが認識できるようにしたコード)を含む
③実行
$ java クラスファイル名
$ java Split
//java SplitLogicでは起動できない
エラー: メイン・メソッドがクラスSplitLogicで見つかりません。
//パッケージに属したクラスの実行
$ java 起動するクラスのFQCN
$ java splitapp.main.Split
・インタプリタ(:ソフトウェア)がJVM(Java Virtual Machine)を用いて、バイトコードの解読を行う
・mainメソッドに含まれる
クラス名を指定する必要がある
JARファイル
jar -cvf クラスファイル名.jar *.class //作成
「クラスファイル名.mf」ファイル内に「Main-Class: クラスファイル名」を記述 //行の終わりは改行
jar -cvfm クラスファイル名.jar クラスファイル名.mf *.class //マニュフェストファイルの作成
java -jar クラスファイル名.jar //実行
複数のクラスを1つにまとめるZIPファイルと似たアーカイブファイル
基本構造
public class クラス名 { //クラスブロック
public static void main(String[] args) { //メソッドブロック
}
}
クラス名はアルファベット大文字
始まり
ブロックによる二重構造
変数
宣言
データ型 変数名;
初期化
データ型 変数名 = 値;
String likes = "ねこ"; //変数の初期化 ※宣言と代入の同時化
likes = "いぬ"; //再代入 ※「ねこ」が上書きされる
System.out.println(likes + "が好きです");
データ型
[整数] 小
byte
:かなり小さい 例)byte glasses; glasses = 7;
short
:小さい 例)short age; age = 7;
★int
:通常 例)int salary; salary = 7777;
long
:大きい 例)long Japanese; Japanese = 124_000_000L;
[小数] 大
float
:あいまい 例)float weight; weight = 60.0F;
★double
:通常 例)double height; height = 177.7;
※金額に対しての使用はNG(厳密な計算が難しいため)
[真偽値]
boolean
:trueかfalse 例)boolean isValid;
[文字]
char
:1文字のみ 例)char color; color = '緑';
※シングルクォーテーション
が必須
[文字列]
★String
:文字の並び 例)String name; name = "John"
※ダブルクォーテーションでOK
定数(final付きの変数)
宣言
final データ型 定数名 = 初期値; ※定数名はすべて大文字が基本
final double PI = 3.14; //定数の宣言
int pie = 7;
PI = 10; //コンパイルエラーの確認
System.out.println("半径" + pie + "cmの円の面積は");
System.out.println(pie * pie * PI);
【目的】書き換え防止のため
式(計算式や宣言式など)
オペランドと演算子から成り立つ
オペランド
❶式に使う値のこと
❷ソースコードでの具体的な指定値はリテラル
と呼ばれる
➡データ型によって、表記方法が異なる
エスケープシンス
String型やchar型で使用される特殊文字
¥"
ダブルクォーテーション
¥'
シングルクォーテーション
¥¥
円記号(¥)
¥n
改行
評価
3原則による式に従った計算処理のこと
①評価結果への置換
演算子はオペランドを用いた計算を行い、計算結果にたどり着く
②優先順位
2 + 7 * 10 = 72 //掛け算が優先
(2 + 7) * 10 = 90 //かっこで囲むことで優先できる
複数の演算子がある場合、Javaのルールに従って優先される
③結合規則
同じ優先順位の演算子が複数ある場合、演算子ごとに定まった方向順が優先される
+演算子
:左から
=演算子
:右から
演算子
式に使う記号のこと
算術演算子(+、ー、*、/、%)
❶すべて左
から
❷優先順位も高め
文字列結合演算子(+)
❶同じく左
から
❷優先順位も高め
代入演算子(=、+=、ー=、*=、/=、%=)
❶すべて右
から
❷優先順位は低い
❸最後に行われるもの
インクリメント/デクリメント演算子(++、ーー)
❶単項演算子とも呼ばれる
❷JavaScriptと同じ
❸最も優先度が高い
❹他演算子と併用しない
ことが望ましい(バグの原因になる恐れがある)
データ型の変換
①代入時の自動型変換
float y = 7; //代入時の自動型変換
double z = y; //代入時の自動型変換
int w = 0.7; //型より小さい型はコンパイルエラーになる
byte q = 2; //byte・short型にint型の代入は例外
各型より大きい型に対しての代入は値が自動的に変換される仕組み
②強制的な型変換
int e = (int)7.7; //キャスト演算子
キャスト演算子
定義
(変換先の型名)値;
強制的な変換の指示を行う
[デメリット]
データの一部を破損してまでも変換を行うため、データの中身が欠落する
➡︎上記の場合、小数点以下が出力されなくなる
そのため、余程の理由がない限り使用しないこと
が望ましい
③演算時の自動型変換
long b = 7 + 7L; //intをlongに変換
double c = 7.7 * 2; //intをdoubleに変換
String msg1 = 7 + "が好きです"; //intをStringに変換
【原則】同じ型同士
【例外】異なる型同士 ➡➡➡ 比較して大きな型へ自動的に統一される
命令実行
定義
命令文(引数);
int p = 1, o = 2;
int m = Math.max(p, o); //値を比較して大きいものを代入する
System.out.println(m); //画面に表示する
System.out.print(m); //画面に表示する(改行なし)
String age = "12";
int n = Integer.parseInt(age); //文字列を数値に変換する
System.out.println("年齢は" + n + "です");
int r = new java.util.Random().nextInt(7); //乱数を発生させる
System.out.println("年齢は" + r + "ですか?");
System.out.println("名前を入力してください");
String name = new java.util.Scanner(System.in).nextLine(); //キーボードから1行の文字列入力を受け取る
System.out.println("年齢は?");
int age1 = new java.util.Scanner(System.in).nextInt(); //キーボードから1つの整数入力を受け取る
System.out.println("いらっしゃい!" + age1 + "歳の" + name + "さん");
制御構文
❶条件式とブロックから成り立つ
❷仕組みはJavaScriptと似ている
条件式
文字列型の変数.equals(比較対象の文字列)
if (str.equals("おはよう"))
❶等しいを表すのは==
・・・文字列
の比較はできない
条件分岐
①if-else文
②if文
③if-else if-else文
elseブロックが空なら、丸ごと省略が可能
④switch文
if文をスマートにしたもの
条件❶左右辺が一致する式であること
❷比較値が小数と真偽値でないこと
※caseラベルの末尾にはbreak文
繰り返し
①while文
前置判定(ブロック実行前に条件式の評価を行う)
②do-while文
do {
temp++;
System.out.println("1度上がりました");
} while(temp > 27);
後置判定(ブロック実行後に条件式の評価を行う)
最低でも1回
は処理が行われる
③for文
for (int 変数名 = 0; 変数名 < 繰り返す値; 変数名++)
for (int 変数名 = 1; 変数名 < 繰り返す値; 変数名++) //ループ変数を1から始める
for (int 変数名 = 0; 変数名 < 繰り返す値; 変数名 += n) //ループ変数をnずつ増やす
for (int 変数名 = n; 変数名 > 1; 変数名--) //ループ変数をnから1ずつ減らす
for (; 変数名 < n; 変数名++) //ループ変数を初期化しない
for (int 変数名 = 0; 変数名 < 繰り返す値;) //繰り返し処理を行わない
JavaScriptと似ている
繰り返す回数が定まっている場合
に使われる
その他
繰り返しの中断
JavaScriprと似ている
①break文
②continue文
無限ループ
①while (true) {
処理
}
②for (;;) {
処理
}
中断されない限り、意図的
にループし続ける
配列
JavaScriptと似ている
宣言
データ型[] 配列変数名;
int[] scores;
代入
配列変数名 = new データ型[値];
scores = new int[5];
初期化
①データ型[] 配列変数名 = new データ型[] {値};
②データ型[] 配列変数名 = {値};
int[] scores = new int[] {10, 20, 30, 40, 50};
int[] scores = {10, 20, 30, 40, 50};
※初期化するための値設定
boolean:false
String:null
それ以外:0
要素数の取得
配列変数名.length
int num = scores.length;
文字列変数名.length();
String str = "Javaを学ぶ";
System.out.println(str.length());
エラー
ArrayIndexOutOfBoundsException
【原因】存在しない要素を使用しているため
for文との組み合わせ
①ループによる全要素の利用
for (int i = 0; i < 配列変数名.length; i++) {
配列変数名[i]を用いた処理
}
for (int i = 0; i < scores.length; i++) {
System.out.println(scores[i]); //ループ毎にiが変化する
}
②ループによる集計
int sum = 0; //変数の初期化
for (int i = 0; i < scores.length; i++) {
sum += scores[i]; //1科目ずつsumに合算する
}
int count = 0;
for (int i = 0; i < scores.length; i++) {
if (scores[i] >= 25) {
count++; //条件に合致する要素をカウントする
}
}
③添え字に対応した情報の利用
int[] seq = new int [10];
for (int i = 0; i < seq.length; i++) {
seq[i] = new java.util.Random().nextInt(4);
}
for (int i = 0; i < seq.length; i++) {
char[] base = {'A', 'T', 'G', 'C'};
}
System.out.println(base[seq[i]] + " ");
④拡張for文
for (データ型 変数名 : 配列変数名) {
処理
}
int[] scores = {10, 20, 30, 40, 50};
for (int value : scores) {
System.out.println(value);
}
要素を1つ
ずつ取り出すループ専用
通常のfor文より、ループ変数や添え字の記述なしでスッキリした形になる
後片付け
ガベージコレクション
boolean valid = true;
if (valid == true) {
int[] array = {2. 4. 6}
} //この時点でarrayはメモリからなくなる
newで確保された3要素はブロックが終了しても残り続ける(ゴミ)
・・・どの配列変数からも参照されない
そんなゴミを自動で探して片付けてくれる仕組み
null
int[] array = {1, 3, 5};
array = null;
array[0] = 9;
参照型変数にのみ代入が可能
意図的に配列の参照を行わないようにする=参照を切る
エラー
NullPointerException
【原因】nullが格納された配列変数を利用すると起こる
宣言
データ型[][] 配列変数名 = new データ型[行数][列数];
int[][] scores = new int[3][3];
使用方法
配列変数名[行の添え字][列の添え字]
System.out.println(scores[1][1]
メソッド
❶複数の文で書かれた処理コードを1つ
にまとめて名前をつけたもの
❷メソッドを定義する立場と呼び出す立場が常に同じではない
ことに注意
➡︎開発は複数人で行うことが多いため
❸メソッド名は処理内容がわかるもの
が望ましい
[メリット]
①コードの見やすさから、把握が容易
②機能ごとのメソッドに分けることで、修正範囲が限定できる(エラーの 原因元を探しやすくする)
③メソッドは使い回しができるため、作業効率化を図れる
定義
①public static 戻り値のデータ型 メソッド名(引数リスト) {
②メソッドの呼び出しにより実行される具体的な処理
}
public static void hello() {
System.out.println("こんにちは"); //メソッドブロック=実行内容
}
[2段階構成]
①重要事項の表明
②処理内容
呼び出し
メソッド名(引数リスト);
public static void main(String[] args) {
System.out.println("メソッドの呼び出し"); //mainメソッドブロック
hello(); //メソッドの呼び出し
methodA(); //methodBを含むmethodAが呼び出される
}
public static void methodA() {
System.out.println("A");
methodB();
}
public static void methodB() {
System.out.println("B");
}
・・・定義するだけでは実行されない
^^メソッドの記述順に決まりはない(mainメソッドが中心になるため)
引数
メソッド名() //何も渡さない
メソッド名(値) //1つ渡す
メソッド名(値1, 値2・・・) //複数渡す
① public static void main(String[] args) {
hello("田中"); //引数の定義(1つ)
hello("佐藤");
hello("鈴木");
}
public static void hello(String name) { //文字列型変数nameを定義
System.out.println(name + "さん、こんばんは");
}
② public static void main(String[] args) {
add(100, 200); //引数の定義(2つ)
add(10, 20);
}
public static void add(int x, int y) {
int ans = x * y;
System.out.println(ans);
}
❸ public static void main(String[] args) {
methodC("さようなら", 777);
}
public static void methodC(int x, String y) { //コンパイルエラー
System.out.println(x + y);
}
❹ public static void main(String[] args) {
int a = 7;
int b = 77;
add();
}
public static void add() {
int ans = a + b; //コンパイルエラー
System.out.println(a + b);
}
❶メソッドで定義するデータ型と順番に注意
❷引数と変数の各データ型が異なるとコンパイルエラーになる
仮引数
:受け取る変数 ➡➡➡︎ ここで言うx、y
実引数
:渡す変数 ➡︎➡➡ ここで言う100、200、10、20
❸スコープにより、mainメソッドで定義した変数は別メソッドでの使用不可
ローカル変数
:メソッド内で宣言した変数 ➡➡➡︎ ここで言うmain()、add()
そのメソッド内でのみ
有効なため、別メソッドの同名ローカル変数はまったくの別物
戻り値
public static 戻り値のデータ型 メソッド名(引数リスト) { //戻り値のデータ型はreturnによって戻される値と同じ型
メソッドの呼び出しにより実行される具体的な処理
return 戻り値; //戻り値は変数名やリテラル(100、"hello"など)を指定する
}
public static int add(int x, int y) {
int ans = x + y;
return ans;
}
❶何も戻さない場合は、データ型にvoid
を使う
❷return文は「値を戻す」だけでなくメソッドを終わらせる
意味を持つ
^^^^return文後に処理コードを書くとコンパイルエラーになる
呼び出し
データ型 変数名 = メソッド名(引数リスト); //メソッドの呼び出しが優先される
① public static void main(String[] args) {
int ans = add(100, 200); //呼び出し
System.out.println("100 + 200 = " + ans);
}
② public static void main(String[] args) {
System.out.println(add(add(100, 200), add(10, 20))); //戻り値をそのまま使用
}
必ずしも変数で戻り値を受け取る必要はない
オーバーロード(多重定義)
①public static void main(String[] args) {
System.out.println(add(7, 77));
System.out.println(add(7.7, 77.7));
System.out.println(add("yahoo", "google"));
}
public static int add(int x, int y) {
return x + y;
}
public static double add(double x, double y) {
return x + y;
}
public static String add(String x, String y) {
return x + y;
}
②public static void main(String[] args) {
System.out.println(add("7 * 77 = " + add(1, 2))); //*が呼び出される
System.out.println(add("7 * 77 * 2 = " + add(1, 2, 3))); //#が呼び出される
}
public static int add(int a, int b) {
return a + b; //*
}
public static int add(int a, int b, int c) {
return a + b + c; //#
}
【原則】メソッドに同名を名付けることはできない(たとえ似たような処理内容だとしても)
それを可能にする
仕組み
【例外】①メソッドの仮引数のデータ型が異なる場合(ここで言うint、double、String)
②メソッドの仮引数の要素数が異なる場合(ここで言うa・b、a・b・c)
引数(配列ver)
public static void main(String[] args) {
int[] array = {1, 3, 5};
printArray(array); //配列を渡す
}
public static void printArray(int[] array) { //引数に配列指定
for (int element : array) {
System.out.println(element);
}
}
値渡し
:値そのものが渡される呼び出しのこと
配列を用いる場合は値(ここで言う1、3、5)ではなく要素のアドレス
がコピーされる
参照渡し
:引数としてアドレスを渡すこと
➡︎呼び出し先での書き換えは呼び出し元にも反映される
戻り値(配列ver)
public static void main(String[] args) {
int[] array = makeArray(3);
for (int i : array) {
System.out.println(i);
}
}
public static int[] makeArray(int size) {
int[] newArray = new int[size];
for (int i = 0; i < newArray.length; i++) {
newArray[i] = i;
}
}
コマンドライン引数
String[] args
プログラム起動時にそのプログラムに渡す値
その値はmainメソッド
に渡される
起動
java プログラム名 引数リスト
java Sample abc def ghi
java Sample 1 2 3
部品化
ファイル毎に開発分担(クラスを分割させる)を行う手法
^^^^プログラムの完成品は複数のソースファイルの集合体のことが多い
①処理メソッドのみのソースファイルの作成
public class SplitLogic {
public static int tasu(int a, int b) {
return (a + b);
}
public static int hiku(int a, int b) {
return (a - b);
}
}
②mainメソッドの呼び出しの修正
public class Split {
public static void main(String[] args) {
int a = 7; int b = 1;
int total = SplitLogic.tasu(a, b); //ここ
int delta = SplitLogic.hiku(a, b); //ここ
System.out.println("足したら" + total + "、引いたら" + delta);
}
}
処理メソッドがmainメソッドに所属しなくなったため、所属先を明記して呼び出す必要がある
パッケージ
クラス毎のグループに分類・管理できる仕組み
定義
package 所属させるパッケージ名;
package splitapp.main;
public class Split {
}
package splitapp.logics;
public class SplitLogic {
}
ソースコードの先頭
に書かなければならない
小文字
が一般的
パッケージ同士に親子関係や階層関係はない
(それぞれ独立したもの)
デフォルトパッケージ
:どのパッケージにも属していないこと(無名パッケージ
とも)
import文が使用できない
FQCN(完全限定クラス名もしくは完全修飾クラス名)
パッケージ名.クラス名
package splitapp.main;
public class Split {
int total = splitapp.logics.SplitLogic.tasu(a, b); //ここ
int delta = splitapp.logics.SplitLogic.hiku(a, b); //ここ
}
別パッケージにあるクラスを呼び出すには、その所属パッケージを指定しなければならない
import文
import パッケージ名.クラス名;
package splitapp.main;
import splitapp.logics.SplitLogic; //SplitLogicのみをインポートする場合
import splitapp.logics.*; //すべてをインポートする場合
import splitapp.main.*; //すべてをインポートする場合
※import splitapp.*; //これではすべてをインポートできない
//どちらの表記でも構わない
int total = SplitLogic.tasu(a, b);
int delta = splitapp.logics.SplitLogic.hiku(a, b);
FQCNの省略が可能
packageより後
に記述
あくまで入力軽減機能
名前空間
付けられる名前のキャパ
名前の衝突
:異なる内容のクラス同士で同じ名前を取り合うこと
パッケージが異なれば、同じ名前は使える(FQCNで区別できるため)
➡︎そのため、パッケージ名の衝突を避ける必要がある
自社ドメインを前後逆順にしたパッケージ名が推奨(java.example.comならcom.example.java)
Java API
public class Main {
public static void main(String[] args) {
int[] heights = {170, 150, 160, 180};
java.util.Arrays.sort(heights); //java.utilパッケージのArraysクラスにあるsortメソッドを呼び出す
for (int h : heights)
System.out.println(h);
}
}
}
❶Javaにもともと組み込まれているパッケージやクラスの総称
❷自由に利用ができる
APIリファレンス
:APIの説明書
(https://www.oracle.com/jp/java/technologies/javase/documentation/api-jsp.html)
[代表的なパッケージ]
java.lang
:不可欠なクラス群(System、Integer、Math、Object、String、Runtimeなど)
自動でインポートされる
java.util
:プログラミングに便利なクラス群
java.math
:数字に関するクラス群
java.net
:通信を行うクラス群
java.io
:データの逐次処理を行うクラス群
オブジェクト指向(プログラミング)
❶ソフトウェアの開発時に用いる部品化の考え方
❷基本文法とは学ぶものや学び方が異なるため、注意
^^^正解自体ではなく、その正解に辿り着くため
の考え方を学ぶ
❸現実世界に登場する対象物単位で、プログラムをクラスに分割して捉える
←→手続き型プログラミング
(:1行1行実行する手順を定めなければならない)
❹各クラスには責務(行動責任や情報保持責任)
が書き込まれるため、ひとつひとつ指示する必要がない
^^^責務を行うために、各々が属性
と操作
を持つ
[メリット]
(①人間が把握しやすいプログラム開発の実現ができる)
(②プログラムの変更が容易になる)
(③プログラムの一部を転用しやすい)
^^^ラクして、楽しく、良いものが作れるようになる
^^^現実世界の対象物とその動きをPC上の仮想世界で再現する
だけの話だから
①継承
既存部品を流用して、新たな部品を作る
②多態性
類似する部品を同じ扱いにできる
③カプセル化
指定部品が属性や操作を利用できない状態にする
インスタンス
仮想世界
(:コンピュータのメモリ領域)のパフォーマー(を生み出すのがクラス)
➡︎インスタンス化
^^^ヒープ
(:その領域のこと)の中に確保されたメモリ領域
・・・そのままでは動かないため、各登場人物のクラスとは別に指示役のクラス(mainメソッドを含む)
を用意する
クラス名 変数名 = new クラス名(); //インスタンスの生成
変数名.フィールド名 = 値; //フィールドへ代入
変数名.メソッド名(); //メソッドの呼び出し
public class Kamisama {
public static void main(String[] args) {
Sword s = new Sword();
s.name = "ちゅんちゅんせいばー";
s.damage = 10;
Hero h1 = new Hero(); //インスタンスの生成 --ここで勇者が誕生
h1.name = "ちゅんちゅん丸"; //フィールドへ代入
h1.hp = 100;
h1.sword = s; --swordインスタンスをsに代入
Hero h2 = new Hero();
h2.name = "ちゃんちゃん丸";
h2 = h1; //h1をh2へコピー --番地情報がコピーされている(インスタンスそのものではなく)
h2.hp = 200;
System.out.println("勇者" + h1.name + "が誕生しました。")
System.out.println("装備している武器は" + h1.sword.name + "です。"); --勇者h1「の」sword「の」name
h1.sit(3); //メソッドの呼び出し
h1.slip();
w.heal(h1);
System.out.println("きのこ星人" + m1.suffix + "が出現しました。");
h1.attack();
h1.run();
}
}
オブジェクト指向によって、mainメソッドの中身がわかりやすくなる
参照
:変数に入っているアドレス情報
JVMが参照の解決
もしくはアドレス解決
(:変数から番地情報を取得、番地にアクセス)を行なっている
独立性
:同一クラスでも異なるインスタンスであれば、影響を受け合わないこと
クラス
クラス図(:設計図)
を基に定
UML(Unified Modeling Languages:世界共通設計図)の1つ
定義
public class Hero { //クラスの宣言
String name; //属性の宣言
int hp;
Sword sword; --装備の情報
public void attack() {
System.out.println(this.name + "は" + this.sword.name + "で攻撃をした。");
System.out.println("敵に5のダメージを与えた。");
}
public void sleep() { //操作の宣言--メソッド
this.hp = 100; //thisキーワード
System.out.println(this.name + "は休んで回復した。");
}
public void sit(int sec) { //何秒座るかの引数
this.hp += sec; //座る秒数分回復
System.out.println(this.name + "は" + sec + "秒座った.");
System.out.println("HPが" + sec + "ポイント回復した。");
}
public void slip() {
this.hp -= 5; //転ぶことでHPが減る
System.out.println(this.name + "は転んだ.");
System.out.println("5のダメージ");
}
public void run() {
System.out.println(this.name + "は逃げ出した.");
System.out.println("ゲームオーバー");
System.out.println("最終HPは" + this.hp + "でした。");
}
----
public class Matango {
int hp;
int level = 10; //属性の初期値指定
final int LEVEL = 10; //定数フィールド(大文字推奨)
char suffix;
}
----
public class Sword {
String name;
int damage;
}
----
public class Wizard {
String name;
int hp;
public void heal(Hero h1) { --引数にメソッドを用いた場合
h1.hp += 10;
System.out.println(h1.name + "のHPを10回復させた");
}
}
フィールド
:クラスブロック内で宣言された変数(ここで言うname、hp)
定数フィールド
:値の書き換え不可の変数(ここで言うLEVEL)
メンバ
:フィールドやメソッドの総称
has-aの関係
➡︎あるクラスが別クラスをフィールドとして利用すること
❶オブジェクト指向でのメソッドでは、static
は使わない
❷this
は省略しない(動作の不具合をなくすため)
❸クラス定義によってインスタンスの生成
とインスタンス用クラス型変数の利用
ができる➡︎追加で使えるようになる型
❹Stringも同じクラス型に分類される➡︎特別にnew演算子を使わずにString 変数名 = "文字列";
でインスタンス生成が可能
宣言
Hero h; //クラス型変数名 変数名;
インスタンスはクラス型変数に入れて利用される
➡︎仮想世界に複数存在しうる同名インスタンスの中から特定のインスタンスをプログラムとして識別する
ため
コンストラクタ
インスタンス生成後に自動実行処理されるメソッド
➡︎直接呼び出すことはできない
(あくまでもコードを元にJVMが行う)
[条件]
①メソッド名がクラス名と等しく同じ
②メソッド宣言に戻り値の記載がない(voidを含む)
public class クラス名 {
クラス名() {
自動実行する処理内容
}
}
[フィールドの初期値]
数値型(int、short、longなど):0
char型:¥u0000
boolean型:false
配列型(int[ ]など):null
クラス型(Stringなど):null
public class Hero {
String name;
int hp;
Sword sword;
public void attack() {
省略
}
public void sleep() {
省略
}
public void sit(int sec) {
省略
}
public void slip() {
省略
}
public void run() {
省略
}
public Hero() { //インスタンス生成後に自動実行されるメソッド
this.hp = 100;
}
}
----
public Hero(String name) { //文字列を引数として1つ受け取る ※インスタンスに必ず名前を設定しなければならない
this.hp = 100;
this.name = name; --引数値でnameフィールドを初期化
}
public Hero() { --引数を受け取らないコンストラクタも一緒に作っておく
this.hp = 100;
this.name = "さんぷる";
}
----
public class Kamisama {
public static void main(String[] args) {
Hero h1 = new Hero("ぴょんぴょん丸"); --コンストラクタに渡す引数を生成と同時に行う
Hero h2 = new Hero(); -引数がないので、「さんぷる」が呼び出される
h2.hp = 200;
}
}
----
public class Kamisama {
public static void main(String[] args) {
Hero h1 = new Hero(); --コンストラクタによってHP100が設定される
h1.name = "ぴょんぴょん丸";
h1.sword = s;
Hero h2 = new Hero();
h2.name = "ちゅんちゅん丸";
h2.hp = 200; --新たな数値設定により、変更が可能
System.out.println("勇者" + h1.name + "が誕生しました。");
System.out.println("HPは" + h1.hp + "です。");
System.out.println("勇者" + h2.name + "が誕生しました。");
System.out.println("HPは" + h2.hp + "です。");
}
}
❶mainメソッドで初期値設定をせずに済む
❷オーバーロード(多重定義)はコンストラクタでも可能
❸複数のコンストラクタがある場合、JVMが引数を見て判断してくれる(動作するのは1つのみ)
【例外】
クラスに1つもコンストラクタが定義されていない場合
デフォルトコンストラクタ
(:引数&処理内容なし)がコンパイル時に自動追加される
this(引数); //同クラス内の別コンストラクタの呼び出しをJVMに依頼する
public Hero(String name) {
this.hp = 100;
this.name = name;
}
public Hero() {
this("さんぷる");
}
❶コンストラクタの先頭
に記述しなければならない
❷「this.メンバ名」とはまったくの別物
であるため、注意