0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[JAVA入門 #8] メソッド - コードの再利用とモジュール化

0
Posted at

メソッドとは?

**メソッド(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バージョン呼び出し
  1. 正確に一致する型のメソッドを先に探す
  2. なければ自動型変換可能な型のメソッドを探す

メソッドでリファクタリング

リファクタリング前

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必須
  • voidreturn省略可能
  • returnに出会うと即座にメソッド終了

オーバーロード

  • 同じ名前、異なるパラメータで複数メソッド定義
  • メソッドシグネチャ = 名前 + パラメータ型
  • 戻り値型のみ異なる場合はオーバーロード不可

メソッドの利点

  • 再利用、可読性、モジュール性、保守、抽象化、テスト容易
  • プログラムは無条件に単純に!

本投稿はインフルン キム・ヨンハンのJava講座を学習しながらまとめた内容です。

シリーズ完了! 次の講座で続きます...

0
1
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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?