いまさら聞けないJavaによるオブジェクト指向の常識プログラマーの常識をJavaで身につける(11)(5/5 ページ)

» 2008年05月08日 00時00分 公開
[伊賀敏樹, 山本耕司株式会社 NTTデータ ビジネスブレインズ]
前のページへ 1|2|3|4|5       

Java APIの「裏技」java.lang.reflectパッケージとは?

 Java言語には、java.lang.reflectパッケージを通じて「裏技」のようなAPIが提供されています。このjava.lang.reflectパッケージを利用すると、公開されていないクラスのフィールドやメソッドを「のぞき見」できてしまいます。

java.lang.reflectパッケージで、クラスを「のぞき見」

 ここでは、ラーメン・クラスをのぞき見してみます。

SnoopRamen.java
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
* ラーメン・オブジェクトをのぞき見するクラス
*/

public class SnoopRamen {
    public static void main(final String[] args)
    throws IllegalArgumentException, IllegalAccessException {
        final IRamen ramen = new Ramen();

        // ラーメン・インスタンスから
        // java.lang.Classインスタンスを取得
        final Class classRamen = ramen.getClass();

        System.out.println("フィールド一覧");
        // フィールド一覧を取得
        final Field[] fields = classRamen.getDeclaredFields();
        for (int index = 0; index < fields.length; index++) {
            final Field field = fields[index];
            System.out.println(" " + field.toString());
        }

        System.out.println("メソッド一覧");
        // メソッド一覧を取得
        final Method[] methods = classRamen.getDeclaredMethods();
        for (int index = 0; index < methods.length; index++) {
            final Method method = methods[index];
            System.out.println(" " + method.toString());
        }
    }
}

フィールド一覧
 private java.lang.String Ramen.fSoup
メソッド一覧
 public java.lang.String Ramen.getSoup()
 public void Ramen.show()
実行結果(コンソール出力)

 ラーメン・クラスに、どのようなフィールドやメソッドがあるのかが、表示されていますね。特別なjarファイルをクラスパスに追加などするまでもなく、このような芸当ができることもJava言語の特徴の1つです。

オブジェクト指向を「台無し」にしてしまうjava.lang.reflectパッケージ

 さらに、java.lang.reflectパッケージを利用すると、カプセル化により保護されているはずのオブジェクトの内容を、書き換えることもできてしまいます。ラーメンのトッピングを勝手に変えて、「いちごラーメン」を作ってみます。

TrickRamen.java
import java.lang.reflect.Field;

/**
* ねぎラーメン・オブジェクトを外から勝手にいじるクラス
*/

public class TrickRamen {
    public static void main(final String[] args)
    throws IllegalArgumentException, IllegalAccessException,
    SecurityException, NoSuchFieldException {
        // ラーメン料理人・インスタンスを作成する
        final RamenCook cook = new RamenCook();

        // ラーメン料理人にラーメンを注文する
        final IRamen ramen = cook.acceptLeekRamenOrder();

        final Class classRamen = ramen.getClass();

        // フィールドを取得
        final Field field
            = classRamen.getDeclaredField("fTopping");
        field.setAccessible(true);
        // privateフィールドの中身を勝手に外部から操作
        // この店では「いちごラーメン」は扱っていないはずなのに……

        field.set(ramen, "いちご");

        System.out.println("ラーメン・オブジェクトを確認");
        ramen.show();
    }
}

 上記のプログラムでは、「field.setAccessible(true);」を呼び出し、Java言語のアクセス修飾子とかかわりなく操作できるようにしてから、「field.set(ramen, "いちご");」を呼び出して、fToppingの値を書き換えています。

ラーメン・オブジェクトを確認
ラーメンを表示
 トッピング: いちご
 スープ : とんこつ
実行結果(コンソール出力)

 このラーメン屋では提供していないはずの、「いちごラーメン」が出来上がってしまいました。

図8 いちごラーメン 図8 いちごラーメン(こちらの図はJavaプログラミング[アプリケーション編]ステップアップラーニング』(技術評論社)で使われた図を引用して再作成したものです)

 このように、java.lang.reflectパッケージはオブジェクト指向を「台無し」にしてしまう力を併せ持っています。ですから、よほど特殊な目的を実現するプログラミングを行う場合でもない限り、java.lang.reflectパッケージは「利用してはいけない」APIである、ということも、Java言語によるプログラミングの常識なのです。

もっとオブジェクト指向を習得するためには?

 Java言語を使ってオブジェクト指向の基本概念を見てきましたが、いかがだったでしょうか。オブジェクト指向は難しくとっつきにくいものですが、これを使いこなすといろいろな応用ができることが期待できます。

 初心者のうちは、ほかの人やAPIなどがどのようにオブジェクト指向を扱っているのかを読む/知ることから学んでいくのが良い学習法だと思います。そして、オブジェクト指向の基本的な概念を理解したうえで、オブジェクト指向に関連する技術の中から、興味があるものにチャレンジしていってみましょう。

参考文献

筆者紹介

blanco Framework(コミッタ)

伊賀 敏樹(いが としき)
ハンドル:いがぴょん

1968年生まれ。現在、NTTデータ ビジネスブレインズ 第一SI事業部 ソリューショングループ所属。システム開発の技術支援などに従事する。仕事におけるJava言語とのかかわりは1998年から。 現在 blanco Frameworkというオープンソースによるソースコード自動生成タイプの開発フレームワーク提供に取り組んでいる。 趣味はヴァイオリン演奏。アマチュアオーケストラで演奏することもある。

ホームページ
いがぴょんの日記ウェブページv2(1996年から続けているWeb日記)

主な著書
やさしく学ぶ基礎からのJDBC
Javaプログラミング[アプリケーション編]ステップアップラーニング


前のページへ 1|2|3|4|5       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。