Javaの世界でディープダイブ: メソッド引数、メソッド呼び出し、戻り値の全てを解明
Javaというプログラミング言語の世界は、多くのエンジニアにとって無限の可能性と楽しさを秘めています。
特に、メソッドに焦点を当てた時、その魅力はいかんなく発揮されます。メソッドとは、特定の操作をまとめたものであり、適切に使用することでコードの再利用性や可読性を高めることができます。
セクション1: メソッド引数とは何か?
まず最初に「メソッド引数」について探求していきましょう。
メソッド引数とは、メソッドが外部から情報を受け取るための「箱」のようなものです。メソッドを呼び出す際に、この「箱」に情報(値)を入れて、メソッドに渡すことができます。メソッドは、この受け取った情報をもとに処理を行います。
サンプルコード1: メソッド引数の基本
ソースコード例
1 2 3 4 5 6 7 8 9 10 11 |
import java.util.*; public class Program { public static void main(String[] args) { greeting("World"); // "World" is an argument passed to the greeting method } static void greeting(String name) { // "name" is a parameter received by the method System.out.println("Hello, " + name + "!"); } } |
出力結果
Hello, World!
上記のサンプルコードでは、"World"という文字列を引数としてgreetingメソッドに渡しています。
そして、greetingメソッドでは、受け取った引数("World")を使用して、"Hello, World!"と出力しています。
セクション2: Javaでメソッドを呼び出す際のポイント
次に、「メソッドの呼び出し」にフォーカスを当てていきます。
メソッドを呼び出す、とは、定義したメソッドを実行することを意味します。メソッド名の後に()(括弧)をつけることで、メソッドを呼び出すことができ、引数が必要な場合は括弧の中に値を指定します。
KindleUnlimited会員であれば、全ての本をご覧頂けます。 StreamAPIを理解すれば、Javaの世界が変わる 第1版
サンプルコード2: メソッド呼び出しの例
ソースコード例
1 2 3 4 5 6 7 8 9 10 |
public class Program { public static void main(String[] args) { String message = createGreeting("Java"); System.out.println(message); } static String createGreeting(String name) { return "Hello, " + name + "!"; } } |
出力結果
Hello, Java!
このコードのcreateGreetingメソッドはString型の引数を1つ取り、String型の値を返します。
そして、mainメソッド内でcreateGreetingメソッドを呼び出し、返り値を変数messageに代入しています。最後に、messageを出力しています。
セクション3: メソッド戻り値の利用法
さて、メソッドの「戻り値」について見ていきましょう。
戻り値は、メソッドが計算や処理をした結果を呼び出し元に返すためのものです。returnキーワードを使用して、メソッドから値を返すことができます。
サンプルコード3: 戻り値がvoidのメソッド
ソースコード例
1 2 3 4 5 6 7 8 9 |
public class Program { public static void main(String[] args) { displayGreeting("Java"); } static void displayGreeting(String name) { System.out.println("Hello, " + name + "!"); } } |
出力結果
Hello, Java!
こちらの例では、displayGreetingメソッドは何も返さないため、戻り値の型としてvoidを指定しています。
ただし、このメソッドは副作用(ここではコンソールへの出力)を持っています。
セクション4: さまざまな戻り値の型
Javaでは、メソッドの戻り値の型にさまざまなデータ型を指定することができます。このセクションでは、基本的なデータ型や複雑なデータ構造まで、さまざまな戻り値の型の例を見ていきます。
1. int型の戻り値
1 2 3 4 5 6 7 8 9 10 |
public class Sample { public static void main(String[] args) { int result = multiply(5, 3); System.out.println(result); } static int multiply(int a, int b) { return a * b; } } |
出力結果
15
2. String型の戻り値
1 2 3 4 5 6 7 8 9 10 |
public class Sample { public static void main(String[] args) { String combined = combineStrings("Hello, ", "Java!"); System.out.println(combined); } static String combineStrings(String str1, String str2) { return str1 + str2; } } |
出力結果
Hello, Java!
3. 配列の戻り値
1 2 3 4 5 6 7 8 9 10 11 12 |
public class Sample { public static void main(String[] args) { int[] numbers = getNumbers(); for(int num : numbers) { System.out.print(num + " "); } } static int[] getNumbers() { return new int[]{1, 2, 3, 4, 5}; } } |
出力結果
1 2 3 4 5
4. リストの戻り値
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
import java.util.ArrayList; import java.util.List; public class Sample { public static void main(String[] args) { List items = getItems(); for(String item : items) { System.out.println(item); } } static List getItems() { List list = new ArrayList<>(); list.add("Apple"); list.add("Banana"); list.add("Cherry"); return list; } } |
出力結果
Apple Banana Cherry
これらの例からわかるように、Javaではメソッドの戻り値としてさまざまなデータ型やデータ構造を使用することができます。戻り値の型に合わせて、適切なデータ構造や型を返すように設計することで、効率的なプログラミングが可能となります。
セクション5: メソッドのオーバーロード
Javaでは、同じ名前のメソッドをクラス内に複数定義することができます。これをメソッドのオーバーロードと呼びます。メソッドをオーバーロードするには、メソッド名は同じである必要がありますが、パラメータの型や数が異なる必要があります。
1. パラメータの数が異なる場合のオーバーロード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class Sample { public static void main(String[] args) { System.out.println(add(5, 3)); System.out.println(add(5, 3, 2)); } static int add(int a, int b) { return a + b; } static int add(int a, int b, int c) { return a + b + c; } } |
出力結果
8 10
2. パラメータの型が異なる場合のオーバーロード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class Sample { public static void main(String[] args) { System.out.println(multiply(5, 3)); System.out.println(multiply(5.0, 3.0)); } static int multiply(int a, int b) { return a * b; } static double multiply(double a, double b) { return a * b; } } |
出力結果
15 15.0
オーバーロードを用いることで、同じ動作のロジックでも異なる型やパラメータ数に対応することができ、プログラムの可読性と再利用性を高めることができます。ただし、メソッドのオーバーロードが過多になるとコードの管理が複雑になるため、利用の際は適度なバランスを考慮しましょう。
セクション6: メソッドのスコープと可視性
Javaプログラムでは、メソッドが定義される場所によってその「スコープ」(メソッドが呼び出せる範囲)と「可視性」(他のクラスから見えるかどうか)が決まります。
ここでは、メソッドのスコープと可視性に関する基本的な原則について、ソースコード例を交えながら詳しく解説していきます。
1. ローカル変数のスコープ
メソッド内で定義される変数(ローカル変数)のスコープは、その変数が定義されたブロック内です。
すなわち、変数はそのブロックを抜けるとアクセスできなくなります。
ソースコード例
1 2 3 4 5 6 7 |
public class Sample { public static void main(String[] args) { int x = 10; System.out.println(x); // ここではxが利用可能 } // ここではxは利用不可 } |
2. メソッドの可視性
メソッドの可視性は、アクセス修飾子によって制御されます。public, private, protected, または デフォルト(アクセス修飾子を指定しない)が利用できます。
- public: どこからでもアクセス可能
- private: 同じクラス内からのみアクセス可能
- protected: 同じパッケージまたはサブクラスからアクセス可能
- デフォルト: 同じパッケージからアクセス可能
こちらもソースコードを通じて、それぞれのアクセス修飾子の違いを確認していきましょう。
この節は理解するのが少し難しいかもしれませんが、実際にコードを書いて実行してみると理解が深まるでしょう。
セクション7:メソッド引数: 値渡し vs. 参照渡し
Javaではメソッド引数は値渡しであり、これはプリミティブ型とオブジェクト参照の両方に適用されます。では詳しく見ていきましょう。
プリミティブ型の引数
プリミティブ型(int, char, float, etc.)の引数は、その値がメソッドにコピーされます。これは、メソッド内でパラメータの値を変更しても、メソッド呼び出し元の値には影響しないことを意味します。
1 2 3 4 5 6 7 |
void modifyPrimitive(int number) { number = 99; } int num = 10; modifyPrimitive(num); // numの値は10のままです。 |
上記の例では、modifyPrimitive
メソッド内でnumber
の値を変更しても、num
の値は変わりません。
オブジェクト参照の引数
オブジェクト参照を引数として渡す場合、その参照(またはポインタ)が値としてコピーされます。しかし、ここで注意が必要なのは、参照がコピーされるのはあくまで「参照」であり、オブジェクト自体はコピーされない点です。
1 2 3 4 5 6 7 |
void modifyObjectReference(StringBuffer buffer) { buffer.append(" World"); } StringBuffer stringBuffer = new StringBuffer("Hello"); modifyObjectReference(stringBuffer); // stringBufferの内容は "Hello World" となります。 |
この例では、modifyObjectReference
メソッドにstringBuffer
の参照が渡され、メソッド内でそのオブジェクトを変更しています。したがって、メソッド呼び出し元のstringBuffer
も変更されます。
参照自体の変更は反映されない
オブジェクト参照を変更しても、その変更はメソッド呼び出し元には影響しません。
1 2 3 4 5 6 7 |
void modifyReference(StringBuffer buffer) { buffer = new StringBuffer("New World"); } StringBuffer stringBuffer = new StringBuffer("Hello"); modifyReference(stringBuffer); // stringBufferの内容は "Hello" のままです。 |
上記では、modifyReference
メソッド内でbuffer
を新しいオブジェクトに設定していますが、stringBuffer
の内容は変更されません。なぜなら、メソッド内で参照が新しいオブジェクトに変わっただけで、呼び出し元の参照(stringBuffer
)は変わらないからです。
まとめ
この記事では、Javaのメソッドに関連する基本的な操作、つまり引数の渡し方、メソッドの呼び出し方、および戻り値の取り扱い方について概観しました。これらの基本を理解することで、Javaプログラミングの様々な側面に対応することができます。