2-2. メソッドとコンストラクタ¶
メソッドとコンストラクタは、クラスの動作を定義し、オブジェクトを初期化するための重要な要素です。
メソッドの詳細¶
メソッドの構造¶
例¶
public class Calculator {
// 戻り値あり、パラメータあり
public int add(int a, int b) {
return a + b;
}
// 戻り値なし(void)
public void printSum(int a, int b) {
System.out.println("Sum: " + (a + b));
}
// パラメータなし
public String getWelcomeMessage() {
return "Welcome to Calculator!";
}
}
パラメータと引数¶
値渡し(Pass by Value)¶
Javaはすべて値渡しです。
プリミティブ型の場合:
public class Example {
public static void main(String[] args) {
int x = 10;
modify(x);
System.out.println(x); // 10(変更されない)
}
static void modify(int num) {
num = 20; // ローカル変数のみ変更
}
}
参照型の場合:
public class Example {
public static void main(String[] args) {
Person person = new Person();
person.name = "Alice";
modifyPerson(person);
System.out.println(person.name); // "Bob"(オブジェクトの内容は変更される)
reassignPerson(person);
System.out.println(person.name); // "Bob"(参照自体は変更されない)
}
static void modifyPerson(Person p) {
p.name = "Bob"; // オブジェクトの内容を変更
}
static void reassignPerson(Person p) {
p = new Person(); // ローカル変数のみ変更
p.name = "Charlie";
}
}
ポイント: 参照のコピーが渡されるため、オブジェクトの内容は変更できますが、参照自体は変更できません。
可変長引数(Varargs)¶
メソッドに任意の個数の引数を渡せます。
public class MathUtil {
// 可変長引数
public static int sum(int... numbers) {
int total = 0;
for (int num : numbers) {
total += num;
}
return total;
}
}
// 使用例
int result1 = MathUtil.sum(1, 2, 3); // 6
int result2 = MathUtil.sum(1, 2, 3, 4, 5); // 15
int result3 = MathUtil.sum(); // 0
制約: - 可変長引数はパラメータの最後に1つだけ指定可能
// OK
public void method(String name, int... numbers) { }
// エラー
public void method(int... numbers, String name) { }
public void method(int... numbers1, int... numbers2) { }
メソッドのオーバーロード¶
同じ名前で異なるパラメータを持つメソッドを複数定義できます。
public class Printer {
// パラメータの型が異なる
public void print(int value) {
System.out.println("Integer: " + value);
}
public void print(double value) {
System.out.println("Double: " + value);
}
public void print(String value) {
System.out.println("String: " + value);
}
// パラメータの数が異なる
public void print(String message, int times) {
for (int i = 0; i < times; i++) {
System.out.println(message);
}
}
}
// 使用例
Printer printer = new Printer();
printer.print(10); // Integer: 10
printer.print(3.14); // Double: 3.14
printer.print("Hello"); // String: Hello
printer.print("Hi", 3); // Hi(3回)
オーバーロードの条件: - パラメータの数、型、順序が異なる必要がある - 戻り値の型だけが異なるのはNG
// エラー: 戻り値の型だけ異なる
public int getValue() { return 1; }
public double getValue() { return 1.0; } // コンパイルエラー
コンストラクタ¶
コンストラクタは、オブジェクトの初期化を行う特別なメソッドです。
コンストラクタの特徴¶
- クラス名と同じ名前
- 戻り値の型を指定しない(
voidも不要) newキーワードでオブジェクト生成時に自動的に呼ばれる
デフォルトコンストラクタ¶
コンストラクタを定義しない場合、コンパイラが自動的にデフォルトコンストラクタを生成します。
カスタムコンストラクタ¶
public class Person {
String name;
int age;
// コンストラクタ
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
// 使用例
Person person = new Person("Alice", 25);
System.out.println(person.name); // Alice
注意: カスタムコンストラクタを定義すると、デフォルトコンストラクタは自動生成されません。
public class Person {
String name;
public Person(String name) {
this.name = name;
}
}
// Person person = new Person(); // エラー: 引数なしのコンストラクタが存在しない
Person person = new Person("Alice"); // OK
コンストラクタのオーバーロード¶
複数のコンストラクタを定義できます。
public class Person {
String name;
int age;
String email;
// コンストラクタ1
public Person() {
this.name = "Unknown";
this.age = 0;
}
// コンストラクタ2
public Person(String name) {
this.name = name;
this.age = 0;
}
// コンストラクタ3
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// コンストラクタ4
public Person(String name, int age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
}
// 使用例
Person p1 = new Person();
Person p2 = new Person("Alice");
Person p3 = new Person("Bob", 30);
Person p4 = new Person("Charlie", 25, "charlie@example.com");
コンストラクタチェーン(this())¶
他のコンストラクタを呼び出すことで、重複を避けられます。
public class Person {
String name;
int age;
String email;
// コンストラクタ1
public Person() {
this("Unknown", 0, null); // コンストラクタ3を呼び出す
}
// コンストラクタ2
public Person(String name) {
this(name, 0, null); // コンストラクタ3を呼び出す
}
// コンストラクタ3(メイン)
public Person(String name, int age, String email) {
this.name = name;
this.age = age;
this.email = email;
}
}
注意: this() はコンストラクタの最初の行でなければなりません。
public Person(String name) {
System.out.println("Creating person...");
this(name, 0, null); // エラー: this()は最初の行でなければならない
}
初期化ブロック¶
インスタンス初期化ブロック¶
public class Person {
String name;
int age;
// インスタンス初期化ブロック(コンストラクタより前に実行)
{
System.out.println("Initializing...");
age = 0;
}
public Person(String name) {
this.name = name;
}
}
static初期化ブロック¶
クラスがロードされる際に1度だけ実行されます。
public class Config {
static String dbUrl;
static int maxConnections;
// static初期化ブロック
static {
System.out.println("Loading configuration...");
dbUrl = "jdbc:mysql://localhost:3306/mydb";
maxConnections = 10;
}
}
初期化の順序¶
public class Demo {
static int staticVar = initStaticVar();
int instanceVar = initInstanceVar();
static {
System.out.println("3. Static block");
}
{
System.out.println("5. Instance block");
}
public Demo() {
System.out.println("6. Constructor");
}
static int initStaticVar() {
System.out.println("2. Static variable initialization");
return 1;
}
int initInstanceVar() {
System.out.println("4. Instance variable initialization");
return 1;
}
public static void main(String[] args) {
System.out.println("1. Main method");
new Demo();
}
}
// 出力:
// 1. Main method
// 2. Static variable initialization
// 3. Static block
// 4. Instance variable initialization
// 5. Instance block
// 6. Constructor
実践例: Rectangleクラス¶
public class Rectangle {
private double width;
private double height;
// コンストラクタ1: デフォルト(正方形)
public Rectangle() {
this(1.0, 1.0);
}
// コンストラクタ2: 正方形
public Rectangle(double side) {
this(side, side);
}
// コンストラクタ3: 長方形
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
// メソッド
public double getArea() {
return width * height;
}
public double getPerimeter() {
return 2 * (width + height);
}
public void scale(double factor) {
width *= factor;
height *= factor;
}
public void displayInfo() {
System.out.println("Width: " + width + ", Height: " + height);
System.out.println("Area: " + getArea());
System.out.println("Perimeter: " + getPerimeter());
}
}
// 使用例
public class Main {
public static void main(String[] args) {
Rectangle r1 = new Rectangle(); // 1x1の正方形
Rectangle r2 = new Rectangle(5); // 5x5の正方形
Rectangle r3 = new Rectangle(4, 6); // 4x6の長方形
r3.displayInfo();
r3.scale(2); // 2倍に拡大
r3.displayInfo();
}
}
まとめ¶
メソッド¶
- 構造: アクセス修飾子、戻り値の型、メソッド名、パラメータ
- 値渡し: すべて値渡し(参照型は参照のコピーが渡される)
- 可変長引数:
int... numbersで任意個数の引数 - オーバーロード: 同じ名前で異なるパラメータ
コンストラクタ¶
- 目的: オブジェクトの初期化
- 特徴: クラス名と同じ、戻り値なし
- デフォルト: 定義しない場合は自動生成
- オーバーロード: 複数のコンストラクタを定義可能
- チェーン:
this()で他のコンストラクタを呼び出し
次のセクションでは、カプセル化について学びます。