メソッドとは?
**メソッド(Method)は特定の作業を行うコードブロックです。他の言語では関数(Function)**とも呼ばれます。
メソッドが必要な理由
繰り返されるコードをメソッドにすると:
- ✅ コードの重複を除去
- ✅ 保守性向上
- ✅ 再利用可能
// 悪い例: コードの重複
int sum1 = 10 + 20;
System.out.println("合計: " + sum1);
int sum2 = 30 + 40;
System.out.println("合計: " + sum2);
int sum3 = 50 + 60;
System.out.println("合計: " + sum3);
// 良い例: メソッドで重複除去
public static void printSum(int a, int b) {
int sum = a + b;
System.out.println("合計: " + sum);
}
printSum(10, 20);
printSum(30, 40);
printSum(50, 60);
💡 メソッド = 数学の関数: 入力値を入れると → 計算された結果が出力
メソッドの定義
基本構造
修飾子 戻り値型 メソッド名(パラメータリスト) {
// メソッド本文
return 戻り値; // 戻り値型がvoidでない場合
}
構成要素
public static int add(int a, int b) {
int sum = a + b;
return sum;
}
1. 修飾子 (Modifier): public, static
- 今は
public staticで記述 (後で詳しく説明)
2. 戻り値型 (Return Type): int
- メソッド実行後に返されるデータの型
- 戻り値がない場合は
voidを使用
3. メソッド名 (Method Name): add
- メソッドを呼び出す際に使用する名前
- 一般的に動詞で始める (例:
add,calculate,print)
4. パラメータ (Parameter): int a, int b
- メソッドに渡される入力値
- 不要な場合は空にできる (選択事項)
5. メソッド本文 (Method Body): { ... }
- 実際に実行されるコード
6. return文 (Return): return sum;
- メソッドの結果値を返す
-
voidの場合は省略可能
メソッドの呼び出し
// メソッド定義
public static int add(int a, int b) {
return a + b;
}
// メソッド呼び出し
public static void main(String[] args) {
int result = add(10, 20); // 10と20を渡す
System.out.println(result); // 30出力
}
用語整理
int result = add(10, 20);
↑ ↑ ↑
メソッド名 引数
public static int add(int a, int b)
↑ ↑
パラメータ
引数(Argument): メソッド呼び出し時に渡す値
- 例:
add(10, 20)の10,20
パラメータ(Parameter): メソッド定義時に宣言する変数
- 例:
add(int a, int b)のint a,int b
💡 メソッド呼び出し時、引数がパラメータに代入されます。
型と個数が一致する必要がある
// メソッド定義
public static void call(String str, int age) {
System.out.println(str + ", " + age);
}
// 正しい呼び出し
call("Hello", 20); // OK: String, int順序一致
// 誤った呼び出し
call(20, "Hello"); // エラー! 型順序不一致
call("Hello"); // エラー! パラメータ個数不一致
戻り値型
値を返すメソッド
public static int add(int a, int b) {
int sum = a + b;
return sum; // 必ず値を返す必要がある
}
int result = add(5, 3); // 8が返されてresultに保存
System.out.println(result); // 8
戻り値型がある場合:
- ✅ 必ず
return文で値を返す必要がある - ✅ 戻り値の型が戻り値型と一致する必要がある
値を返さないメソッド (void)
public static void printMessage(String message) {
System.out.println(message);
return; // voidの場合省略可能
}
printMessage("こんにちは"); // 戻り値なしで呼び出し
voidメソッド:
- ✅
return;文省略可能 - ✅ 戻り値を受け取らずに呼び出し
- ✅ 単純に作業のみ実行
returnの特徴
public static void checkAge(int age) {
if (age < 18) {
System.out.println("未成年です。");
return; // メソッド即時終了!
}
System.out.println("成人です。"); // age >= 18の時のみ実行
}
returnに出会うとメソッドが即座に終了します。
パラメータがないまたは戻り値がない場合
// 1. パラメータも戻り値もない場合
public static void printHeader() {
System.out.println("=== プログラム開始 ===");
}
printHeader(); // パラメータなしで呼び出し
// 2. パラメータはあるが戻り値がない場合
public static void printInfo(String name, int age) {
System.out.println("名前: " + name + ", 年齢: " + age);
}
printInfo("田中太郎", 25); // 戻り値なしで呼び出し
// 3. パラメータはないが戻り値はある場合
public static int getTen() {
return 10;
}
int num = getTen(); // 10が返される
Javaの核心原則: 値のコピー
🔥 Javaは常に変数の値をコピーして代入します。
プリミティブ型の値コピー
public static void changeNumber(int num) {
num = 20; // コピーされた値のみ変更
System.out.println("メソッド内部: " + num); // 20
}
public static void main(String[] args) {
int original = 10;
changeNumber(original); // 値をコピーして渡す
System.out.println("main: " + original); // 10 (原本そのまま!)
}
出力:
メソッド内部: 20
main: 10
なぜ原本が変わらないのか?
[mainメソッド] [changeNumberメソッド]
original = 10 num = 10 (コピーされた値)
↓ 値コピー ↓ 値変更
original = 10 (そのまま) num = 20
- メソッドに値を渡す時、原本変数が移動するのではない
- 変数に入っている値を読んでコピーして渡す
- したがって原本は絶対に変更されない
参照型の値コピー (参照値コピー)
public static void changeArray(int[] arr) {
arr[0] = 100; // 参照値でアクセスして配列内容変更
}
public static void main(String[] args) {
int[] numbers = {1, 2, 3};
changeArray(numbers); // 参照値をコピーして渡す
System.out.println(numbers[0]); // 100 (変更された!)
}
参照型も値コピーが正しいです!
- ただしコピーされる値が**参照値(アドレス)**なだけ
- 同じ参照値を持つので同じ配列を指す
- したがって配列の内容は変更される
[main] [changeArray]
numbers [x001] ----+----> arr [x001]
| ↓
+----> [100, 2, 3]
メソッドで値を変更するには?
public static int changeNumber(int num) {
num = num * 2;
return num; // 変更された値を返す
}
public static void main(String[] args) {
int value = 10;
value = changeNumber(value); // 戻り値を再代入
System.out.println(value); // 20
}
メソッドの結果を受け取って再代入する必要があります!
型変換とメソッド
明示的型変換
public static void printNumber(int num) {
System.out.println(num);
}
double number = 1.5;
printNumber((int) number); // 明示的型変換必要
自動型変換
public static void printNumber(double num) {
System.out.println(num);
}
int number = 10;
printNumber(number); // int → double 自動型変換
💡 パラメータに値を渡すことも結局変数に値を代入することなので、型変換規則がそのまま適用されます。
メソッドオーバーロード(Overloading)
オーバーロード: 同じ名前のメソッドをパラメータだけ変えて複数定義すること
// 2つの数の合計
public static int add(int a, int b) {
return a + b;
}
// 3つの数の合計 (オーバーロード)
public static int add(int a, int b, int c) {
return a + b + c;
}
// 実数2つの合計 (オーバーロード)
public static double add(double a, double b) {
return a + b;
}
// 使用
int sum1 = add(1, 2); // 最初のメソッド呼び出し
int sum2 = add(1, 2, 3); // 2番目のメソッド呼び出し
double sum3 = add(1.5, 2.5); // 3番目のメソッド呼び出し
オーバーロード規則
✅ オーバーロード可能:
- パラメータの型が異なる場合
- パラメータの個数が異なる場合
- パラメータの順序が異なる場合
void method(int a, String b) { }
void method(String a, int b) { } // OK: 順序が異なる
❌ オーバーロード不可:
- パラメータは同じで戻り値型のみ異なる場合
- パラメータ名のみ異なる場合
int method(int a) { }
double method(int a) { } // エラー! 戻り値型のみ異なる
void method(int num) { }
void method(int value) { } // エラー! 名前のみ異なる
メソッドシグネチャ(Signature)
メソッドシグネチャ = メソッド名 + パラメータ型(順序)
int add(int a, int b)
↑ ↑ ↑
メソッド名 型 型
↓
シグネチャ: add(int, int)
シグネチャに含まれないもの:
- ❌ 戻り値型
- ❌ パラメータ名
💡 Javaはメソッドシグネチャでメソッドを区別します。
オーバーロード呼び出し優先順位
public static void print(int num) {
System.out.println("int: " + num);
}
public static void print(double num) {
System.out.println("double: " + num);
}
print(10); // intバージョン呼び出し
print(10.5); // doubleバージョン呼び出し
- 正確に一致する型のメソッドを先に探す
- なければ自動型変換可能な型のメソッドを探す
メソッドでリファクタリング
リファクタリング前
public static void main(String[] args) {
int[] students = {90, 80, 70, 60, 50};
// 平均計算
int sum = 0;
for (int i = 0; i < students.length; i++) {
sum += students[i];
}
double average = (double) sum / students.length;
// 出力
System.out.println("合計: " + sum);
System.out.println("平均: " + average);
// ... 他の作業
}
リファクタリング後
public static void main(String[] args) {
int[] students = {90, 80, 70, 60, 50};
int sum = calculateSum(students);
double average = calculateAverage(sum, students.length);
printResult(sum, average);
}
public static int calculateSum(int[] scores) {
int sum = 0;
for (int score : scores) {
sum += score;
}
return sum;
}
public static double calculateAverage(int sum, int count) {
return (double) sum / count;
}
public static void printResult(int sum, double average) {
System.out.println("合計: " + sum);
System.out.println("平均: " + average);
}
長所:
- ✅ mainメソッドで全体の流れを一目で把握可能
- ✅ 各機能が独立したメソッドに分離
- ✅ 再利用とテストが容易
💡 モジュール化(Modularization): プログラムを機能別に分離して独立した単位にすること
メソッド使用の利点
1. コードの再利用
// 一度定義すれば複数箇所で使用
printSum(10, 20);
printSum(30, 40);
printSum(50, 60);
2. 可読性向上
// 悪い例
int x = a * b + c / d - e; // どんな計算か不明確
// 良い例
int price = calculateTotalPrice(quantity, unitPrice, discount); // 明確!
3. モジュール性
- 大きなプログラムを小さく管理可能な部分に分割
- 各メソッドは一つの機能のみ実行
4. 保守容易
// 計算ロジック変更が必要ならメソッドのみ修正
public static int calculatePrice(int quantity, int unitPrice) {
// ここだけ修正すればよい!
return quantity * unitPrice;
}
5. 抽象化
- メソッド内部実装を知らなくても使用可能
- 複雑なロジックを簡単な名前で表現
// 内部複雑度を隠す
double average = calculateAverage(scores); // どう計算するか知らなくてもOK
6. テストとデバッグ
- 各メソッドを独立してテスト可能
- 問題発生時、該当メソッドのみ確認
ネーミング規則
// 変数名: 名詞
int studentCount;
String userName;
double totalPrice;
// メソッド名: 動詞で始める
void printInfo() { }
int calculateSum() { }
boolean isValid() { }
String getName() { }
一般的なメソッド名パターン:
-
get+ 名詞: 値を返す -
set+ 名詞: 値を設定 -
is+ 形容詞: boolean返す -
print/show/display: 出力 -
calculate/compute: 計算
核心まとめ
メソッド基本
- メソッドはコードを再利用するための機能
修飾子 戻り値型 メソッド名(パラメータ) { 本文 }- 引数を渡すとパラメータに代入される
Javaの大原則
- Javaは常に値をコピーして渡す
- プリミティブ型: 値自体をコピー
- 参照型: 参照値(アドレス)をコピー
戻り値と終了
- 戻り値型がある場合
return必須 -
voidはreturn省略可能 -
returnに出会うと即座にメソッド終了
オーバーロード
- 同じ名前、異なるパラメータで複数メソッド定義
- メソッドシグネチャ = 名前 + パラメータ型
- 戻り値型のみ異なる場合はオーバーロード不可
メソッドの利点
- 再利用、可読性、モジュール性、保守、抽象化、テスト容易
- プログラムは無条件に単純に!
本投稿はインフルン キム・ヨンハンのJava講座を学習しながらまとめた内容です。
シリーズ完了! 次の講座で続きます...