【Java】インスタンス化をnewしないで行う方法まとめ|初心者向けサンプル付き解説

お疲れ様です。はるさらと申します。

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のBeanFactoryApplicationContextもこの考え方を応用している

③ シングルトン+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引数なしコンストラクタが存在しない明示的にデフォルトコンストラクタを定義
IllegalAccessExceptionprivateコンストラクタを呼び出しているsetAccessible(true)を使う必要あり(高度な用途)

まとめ:newしないインスタンス化は意外と身近

実務でも、

  • リフレクション(動的クラスロード)
  • ファクトリ(生成処理の共通化)
  • シングルトン(共有オブジェクトの生成制御)

など、newを使わない設計は頻繁に登場します。
特にSpring FrameworkのようなDIコンテナはこの仕組みを内部的に利用しており、
理解しておくとアーキテクチャ全体の理解が深まると思われます。

どなたかのお役に立てば幸いです。
それではまたー!