対象:C言語経験者 / C言語の「関数」がJavaでは「メソッド」になります。構文の差分と、クラスの中に書くという点を理解します
やっていることはC言語の関数と同じです。処理をひとまとめにして名前を付け、呼び出して使います。
Javaでは「クラスの中に定義された関数」のことを メソッド と呼びます。
// ファイルに直接書く
int add(int a, int b) {
return a + b;
}
int main(void) {
int result = add(3, 4);
printf("%d\n", result);
return 0;
}
// クラスの中に書く
public class Calc {
static int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
int result = add(3, 4);
System.out.println(result);
}
}
C言語との主な違いは2点です。
| 項目 | C言語 | Java |
|---|---|---|
| 書く場所 | ファイルに直接書く | 必ずクラスの中に書く |
| 修飾子 | なし | static、public などが付く |
| プロトタイプ宣言 | 必要(呼び出しより前に書かない場合) | 不要(同じクラス内ならどこに書いてもよい) |
| 戻り値なし | void | void(同じ) |
static などの修飾子が加わります。static を付けると「インスタンスを作らなくても呼び出せるメソッド」になります。
クラスやインスタンスについては次の単元で詳しく学びます。今の段階では 「メソッドを定義するときは static を付ける」 と覚えておきましょう。
main メソッドが public static void main になっているのも同じ理由です。JVMがインスタンスを作らずに呼び出せるよう static が付いています。
C言語では呼び出しより後ろに関数を書くとプロトタイプ宣言が必要でしたが、Javaでは不要です。コンパイラがクラス全体を見渡して解決してくれます。
public class Example {
public static void main(String[] args) {
greet("Taro"); // main より後ろに定義されていてもOK
}
static void greet(String name) {
System.out.println("Hello, " + name + "!");
}
}
Javaのプリミティブ型の引数はC言語と同じ 値渡し です。メソッド内で変更しても呼び出し元には影響しません。
public class PassValue {
static void doubleIt(int x) {
x = x * 2; // ローカルの x を変えているだけ
System.out.println("メソッド内: x = " + x);
}
public static void main(String[] args) {
int a = 5;
doubleIt(a);
System.out.println("呼び出し元: a = " + a); // a は変わらない
}
}
配列(参照型)を渡すと、参照(アドレス)のコピー が渡されます。メソッド内で要素を変更すると、呼び出し元の配列にも反映されます。
public class PassArray {
static void fill(int[] arr, int val) {
for (int i = 0; i < arr.length; i++) {
arr[i] = val; // 呼び出し元の配列を直接変更している
}
}
public static void main(String[] args) {
int[] data = {1, 2, 3};
fill(data, 99);
System.out.println(data[0]); // → 99(変わっている)
}
}
C言語と全く同じです。return で値を返します。戻り値がない場合は void。
// 戻り値あり
static int max(int a, int b) {
if (a >= b) {
return a;
} else {
return b;
}
}
// void(戻り値なし)
static void printLine(int n) {
for (int i = 0; i < n; i++) {
System.out.print("-");
}
System.out.println();
// return; は省略可
}
// 使い方
System.out.println(max(3, 7)); // → 7
printLine(10); // → ----------
同じ名前のメソッドを 引数の型や数を変えて複数定義 できます。これをオーバーロードと言います。C言語には同名関数を複数定義する機能はありません。
public class Overload {
// int 型の加算
static int add(int a, int b) {
return a + b;
}
// double 型の加算(同じ名前でOK)
static double add(double a, double b) {
return a + b;
}
// 3つの引数(同じ名前でOK)
static int add(int a, int b, int c) {
return a + b + c;
}
public static void main(String[] args) {
System.out.println(add(1, 2)); // → 3 (int版)
System.out.println(add(1.5, 2.5)); // → 4.0 (double版)
System.out.println(add(1, 2, 3)); // → 6 (3引数版)
}
}
System.out.println() が int・double・String など何でも受け取れるのも、内部でオーバーロードされているからです。
static int add(int a, int b) と static double add(int a, int b) は引数が同じなのでコンパイルエラーになります。
実習1
08_Methods フォルダに Methods.java を作って実行しましょう。
public class Methods {
// ① 値を返すメソッド
static int max(int a, int b) {
return (a >= b) ? a : b;
}
// ② void メソッド(罫線を引く)
static void printBorder(int n) {
for (int i = 0; i < n; i++) {
System.out.print("=");
}
System.out.println();
}
// ③ 配列を受け取るメソッド(参照渡し)
static int sum(int[] arr) {
int total = 0;
for (int x : arr) {
total += x;
}
return total;
}
// ④ オーバーロード
static String repeat(String s, int n) {
String result = "";
for (int i = 0; i < n; i++) {
result += s;
}
return result;
}
static String repeat(String s) {
return repeat(s, 3); // 引数1つ版はデフォルト3回
}
public static void main(String[] args) {
printBorder(20);
System.out.println("max(5, 8) = " + max(5, 8));
System.out.println("max(9, 3) = " + max(9, 3));
printBorder(20);
int[] scores = {85, 62, 91, 47, 78};
System.out.println("合計: " + sum(scores));
System.out.println("平均: " + (double) sum(scores) / scores.length);
printBorder(20);
System.out.println(repeat("Java ", 4));
System.out.println(repeat("Ha")); // 引数1つ版:3回
}
}
実行結果:
| # | 変えてみること | 確認ポイント |
|---|---|---|
| 1 | ③ の sum メソッド内で arr[0] = 999; を追加してから scores[0] を出力する |
配列の参照渡しの動作として、呼び出し元の scores[0] が 999 に変わることを確認しましょう |
| 2 | max メソッドを double 版でオーバーロードして max(3.14, 2.71) を呼ぶ |
引数の型で自動的に正しいメソッドが呼ばれることを確認しましょう |
| 3 | 戻り値の型だけ違う同名メソッドを書いてみる(例:static double sum(int[] arr)) |
コンパイルエラーになることを確認しましょう |
実習2
09_MethodExam フォルダに MethodExam.java を作って実行しましょう。
第67回 問4(26) に登場したメソッド呼び出しパターンです。引数の型に注目しましょう。
public class MethodExam {
// String と boolean を受け取るメソッド
static void over30(String s, boolean b) {
System.out.println(s + " : " + b);
}
public static void main(String[] args) {
String name = "Taro";
int age = 32;
// age > 30 は boolean 型の式なので第2引数に渡せる
over30(name, age > 30);
}
}
実行結果:
age > 30 が引数として渡せるのか確認しましょうage > 30 は比較演算子の式で、結果は boolean 型(true または false)になります。
メソッド over30 の第2引数は boolean b なので、型が一致して渡すことができます。
試験第67回 問4(26) では「age, age - 30」という選択肢は第1引数が int 型なので不正解、「name, age > 30」が正解になります。
頻出ポイント
| よく問われること | 正しい答え |
|---|---|
| メソッドの定義場所 | 必ずクラスの中。C言語のようにファイルに直接は書けません |
| プロトタイプ宣言 | 不要。同じクラス内ならどの順番でも呼び出せます |
| プリミティブ型の引数 | 値渡し。メソッド内で変更しても呼び出し元は変わりません |
| 配列の引数 | 参照のコピーが渡るため、要素の変更は呼び出し元に反映されます |
| オーバーロードの条件 | 引数の型・数が違えばOK。戻り値の型だけの違いはコンパイルエラー |
static の意味 | インスタンスを作らずに呼び出せるメソッド |
public class Q {
static void over30(String s, boolean b) {
System.out.println(s + " : " + b);
}
public static void main(String[] args) {
String name = "taro";
int age = 32;
over30(name, age > 30);
}
}
age > 30 は 32 > 30 なので true。boolean 型として第2引数に渡されます。
| ポイント | 内容 |
|---|---|
| メソッド = 関数 | C言語の関数と同じ概念。クラスの中に書く点が違います |
static | インスタンス不要で呼べるメソッド。今の段階では必ず付けます |
| プロトタイプ不要 | コンパイラがクラス全体を見渡すため宣言不要です |
| 値渡し | プリミティブ型はコピーが渡ります。元の変数は変わりません |
| 配列の引数 | アドレスのコピーが渡ります。要素変更は呼び出し元に反映されます |
| オーバーロード | 引数の型・数が違えば同じ名前のメソッドを複数定義できます |