Java の Class クラスに定義されているメソッドを見ていくシリーズ(目次)。 Class オブジェクトに定義されているメソッドを使うためには、まず Class オブジェクトを何らかの方法で取得する必要があります。 ということで、今回は Class オブジェクトの取得方法を見ていきます。
Class オブジェクトの取得方法
Class オブジェクトを取得する方法には以下のようなものがあります:- クラスリテラルを指定する ・・・ .class
- 既に存在するオブジェクトから、そのクラスを取得する ・・・ getClass()
- クラスを表す文字列から、それが表すクラスを取得する ・・・ Class.forName()
以下、それぞれの方法を見ていきます。
class リテラルを指定する
まずはクラスリテラル*1を指定する方法。 これはクラスの名前が分かっている(決まっている)場合に使用します。 クラスリテラルの使用方法は《クラス名》.class です:Class<String> clazz0 = String.class; Class<?> clazz1 = String.class; Class<Number> clazz2 = Integer.class; // コンパイルエラー Class<? extends Number> clazz3 = Integer.class;
クラスリテラルを使用した場合、用いた名前のクラスが必ずそのまま返されるので、3行目のように親子関係にあるクラス同士(Number と Integer)でもそのまま代入することはできません(Integer.class は Number.class に代入不可!)。 ただし、Class の型パラメータにワイルドカード (?) を指定すれば代入することができます。
プリミティブ型の場合
プリミティブ型を表す Class クラスも扱うことができます。 取得方法は次の2つです:- プリミティブ型のクラスリテラルを指定する
- ラッパクラスに定義されている TYPE フィールド (static フィールド)を取得する
具体的には
Class<?> clazz4 = int.class; Class<?> clazz5 = Double.TYPE
といった感じです。 その他の扱い方は通常の Class オブジェクトと同じです。
既に存在するオブジェクトから、そのクラスを取得する
次は、既に存在しているオブジェクトから Class オブジェクトを取得する方法です。 これはオブジェクトが存在している場合に用います(説明になってない?:->)。 取得方法は、Class を取得したいオブジェクトに対して getClass() メソッドを呼び出すだけです:String s = "abc"; Class<? extends String> clazz = s.getClass()
getClass() メソッドの返り値
上記の例で Class オブジェクトを代入されている変数の型が Class<? extends String> であることに注意*2。 これは、getClass() メソッドが呼ばれている変数の型(正確には apparent type、宣言されている型)が、必ずしも実際の型 (actual type) と同じとは限らないためです。もう少し具体的に見てみましょう。 Double クラスが Number クラスのサブクラス (class Double extends Number) であることを念頭に置いて、Number 変数を Double オブジェクトで初期化します:
Number n = new Double(1.0);
このとき、変数 n の「apparent type」は Number、「actual type」は Double です。 このとき、n に対して getClass() を呼び出すと「actual type」の Class オブジェクト、つまり Double.class が返されます。
ただし、普通のプログラムでは、変数に代入されているオブジェクトの「actual type」は一般に分からないことが多く*3、その場合、「この変数の actual type はこのクラス(今の場合 Number クラス)のサブタイプである」ということまでしか分かりません。 したがって、getClass() が返す Class オブジェクトは「apparent type」とワイルドカード (?) を用いて Class<? extends 《apparent type》> とする必要があります:
Class<? extends Number> clazz = n.getClass();
getClass() メソッドの他の使い方もいくつか載せておきます:
Number n = new Double(1.0); Class<? extends Number> class0 = n.getClass(); Class<?> class1 = n.getClass(); Double d = new Double(1.0); Class<? extends Double> clazz2 = d.getClass(); Class<? extends Number> clazz3 = d.getClass(); Class<?> clazz4 = d.getClass();
getClass() の仕様
こちらのサイトによると、getClass() の仕様が JDK のバージョン (1.4〜1.6) によって変更になっているそうです:1.4 public final Class getClass() 1.5 public final Class<? extends Object> getClass() 1.6 public final Class<?> getClass()
上記の話は1.5の定義をベースにしてますが、1.6でもコンパイルエラーになったりはしません。
クラスを表す文字列から、それが表すクラスを取得する
最後はクラスを表す文字列から、それが表すクラスを取得する方法*4。 この方法で Class オブジェクトを取得するには、Class クラスに定義されている static メソッド Class.forName() メソッドを使用します。 Class.forName() メソッドにはシグニチャの異なる2つのメソッドがオーバーロードされています:メソッド名 | 返り値 | チェック例外 |
---|---|---|
forName(String className) forName(String name, boolean initialize, ClassLoader loader) |
Class<?> | ClassNotFoundException |
1つ目のメソッドは2つ目のメソッドを適当なパラメータで呼び出しているようです。 次の2つのメソッド呼び出しは同じ結果になります(name はクラス名とし、this キーワードでオブジェクトが参照できる場合*5)
Class.forName(name); Class.forName(name, true, this.getClass().getClassLoader());
Class.forName() メソッドの使用方法
Class.forName() メソッドの使用方法はこんな感じ:Class<?> clazz = null try{ clazz = Class.forName("java.lang.String"); }catch(ClassNotFoundException ex){ ex.printStackTrace(); }
指定するクラス名はパッケージ名まで含めた完全修飾名でなければなりません。
その他、いくつかの注意
- 引数にプリミティブ型(int など)もしくは void を指定した場合、ClassNotFoundException が投げられます。
- 引数に配列の型を指定した場合、配列要素のクラスはロードされるが、初期化はされません。 また、この場合に指定する名前(文字列)は、配列オブジェクトに対して Class#getName() で返される文字列にする必要があります。
// java.lang.String[] のクラス Class<?> clazz1 = Class.forName("[Ljava.lang.String;") // int[] のクラス Class<?> clazz2 = Class.forName("[I")
プリミティブ型の配列も大丈夫なようです。

Effective Java 第2版 (The Java Series)
- 作者: Joshua Bloch,柴田芳樹
- 出版社/メーカー: ピアソンエデュケーション
- 発売日: 2008/11/27
- メディア: 単行本(ソフトカバー)
- 購入: 77人 クリック: 936回
- この商品を含むブログ (266件) を見る