お疲れ様です。はるさらと申します。
Javaでオブジェクトを作るとき、
通常は new キーワードを使ってインスタンス化します。
しかし試験や実務等で「new を使わずにインスタンス化したい」ケースが
求められるかしれません。
本記事では、new なしでインスタンスを生成する方法を、
サンプルコード付きでわかりやすく解説します。
また、こちらの記事もインスタンス化について記載しているため
参考になるかもしれません。
なぜ「newしないインスタンス化」が必要なのか
「new を使わずに作る」なんて少し不思議に思うかもしれません。
しかし、フレームワーク開発や動的なクラス読み込み、
DI(依存性注入)などでは、実行時にクラス名からインスタンスを生成する必要があります。
たとえば以下のようなケースです。
- 設定ファイルで指定されたクラスを動的にロードしたい
- 共通ライブラリで汎用的にクラスを扱いたい
- シングルトンやファクトリパターンでインスタンス管理を行いたい
こうしたときに役立つのが、newを使わずにインスタンス化する方法です。
newを使わずにインスタンス化する3つの方法
ここでは、代表的な3つの方法をサンプル付きで紹介します。
① Class.forName()+newInstance()を使う方法(基本)
まずは最も基本的なリフレクションを使う方法です。
この方法では、クラス名(文字列)からインスタンスを生成できます。
Sample.java
package com.example;
public class Sample {
public Sample() {
System.out.println("Sampleクラスのコンストラクタが呼ばれました");
}
public void hello() {
System.out.println("こんにちは、Sampleです。");
}
}
ReflectionExample.java
package com.example;
public class ReflectionExample {
public static void main(String[] args) throws Exception {
// クラス名を文字列で指定
Class<?> clazz = Class.forName("com.example.Sample");
// newを使わずにインスタンス生成
Object obj = clazz.getDeclaredConstructor().newInstance();
// メソッド呼び出し
Sample sample = (Sample) obj;
sample.hello();
}
}
実行結果
Sampleクラスのコンストラクタが呼ばれました
こんにちは、Sampleです。
ポイント解説
Class.forName()… クラスを動的にロードgetDeclaredConstructor().newInstance()… コンストラクタ呼び出しで生成ClassNotFoundExceptionを避けるために、
完全修飾クラス名(パッケージ込み) を指定することが重要
この仕組みはSpringやMyBatisなどの内部でも多用されています。
② 実務でよく使うファクトリパターン
リフレクションは強力ですが、例外処理が多く少し扱いにくいです。
そのため、実務では「ファクトリ(Factory)パターン」を使ってnewを隠蔽することも多いです。
Shape.java
package com.example;
public interface Shape {
void draw();
}
Circle.java
package com.example;
public class Circle implements Shape {
public void draw() {
System.out.println("○ 円を描きました。");
}
}
ShapeFactory.java
package com.example;
public class ShapeFactory {
public static Shape createShape(String type) {
if ("circle".equalsIgnoreCase(type)) {
return new Circle(); // ここでnewしているが呼び出し元は意識しない
}
throw new IllegalArgumentException("不明な型です: " + type);
}
}
Main.java
package com.example;
public class Main {
public static void main(String[] args) {
Shape shape = ShapeFactory.createShape("circle");
shape.draw();
}
}
実行結果
○ 円を描きました。
ポイント解説
- 呼び出し側では
newを直接使わずに済む - ファクトリ内部に生成ロジックをまとめることで保守性が上がる
- Springの
BeanFactoryやApplicationContextもこの考え方を応用している
③ シングルトン+getInstance()で生成(代替手法)
同じインスタンスを共有したい場合、シングルトンパターンも
「newを使わない生成方法」の一つです。
Config.java
package com.example;
public class Config {
private static final Config INSTANCE = new Config();
private Config() {
System.out.println("Configのコンストラクタが呼ばれました");
}
public static Config getInstance() {
return INSTANCE;
}
public void printSetting() {
System.out.println("設定値を表示します。");
}
}
SingletonExample.java
package com.example;
public class SingletonExample {
public static void main(String[] args) {
Config config1 = Config.getInstance();
Config config2 = Config.getInstance();
config1.printSetting();
System.out.println("同一インスタンス? → " + (config1 == config2));
}
}
実行結果
Configのコンストラクタが呼ばれました
設定値を表示します。
同一インスタンス? → true
ポイント解説
privateコンストラクタ+staticインスタンスで制御- 呼び出し側からは
newを使わずにインスタンスを取得 - 設定クラスやDBコネクション管理などでよく使われる
よくあるエラーと注意点
| エラー内容 | 原因 | 対策 |
|---|---|---|
ClassNotFoundException | クラス名が誤っている | 完全修飾名(例:com.example.Sample)を指定 |
NoSuchMethodException | 引数なしコンストラクタが存在しない | 明示的にデフォルトコンストラクタを定義 |
IllegalAccessException | privateコンストラクタを呼び出している | setAccessible(true)を使う必要あり(高度な用途) |
まとめ:newしないインスタンス化は意外と身近
実務でも、
- リフレクション(動的クラスロード)
- ファクトリ(生成処理の共通化)
- シングルトン(共有オブジェクトの生成制御)
など、newを使わない設計は頻繁に登場します。
特にSpring FrameworkのようなDIコンテナはこの仕組みを内部的に利用しており、
理解しておくとアーキテクチャ全体の理解が深まると思われます。
どなたかのお役に立てば幸いです。
それではまたー!



































![【ColofulBox】『[Installatron] WordPress プラグイン~が利用可能になりました』のメールを止める方法](https://harusara22.work/wp-content/uploads/2023/04/E784A1E9A18C124_20230410082422-768x460.jpg?v=1681082704)