Javaエンジニア・プログラマ向けの技術情報・業界ニュースをお届けします。

  1. FEnetJava
  2. Javaコラム
  3. Java TIPS
  4. Javaのインスタンスとは?Javaのインスタンス生成方法や注意点を解説!

Javaのインスタンスとは?Javaのインスタンス生成方法や注意点を解説!

  • Java TIPS
公開日時:   更新日時:
Javaのインスタンスとは?Javaのインスタンス生成方法や注意点を解説!
この記事でわかること
    システム
    エンジニア
    Javaのインスタンスとはどのようなものなのでしょうか。
    プロジェクト
    マネージャー
    インスタンスとは簡単に言えば「クラスをnewするとできるもの」です。

    Javaのインスタンスとは?


    インスタンスとは何なのでしょうか。インスタンスとは簡単に言えば「クラスをnewするとできるもの」です。インスタンスはJavaに限らず、C#などの他のオブジェクト指向言語でも共通する概念ですが、最初のうちは使い方を覚えるだけで問題はありません。

    以下のクラスを例に説明をしましょう。

    class TestClass {
    public int value;
    static int s_value;

    public void dispValue() {
    System.out.println(value);
    }

    public static void dispValue_s() {
    System.out.println(s_value);
    }
    };

    静的と動的

    上のTestClassは以下のように利用できます。

    TestClass.s_value = 3;
    TestClass.dispValue_s();

    実行すると「3」と表示されます。TestClass内のs_valueやdispValue_s()にはstaticというキーワードが付いていますが、これを付けると「静的」になります。staticがないvalueやdispValue()は「動的」と言います。

    動的なフィールドやメソッドは普通には呼び出せない

    動的なvalueやdispValue()は以下のように呼び出そうとしてもエラーになってしまいます。

    TestClass.value = 3;
    TestClass.dispValue();

    また以下のようにdispValue_s()内でvalueを呼び出そうとしても、やはりエラーになります。

    public static void dispValue_s() {
    System.out.println(value); // s_valueでないとエラー
    }

    動的なフィールドやメソッドは直接呼び出せません。どうすれば良いのでしょうか。

    動的なフィールドやメソッドはインスタンスとして呼び出す

    動的なフィールドやメソッドは、クラスをインスタンスにしないと呼び出せないのです。以下のようにnewをしてインスタンスを生成すれば、呼び出すことができます。

    TestClass c = new TestClass();
    c.value = 3;
    c.dispValue();

    newしてインスタンス化するというのは、コンピュータの仕組み的に言えば、動的なメモリを確保するということです。valueというフィールドはnewしないとメモリが確保されないので使えないのです。s_valueは静的で、これは最初からメモリが確保されているのですぐに使えます。

    むやみにnewしない方が良いのも事実

    「いちいちnewしてインスタンスを生成するより、全てstaticにすればよいのでは?」と思う人もいるかもしれません。それで作れればそれで問題ありません。静的の方がパフォーマンスが良いため、動作も速くなります。Javaでは「むやみにnewしない」が鉄則です。

    「それではインスタンスは何の役に立つの?」と思いますよね。しかし動的なクラスは静的なクラスよりメリットがあるのです。インスタンスは以下のように同じクラスを元に複数生成し、データを別個に持つことが出来ます。

    TestClass c1 = new TestClass();
    c1.value = 3;
    TestClass c2 = new TestClass();
    c2.value = 4;

    インスタンスには静的データにはないメリットがある

    静的なstaticフィールドは最初からメモリが確保されているのでnewせずにすぐ使えますが、最初から使える数が決まっているという問題があります。例えば以下のようにTestClassのs_valueを、5つの要素を入れられる配列に拡張するとします。

    static int[] s_value = { 0, 0, 0, 0, 0 };

    しかし6つ以上の値を入れたい場合、Javaプログラムの実行中に配列を拡張して追加することはできません。newでいくらでも増やせるインスタンスであれば、メモリの余裕さえあれば実行中でも際限なく追加できるのです。

    膨大なデータを扱う場合はインスタンスが必要

    Javaを使用したWebシステムにはサーブレットがあります。Webサイトにはユーザーから多くのアクセスが発生し、マルチスレッドで動的に処理する必要があります。上限が見えない程の膨大な量のアクセスがあるため、newで作られるインスタンスを使う必要があるのです。

    なおインスタンスは常にnewで生成されるわけではありません。例えばString型の文字列のインスタンスは以下のように宣言してもnewされています。

    String str = “”あいうえお””;

    ただし以下のようにnewすることもできます。

    String str = new String(“”あいうえお””);

    newが非推奨のクラスもある

    int型の数値を中に保持するInteger型のインスタンスは、newを使用せず以下のように生成します。

    Integer i = Integer.valueOf(100);

    以下のようにnewで生成することもできますが、非推奨となっています。理由はvalueOfで生成すると内部でインスタンスが再利用されて、パフォーマンスが良くなるようにJavaが設計されているからです。この点からもnewはむやみに利用すべきでないことがわかります。

    Integer i = new Integer(100); // 取り消し線が引かれてワーニングが出る

    インスタンスの再利用の落とし穴

    上で述べたように、Javaは内部処理的に同じインスタンスで済めば再利用するようにしています。これに関連して、String型文字列を扱う時に注意すべき点があります。以下のJavaサンプルを実行してみてください。

    String str1 = “”abc””;
    String str2 = “”abc””;

    if (str1==str2) {
    System.out.println(“”同じインスタンスです””);
    }
    if (str1.equals(str2)) {
    System.out.println(“”同じ内容の文字列です””);
    }

    ==の比較が一見矛盾した結果になる

    上のJavaサンプルを実行すると以下のように表示されます。

    同じインスタンスです
    同じ内容の文字列です

    これはおかしな結果です。equalsは文字列の内容比較なので正しいですが、==で比較した場合は同じインスタンスかどうかの比較になります。同じ内容でも別のインスタンスなのに、なぜ同じになってしまうのでしょうか。

    実はJavaの内部処理では、内容が同じ文字列はメモリを節約するために1つのインスタンスにまとめられてしまっているのです。

    インスタンスを==で比較するのは避ける

    今度はstr1とstr2の宣言を以下のように修正して実行してみてください。

    String str1 = “”abc””;
    str1 += “”a””;
    String str2 = “”abc””;
    str2 += “”a””;

    これで実行すると、「同じ内容の文字列です」のみ表示されます。str2を宣言する時に、str1がabcaになっていて、abcではないので別のインスタンスになったということです。

    このようなことがあるので、==で同じインスタンスかどうかを判定するのは避けた方が良いと言えます。

    インスタンス生成を抑止する方法

    staticなフィールドとメソッドだけしかないため、インスタンスの生成が不要な場合クラスは、newを抑止することが可能です。

    class TestClass {
    private TestClass() { // コンストラクタ
    }

    static int s_value;

    public static void dispValue_s() {
    System.out.println(s_value);
    }
    };

    このクラスをnewしようとするとエラーになります。コンストラクタがprivateであるため外部から呼び出せないのです。インスタンスを生成することはコンストラクタを呼び出すことと同義です。コンストラクタが無いクラスでも、実は見えないコンストラクタが存在しています。

    システム
    エンジニア
    Javaのインスタンスについてよく理解できました。
    プロジェクト
    マネージャー
    Javaのインスタンスは使い分けが必要です。しっかりと理解して使用しましょう。

    Javaのインスタンス生成はオブジェクト指向の基本

    Javaのインスタンスについて解説しましたが、ご理解頂けたでしょうか。

    インスタンスを生成しない方がパフォーマンスの良いプログラムを作れるのですが、必要な時はインスタンスを効果的に利用するのがオブジェクト指向らしいプログラミングと言えます。

    FEnetJava・Javaコラムは株式会社オープンアップシステムが運営しています。
    株式会社オープンアップシステムロゴ

    株式会社オープンアップシステムはこんな会社です

    秋葉原オフィスには株式会社オープンアップシステムをはじめグループのIT企業が集結!
    数多くのエンジニアが集まります。

    秋葉原オフィスイメージ
    • スマホアプリから業務系システムまで

      スマホアプリから業務系システムまで

      スマホアプリから業務系システムまで開発案件多数。システムエンジニア・プログラマーとしての多彩なキャリアパスがあります。

    • 充実した研修制度

      充実した研修制度

      毎年、IT技術のトレンドや社員の要望に合わせて、カリキュラムを刷新し展開しています。社内講師の丁寧なサポートを受けながら、自分のペースで学ぶことができます。

    • 資格取得を応援

      資格取得を応援

      スキルアップしたい社員を応援するために資格取得一時金制度を設けています。受験料(実費)と合わせて資格レベルに合わせた最大10万円の一時金も支給しています。

    • 東証プライム上場企業グループ

      東証プライム上場企業グループ

      オープンアップシステムは東証プライム上場「株式会社オープンアップグループ」のグループ企業です。

      安定した経営基盤とグループ間のスムーズな連携でコロナ禍でも安定した雇用を実現させています。

    株式会社オープンアップシステムに興味を持った方へ

    株式会社オープンアップシステムでは、開発系エンジニア・プログラマを募集しています。

    年収をアップしたい!スキルアップしたい!大手の上流案件にチャレンジしたい!
    まずは話だけでも聞いてみたい場合もOK。お気軽にご登録ください。

    株式会社オープンアップシステムへのご応募はこちら↓
    株式会社オープンアップシステムへのご応募はこちら↓

    Java新着案件New Job