Day 5: メソッド
今日学ぶこと
- メソッドの定義と呼び出し
- 引数と戻り値
- メソッドのオーバーロード
- 可変長引数
- スコープとライフタイム
メソッドとは
メソッドは処理をまとめた再利用可能なブロックです。
public class MethodDemo {
// メソッドの定義
static void greet(String name) {
System.out.println("こんにちは、" + name + "さん!");
}
public static void main(String[] args) {
// メソッドの呼び出し
greet("太郎");
greet("花子");
}
}
flowchart TB
subgraph Method["メソッドの構成"]
Modifier["修飾子<br>static"]
Return["戻り値型<br>void / int / String"]
Name["メソッド名<br>greet"]
Params["引数<br>(String name)"]
Body["処理本体<br>{ ... }"]
end
Modifier --> Return --> Name --> Params --> Body
style Modifier fill:#8b5cf6,color:#fff
style Return fill:#3b82f6,color:#fff
style Name fill:#22c55e,color:#fff
style Params fill:#f59e0b,color:#fff
style Body fill:#ef4444,color:#fff
メソッドの構文
修飾子 戻り値型 メソッド名(引数リスト) {
// 処理
return 値; // void の場合は不要
}
戻り値
値を返すメソッド
static int add(int a, int b) {
return a + b;
}
static double calculateBmi(double height, double weight) {
return weight / (height * height);
}
static boolean isEven(int number) {
return number % 2 == 0;
}
// 使用例
int sum = add(3, 5); // 8
double bmi = calculateBmi(1.70, 65.0); // 22.49...
boolean even = isEven(4); // true
void メソッド
static void printLine(int length) {
for (int i = 0; i < length; i++) {
System.out.print("-");
}
System.out.println();
}
// 使用例
printLine(20); // --------------------
引数
値渡し
Javaの引数はすべて値渡しです。プリミティブ型はコピーが渡されます。
static void tryChange(int x) {
x = 100; // 元の変数には影響しない
}
public static void main(String[] args) {
int num = 10;
tryChange(num);
System.out.println(num); // 10(変わらない)
}
参照型の引数
参照型は「参照の値」が渡されるため、オブジェクトの内容は変更できます。
static void addElement(int[] array, int index, int value) {
array[index] = value; // 配列の中身は変更される
}
public static void main(String[] args) {
int[] nums = {1, 2, 3};
addElement(nums, 0, 99);
System.out.println(nums[0]); // 99(変わる)
}
flowchart LR
subgraph Primitive["プリミティブ型"]
P1["num = 10"] -->|"コピー"| P2["x = 10"]
P3["num = 10<br>(変わらない)"]
end
subgraph Reference["参照型"]
R1["nums → [1,2,3]"] -->|"参照のコピー"| R2["array → [1,2,3]"]
R3["nums → [99,2,3]<br>(変わる)"]
end
style Primitive fill:#3b82f6,color:#fff
style Reference fill:#22c55e,color:#fff
メソッドのオーバーロード
同じ名前で引数の型や数が異なるメソッドを定義できます。
static int add(int a, int b) {
return a + b;
}
static double add(double a, double b) {
return a + b;
}
static int add(int a, int b, int c) {
return a + b + c;
}
// 呼び出し時に引数に応じて適切なメソッドが選ばれる
add(1, 2) // int版
add(1.5, 2.5) // double版
add(1, 2, 3) // 3引数版
ポイント: オーバーロードは引数の型や数で区別します。戻り値の型だけが異なるオーバーロードはできません。
可変長引数(varargs)
static int sum(int... numbers) {
int total = 0;
for (int n : numbers) {
total += n;
}
return total;
}
// 使用例
sum(1, 2, 3) // 6
sum(1, 2, 3, 4, 5) // 15
sum() // 0
制約: 可変長引数はメソッドの最後の引数としてのみ使えます。
// ✅ OK
static void log(String tag, String... messages) { }
// ❌ NG
// static void log(String... messages, String tag) { }
スコープとライフタイム
public class ScopeDemo {
// クラスレベル(static変数)
static int classVar = 100;
static void method() {
// メソッドレベル(ローカル変数)
int localVar = 10;
if (true) {
// ブロックレベル
int blockVar = 5;
System.out.println(blockVar); // ✅ OK
}
// System.out.println(blockVar); // ❌ スコープ外
}
}
| スコープ | 宣言場所 | 有効範囲 |
|---|---|---|
| クラスレベル | クラス直下 | クラス全体 |
| メソッドレベル | メソッド内 | メソッド内 |
| ブロックレベル | {} 内 |
そのブロック内 |
再帰
メソッドが自分自身を呼び出す手法です。
// 階乗: n! = n × (n-1)!
static long factorial(int n) {
if (n <= 1) {
return 1; // 基底条件
}
return n * factorial(n - 1); // 再帰呼び出し
}
// 使用例
factorial(5) // 120 (5 × 4 × 3 × 2 × 1)
flowchart TB
F5["factorial(5)<br>5 × factorial(4)"]
F4["factorial(4)<br>4 × factorial(3)"]
F3["factorial(3)<br>3 × factorial(2)"]
F2["factorial(2)<br>2 × factorial(1)"]
F1["factorial(1)<br>return 1"]
F5 --> F4 --> F3 --> F2 --> F1
style F5 fill:#3b82f6,color:#fff
style F4 fill:#3b82f6,color:#fff
style F3 fill:#3b82f6,color:#fff
style F2 fill:#3b82f6,color:#fff
style F1 fill:#22c55e,color:#fff
フィボナッチ数列
static int fibonacci(int n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
// fibonacci(6) → 8 (0, 1, 1, 2, 3, 5, 8)
注意: 再帰には必ず基底条件(終了条件)が必要です。ないと無限再帰で
StackOverflowErrorが発生します。
実践: ユーティリティメソッド集
import java.util.Arrays;
public class Utilities {
// 配列の最大値
static int max(int... numbers) {
int result = numbers[0];
for (int n : numbers) {
if (n > result) result = n;
}
return result;
}
// 配列の平均
static double average(int... numbers) {
int sum = 0;
for (int n : numbers) {
sum += n;
}
return (double) sum / numbers.length;
}
// 文字列の繰り返し
static String repeat(String str, int count) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < count; i++) {
sb.append(str);
}
return sb.toString();
}
// 回文判定
static boolean isPalindrome(String str) {
String clean = str.toLowerCase().replaceAll("\\s+", "");
return clean.equals(new StringBuilder(clean).reverse().toString());
}
public static void main(String[] args) {
System.out.println("最大値: " + max(3, 7, 1, 9, 4));
System.out.printf("平均値: %.2f%n", average(80, 90, 75, 88));
System.out.println(repeat("★", 5));
System.out.println("回文? " + isPalindrome("A man a plan a canal Panama"));
}
}
まとめ
| 概念 | 説明 |
|---|---|
| メソッド | 処理をまとめた再利用可能なブロック |
| 戻り値 | returnで値を返す。voidは返さない |
| 値渡し | プリミティブ型はコピーが渡される |
| オーバーロード | 同名メソッドの引数違い定義 |
| 可変長引数 | int... numbersで任意個の引数 |
| 再帰 | メソッドが自分自身を呼び出す |
重要ポイント
- メソッドは1つの責務に集中させる
- Javaはすべて値渡し(参照型は参照の値が渡される)
- オーバーロードは引数の型・数で区別
- 再帰には必ず基底条件を設定する
練習問題
問題1: 基本
2つの整数の最大公約数(GCD)を求めるメソッドを作成してください(ユークリッドの互除法を使用)。
問題2: 応用
文字列配列を受け取り、最も長い文字列を返すメソッドと、すべての文字列を逆順にした配列を返すメソッドを作成してください。
チャレンジ問題
再帰を使って、指定された深さの「ハノイの塔」を解くプログラムを作成してください。各手順を「ディスク1をAからCへ移動」のように表示しましょう。
参考リンク
次回予告: Day 6では「クラスとオブジェクト」について学びます。Javaの核心であるオブジェクト指向プログラミングに踏み出しましょう。