Javaのメソッドはプログラムを効率的にかつ再利用性の高い形で構築するための基本要素で、メソッドを理解することはJavaプログラミングの第1歩です。このページでは、Java初心者の方でも理解できるようにメソッドの定義方法、呼び出し方法、そしてその背後にある動作原理を、ステップバイステップで詳しく解説します。

メソッドを理解し適切に活用することで、より効率的で管理しやすいプログラムを作成することが可能になります。是非最後までご覧ください。
Javaのメソッドとは?
メソッドとは、特定の機能や処理をまとめたコードの塊です。プログラム内で同じ処理を繰り返し使いたい場合、メソッドを使うことでコードを簡潔かつ整理された形に保つことができます。あらかじめ料理のレシピを用意しておいて、後から何度も効率よく同じ料理を作れるようにするイメージです。
似たような概念に「関数」が存在しますが、Javaには「関数」という独立した概念は存在せずすべて「メソッド」として定義されるという点を覚えておきましょう。
- 関数(Function)
- 一般的なプログラミング言語(例えば、PythonやJavaScript)では、関数は独立して存在し、特定のタスクを実行する。
- メソッド(Method)
- メソッドは、オブジェクト指向プログラミング(OOP)で使われる用語で、特定のクラスに関連付けられた関数(のようなもの)です。
メソッドは、クラスの中で定義され、クラスを通して利用するものであるということを理解できればOKです。
メソッドの定義方法
ここからが本題。
Javaでメソッドを定義するための基本的なルールを説明していきます。
メソッドの基本構造
メソッドを定義するための基本的な構文は以下の通り。
修飾子 戻り値の型 メソッド名(引数) { // メソッドの中の処理 return 戻り値; // 戻り値がある場合 }
サンプルコード 2つの整数を加算するメソッド
public int add(int num1, int num2) { int sum = num1 + num2; return sum; } // public:他のクラスからもアクセス可能であることを示す // int:このメソッドは整数型の値を返すことを示す // add:メソッド名 // (int num1, int num2):二つの整数を引数として受け取る // return sum;:計算結果を呼び出し元に返す
このコードは、整数(int
)を返すadd
というメソッドを定義しています。このメソッドは2つの整数を引数として受け取った後2つの整数を加算し、その結果を返します。
引数はメソッドに与える「インプット」で、戻り値は「アウトプット」。料理の具材を渡したら一品作ってくれるシェフのようなもので、具材にあたるのが引数、出来上がった料理が戻り値です。

戻り値がないメソッド:void
戻り値がないメソッドを定義する場合は、戻り値の型としてvoid
を指定します。例えば、戻り値のない「挨拶を表示するメソッド」であれば↓のように定義します。
public void greet(String name) { System.out.println("Hello, " + name); }
このメソッドは、name
という引数を受け取り、「Hello (名前)」を表示するだけで戻り値はありません。そのため戻り値の型には「void」を指定してます。
可変長引数(varargs)
メソッドに任意の数の引数を渡すことを可能にする便利な可変長引数という機能もあります。可変長引数を使うと、呼び出し側で渡す引数の数を柔軟にできます。メソッド側では内部的に配列として扱われます。

可変長引数を定義するには、型の後に「...」を付けます。
public void sampleMethod(int... numbers) { // numbers は int 型の配列として扱われる } /* 呼び出し側では、個別の値または配列を渡すことができます。 */ sampleMethod(1, 2, 3); // 3つの引数を渡す sampleMethod(new int[]{4, 5, 6}); // 配列を渡す sampleMethod(); // 引数なしも可能
- ルール:
可変長引数はメソッドのパラメータリストの最後に1つだけ指定できます。
public void anotherMethod(String name, int... scores) { // name は通常の引数、scores は可変長引数 }
可変長引数はメソッド内部で配列として扱われるため、配列のインデックスを利用して個々の要素にアクセスすることもできます。
public void printFirstNumber(int... numbers) { if (numbers.length > 0) { System.out.println("最初の数字: " + numbers[0]); } else { System.out.println("数字が渡されていません"); } }
メソッドの呼び出し
メソッドを呼び出す際には次のような構文を用います。
オブジェクト名.メソッド名(引数);
そのうえで、Javaのメソッドの呼び出し方を詳しく見ていくと3パターンあります。それぞれのケースで微妙に使い方が異なりますので、ここではそれぞれのメソッド呼び出しの違いと具体例を詳しく解説します。
- クラス内からのメソッド呼び出し(同じクラス内のメソッド呼び出し)
- インスタンスメソッドの呼び出し
- クラスメソッド(staticメソッド)の呼び出し
1.クラス内からのメソッド呼び出し
クラス内で定義したメソッドは、同じクラスの他のメソッドから直接呼び出すことができます。
ルール:
public class ClassInternalCall { // method1: シンプルなメッセージを表示する public void method1() { System.out.println("こんにちは!クラス内メソッドの呼び出しです。"); } // method2: method1を呼び出す public void method2() { method1(); // クラス内のメソッドをそのまま呼び出し } // mainメソッド public static void main(String[] args) { ClassInternalCall obj = new ClassInternalCall(); // インスタンスを生成 obj.method2(); // method2を呼び出し、その中でmethod1が呼ばれる } }
解説:
method1()
:- 「こんにちは!クラス内メソッドの呼び出しです。」と表示するシンプルなメソッドです。
method2()
:method1()
をクラス内から直接呼び出しています。- **
this.method1()
**と書くこともできますが、暗黙的にthis
が使われるため省略しています。
main
メソッド:- インスタンスを生成し、そのインスタンスから
method2()
を呼び出しています。 method2()
内でmethod1()
が呼ばれるため、プログラムの実行結果としてメッセージが表示されます。
- インスタンスを生成し、そのインスタンスから
2.インスタンスメソッドの呼び出し
ルール:
- インスタンス(オブジェクト)を生成してから、インスタンスメソッドを呼び出します。

参考 Javaのクラスの基本(オブジェクト&インスタンス化の基本)
ステップ1 クラスのインスタンスを作成
クラス名 オブジェクト名 = new クラス名();
ステップ2 メソッドの呼び出し
オブジェクト名.メソッド名(引数);
わかりやすい例として、自動車(クラス)に「エンジンをかける」(メソッド)という機能を定義し、それを呼び出す例を考えます。
public class Car { // メソッドの定義 public void startEngine() { System.out.println("エンジンがかかりました"); } } public class Main { public static void main(String[] args) { // Carクラスのインスタンスを作成 Car myCar = new Car(); // インスタンスを使ってメソッドを呼び出し myCar.startEngine(); } }
日常生活でも同じですが、エンジンをかけるためには車そのものが存在しないといけません。これと同じでメソッドを呼び出すには、まず自動車のインスタンス(具体的な車)を作るステップが必要です。↑のサンプルコードでは、Car
クラスのstartEngine
メソッドを使ってエンジンをかける動作を実行しています。
3.クラスメソッド(staticメソッド)の呼び出し
一部のメソッドはインスタンス化せず、直接クラスを指定することで呼び出すことが可能です。このようなメソッドをクラスメソッド(=staticメソッド)と呼びます。
ルール:
static
キーワードを使って定義したメソッドは、クラス名から直接呼び出します。- インスタンスの生成が不要です。
ポイント:
- クラスメソッドはクラス全体で共有される。
- オブジェクトを作成せずに使用できる。
クラスメソッドは、クラス名.メソッド名()
という形で呼び出します。
public class MathUtils { public static int add(int a, int b) { return a + b; } } ------------------------------------------------- public class Main { public static void main(String[] args) { int result = MathUtils.add(5, 3); System.out.println("結果は:" + result); } }
呼び出し方法 | 説明 | 例 |
---|---|---|
クラス内呼び出し | 同じクラス内のメソッドを呼び出す。インスタンス不要。 | method1(); |
インスタンスメソッド呼び出し | インスタンスを生成してから呼び出す。 | obj.greet(); |
クラスメソッド呼び出し | クラス名から直接呼び出す。static メソッド。 | StaticMethodCall.sayHello(); |
メソッドチェーンとは、メソッドの呼び出しを連鎖(チェーン)させることで、コードを簡潔に記述できるようにするテクニックです。
通常は、メソッドを呼び出す際、複数の処理を別々に書きます。
String str = " Java "; str = str.trim(); // 空白を削除 str = str.toUpperCase(); // 大文字に変換 str = str.concat("!!!"); // 文字を追加 // JAVA!!!
メソッドチェーンを使うと以下のようにまとめられます。
String str = " Java ".trim().toUpperCase().concat("!!!"); // JAVA!!!
ポイント メソッドチェーンを利用する条件
メソッドの動作原理をシステムの観点から理解する
メソッドがどのように動作するのか。これをシステム的な観点から正しく理解することで、プログラムの効率やバグの原因を把握しやすくなります。ここではJavaメソッドのシステム的な動作原理を詳しく解説します。
スタックフレームとメソッド呼び出し
定義したメソッドは呼び出しされると、メモリ上に作成されるスタックフレームと呼ばれる領域にメソッドの情報が保持されます。
- スタック:メソッド呼び出しの履歴を管理するデータ構造です。
- スタックフレーム:各メソッド呼び出しごとに作成され、ローカル変数や引数、戻り先の情報を保持します。
スタックフレームはレストランの注文票のようなもの。注文ごとに新しい注文票が作成され、料理が提供されるとその注文票は破棄されます。
動作の流れ:
- メソッド呼び出し時:新しいスタックフレームがスタックに積まれる。
- メソッド実行中:スタックフレーム内でローカル変数や引数が管理される。
- メソッド終了時:スタックフレームがスタックから取り除かれ、制御が呼び出し元に戻る。
引数の受け渡し
Javaでは、引数は基本的に値渡しで行われます。
- プリミティブ型:値そのものがコピーされる。
- 参照型:オブジェクトの参照(アドレス)がコピーされる。
注意点:参照型の場合、オブジェクト自体は同じものを指しているため、メソッド内でオブジェクトの状態を変更すると、呼び出し元にも影響します。
public class Example { public static void changeValue(int num) { num = 10; } public static void changeArray(int[] arr) { arr[0] = 10; } public static void main(String[] args) { int number = 5; changeValue(number); // 静的メソッドの呼び出し System.out.println(number); // 出力: 5 int[] array = {1, 2, 3}; changeArray(array); // 静的メソッドの呼び出し System.out.println(array[0]); // 出力: 10 } }
Javaメソッド練習問題
メソッドの使い方をマスターするためには、実際に手を動かしてみるのが一番です。ここでは、初心者でも取り組みやすい計算機プログラムを中心に、メソッドを使った練習問題を3つ用意しました。
問題 1:足し算メソッドを作成するプログラム
課題内容:
- 2つの整数を引数として受け取り、それらを加算して結果を返すメソッドを作りましょう。
条件:
- メソッド名は
add
とする。 - メインメソッドから
add
メソッドを呼び出して、結果を表示してください。
public class Calculator { // 2つの整数を加算するメソッド public 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); // 出力: 足し算の結果: 7 } }
問題 2:簡単な電卓プログラム
課題内容:
- 4つの基本的な計算を行うメソッド(足し算、引き算、掛け算、割り算)をそれぞれ作りましょう。
条件:
- メソッド名は以下のようにします:
add(int a, int b)
:足し算subtract(int a, int b)
:引き算multiply(int a, int b)
:掛け算divide(int a, int b)
:割り算(割り算の際、割る数が0にならないようにチェック)
- 各メソッドの結果を表示するプログラムを作成してください。
public class SimpleCalculator { // 足し算メソッド public static int add(int a, int b) { return a + b; } // 引き算メソッド public static int subtract(int a, int b) { return a - b; } // 掛け算メソッド public static int multiply(int a, int b) { return a * b; } // 割り算メソッド (0除算のチェック付き) public static double divide(int a, int b) { if (b == 0) { System.out.println("エラー: 0で割ることはできません。"); return 0; } return (double) a / b; } public static void main(String[] args) { System.out.println("足し算: " + add(5, 3)); // 出力: 足し算: 8 System.out.println("引き算: " + subtract(5, 3)); // 出力: 引き算: 2 System.out.println("掛け算: " + multiply(5, 3)); // 出力: 掛け算: 15 System.out.println("割り算: " + divide(6, 2)); // 出力: 割り算: 3.0 divide(5, 0); // 出力: エラー: 0で割ることはできません。 } }
問題 3:最大値を求めるプログラム
課題内容:
- 3つの整数を引数として受け取り、その中で最大の値を返すメソッドを作りましょう。
条件:
- メソッド名は
findMax
とする。 - メインメソッドから
findMax
を呼び出して、3つの値のうち最大値を表示してください。
public class MaxValueFinder { // 3つの整数の最大値を求めるメソッド public static int findMax(int a, int b, int c) { int max = a; // 初期値としてaを設定 if (b > max) { max = b; } if (c > max) { max = c; } return max; } public static void main(String[] args) { int maxValue = findMax(42, 35, 27); // メソッドの呼び出し System.out.println("最大値は: " + maxValue); // 出力: 最大値は: 42 } }
Java:メソッドのオーバーロード

最後により実践で使える知識を補足していきます。
メソッドのオーバーロードとは、同じクラス内で「メソッド名」が同じ複数のメソッドを定義することを指します。単に同名のメソッドを複数定義すれば良いわけではなく、Javaの仕様上、以下の条件を満たす必要があります。
ポイント Javaにおけるメソッドのオーバーロードの条件
項目 | 説明 |
---|---|
メソッド名 | 同じである必要がある |
引数の数 | 異なっている必要がある(もしくは型が違う) |
引数の型 | 異なっている必要がある(順番の違いもOK) |
引数の順序 | 型が異なれば、順番違いでもOK |
戻り値の型 | 無関係(違っていても、それだけではオーバーロードにはならない) |
アクセス修飾子など | 影響しない(public、privateなどが違ってもOK) |
これにより、「同じ目的」であっても引数の取り方が異なるメソッドを用意できるようになり、使う側(メソッドを呼び出す側)は「引数の与え方」に応じて適切なメソッドを呼び分けられるメリットがあります。
public class OverloadExample { // int型の配列を要素ごとに足し合わせるメソッド public int sum(int a, int b) { return a + b; } // double型の配列を要素ごとに足し合わせるメソッド public double sum(double a, double b) { return a + b; } }
上記の例では、「sum
」というメソッド名は同じですが、引数の型が違うため、Javaでは両方のメソッドを同一クラスで定義できます。
オーバーロードとオーバーライドの違い
両者は全くの別物なので混同しないように注意が必要です。
オーバーロードのメリット
可読性の向上
たとえば「同じ概念の操作を、異なる型や異なる数の引数で実行したい」とき、メソッド名を使い回すことで直感的に分かりやすいコードにできます。
sum(int a, int b)
、sum(int[] arr)
、sum(double a, double b)
といった形で「加算」を表すメソッドの名前を全て「sum」で統一すれば、「これは足し算を行うメソッドだな」と名前だけで理解できるため、メソッド名の違いに悩むことが減ります。
メンテナンス性の向上
メソッド名を統一できるということは、「同じ目的の処理」に対してメソッドを乱立させる必要がなくなるということでもあります。もしメソッド名を別々に用意した場合、sumInt()
, sumDouble()
, sumArray()
などと命名し、それぞれに関連する実装やドキュメントを別々に管理しなければなりません。オーバーロードは、そうした煩雑さを軽減します。
オーバーロードがどのように判定されるか
オーバーロードでは、コンパイル時にどのメソッドが呼び出されるかが決定されます。Javaコンパイラはメソッド呼び出しの際に、引数リスト(型や数、順序など)を見て「どのシグニチャ(メソッドの定義)に合致するか」を判定します。
シグニチャ(Signature)
Javaにおいて、メソッド名 + 引数の型の組み合わせのことを「メソッドのシグニチャ」と呼びます。戻り値の型はシグニチャに含まれません。したがって、以下はオーバーロードにはなりません。
public int sample(int x) { ... } public double sample(int x) { ... } // 戻り値だけが異なるが、引数の型・数は同じ => オーバーロード不可
実際の呼び出しと注意点
自動型変換が絡む場合
Javaでは、int型からlong型への拡張変換など、暗黙的な型変換が行われる場合があります。オーバーロードの際には、暗黙的な型変換が最も適切にマッチするものが優先されます。
public class OverloadMatch { public void printValue(int x) { System.out.println("int版: " + x); } public void printValue(long x) { System.out.println("long版: " + x); } public static void main(String[] args) { OverloadMatch om = new OverloadMatch(); om.printValue(10); // どちらが呼ばれるか? } }
この場合、10
はintリテラルであり、printValue(int x)
が最適一致となるため、int版: 10
が呼び出されます。ただし、引数が10L
(longリテラル)であれば、printValue(long x)
が呼ばれます。
ランタイム型は関係ない
オーバーロードはコンパイル時にどのメソッドが呼び出されるかが決まるため、「実行時のオブジェクトの型」によってメソッドが振り分けられることはありません。たとえば以下のような例を見てみましょう。
public class OverloadDemo { public void display(Number n) { System.out.println("Number版"); } public void display(Integer i) { System.out.println("Integer版"); } public static void main(String[] args) { OverloadDemo demo = new OverloadDemo(); Number num = Integer.valueOf(10); demo.display(num); // どちらが呼ばれる? } }
num
は実行時にはInteger
のオブジェクトを指していますが、変数宣言がNumber num
となっているので、コンパイル時には「Number
型の引数」を取るメソッドだと判断されます。そのため、呼び出されるのはdisplay(Number n)
の方です。
サンプルコード メソッドのオーバーロード:まとめ
public class OverloadCheck { // 1) int型2つ public void printSum(int a, int b) { System.out.println("int + int = " + (a + b)); } // 2) double型2つ public void printSum(double a, double b) { System.out.println("double + double = " + (a + b)); } // 3) 可変長引数 (int) public void printSum(int... values) { int total = 0; for (int val : values) { total += val; } System.out.println("可変長引数 = " + total); } // 4) 引数の数が異なる public void printSum(int a, int b, int c) { System.out.println("int3つ = " + (a + b + c)); } public static void main(String[] args) { OverloadCheck oc = new OverloadCheck(); oc.printSum(2, 3); // int + int oc.printSum(2.0, 3.5); // double + double oc.printSum(1, 2, 3); // int3つ oc.printSum(1, 2, 3, 4); // 可変長引数 } }
Javaのメソッドオーバーロードは便利かつ強力な機能ですが、正しい理解と注意深い設計が求められます。「同じメソッド名で色々な引数を受け取れると便利」というメリットは大きい一方で、コンパイラレベルの解決が複雑化するケースも存在します。

オーバーロードの理解を深めるためには、ぜひご自身でいくつかコードを書いて試し、引数の型や数を変えてみたり、可変長引数やオートボクシングを混在させてみたりして、コンパイラがどのように判断するかを確認してみてください。
メソッド終了/制御の戻しとしての「return」
Javaにおける return 文は、戻り値を返すためだけでなく、メソッドの実行を途中で終了して呼び出し元に「制御」を戻すためにも使えます。つまり、return は「値の返却」と「メソッド終了・制御の戻し」という2つの役割を担っています。
戻り値の返却としての return
戻り値が必要なメソッドでは、return 文で計算結果や値を呼び出し元に返します。
public int add(int a, int b) { return a + b; // 計算結果を返してメソッドを終了する }
制御の戻しとしての return
戻り値が不要な(void 型の)メソッドでも、return を使うことでメソッドの実行を途中で終了し、呼び出し元に制御を戻すことができます。これにより、特定の条件下で「これ以上の処理は不要」という場合に、早期にメソッドを抜けることが可能です。
public void process(String data) { if (data == null) { // データがnullの場合は、それ以降の処理をスキップしてメソッドを終了する return; } // dataがnullでない場合のみ、以下の処理が実行される System.out.println("データ処理: " + data); }
この例では、data が null の場合に return 文が実行され、メソッド内の残りのコードは実行されずに、呼び出し元に制御が戻ります。これが「制御の戻し」としての return の役割です。
なぜ制御の戻しが重要か
return 文は「値を返す」ためだけでなく、「処理を途中で終了して呼び出し元に制御を戻す」ためにも利用できる重要なキーワードです。この特性を上手に使うことで、コードの効率性や可読性を高め、適切なエラーハンドリングを実現することが可能になります。