English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Javaにおける反射详解

目次

  1. Java反射API
  2. 反射を通じてインスタンスを生成します。
  3. プライベートメソッドの反射による呼び出し
  4. javapツールについて
  5. 参考文献

Java反射API

Java反射これは、実行中の状態でクラスの属性やメソッドを取得したり、クラスの実行時の行動を変更できるプロセスを指します。

java.lang.Classクラスメタデータの取得、クラスの実行時の行動の確認および変更に使用される多くのメソッドを提供しています。

Javaの反射はjava.langおよびjava.lang.reflectパッケージのクラスに関連しています。

反射の適用シーンの例

  1. IDE、Eclipse、MyEclipse、NetBeansなど;
  2. デバッガー;
  3. テストツールなど;
  4. 主要なフレームワーク、spring、hibernateなど;

java.lang.Classクラス

java.lang.Classクラスは以下の2つの主要機能を提供します:

  1. 実行中のクラスのメタデータにアクセスするためのメソッドを提供します;
  2. クラスの実行時行動を確認および修正するためのメソッドを提供します;

java.lang.Classクラスの常用メソッド

Method Description
1) public String getName() クラス名を返します
2) public static Class forName(String className) throws ClassNotFoundException クラスをロードし、Classオブジェクトを返します
3) public Object newInstance() throws InstantiationException, IllegalAccessException インスタンスオブジェクトを作成します
4) public boolean isInterface() インターフェースであるかどうかを判断します
5) public boolean isArray() 配列であるかどうかを判断します
6) public boolean isPrimitive() 原始データタイプであるかどうかを判断します
7) public Class getSuperclass() 親クラスのClassリファレンスを返します
8) public Field[] getDeclaredFields() throws SecurityException クラスのメンバー属性フィールドの配列を返します
9) public Method[] getDeclaredMethods() throws SecurityException クラスのメソッドの配列を返します
10) public Constructor[] getDeclaredConstructors() throws SecurityException クラスのコンストラクタの配列を返します
11) public Method getDeclaredMethod(String name, Class[] parameterTypes) throws NoSuchMethodException, SecurityException クラス内で指定されたパラメータタイプのメソッドを返します

どうやってClassオブジェクトを取得しますか?

以下の3つの方法があります:

  1. ClassクラスのforName()メソッドは、動的にロードされ、実行時にクラスが読み込まれ、クラスの静的初期化が行われます。
  2. getClass()メソッドのオブジェクト、静的ロード(コンパイル時に既にロードされています)
  3. .class文法、静的ロード(コンパイル時に既にロードされています)

forName()メソッドの例

動的ロードに使用できます。クラスの完全限定名がわかっている場合に使用します。注意していただきたいのは、元のデータ型には適用しないでください;

package tmp;
class Simple
{
}
public class Test
{
 public static void main(String args[]) throws ClassNotFoundException
 {
 try63Class<&#
 System.out.println(c.getName());
 System.out.println(c.getSimpleName());
 }
}
tmp.Simple
Simple

getClass()メソッドの例:

インスタンスオブジェクトからClassオブジェクトを取得します。

package tmp;
class Simple
{
}
public class Test
{
 void printName(Object obj)
 {
 }
 public static void main(String args[])
 {
 Simple s = new Simple();
 try63; extends Object> c = s.getClass();
 System.out.println(c.getName());
 System.out.println(c.getSimpleName());
 }
}
tmp.Simple
Simple

.class文法の例

クラス名に適用されることができますが、元のデータ型にも適用できます。以下に示します:

package tmp;
public class Test
{
 public static void main(String args[])
 {
 Class<Boolean> c = boolean.class;
 System.out.println(c.getName());
 Class<Test> c2 = Test.class;
 System.out.println(c2.getName());
 }
}
boolean
tmp.Test

Classオブジェクトが対応するタイプを判定する

以下のメソッドを使用してClassオブジェクトが対応するタイプを判定できます:

1) public boolean isInterface(): インターフェースに対応しているかどうか
2) public boolean isArray(): 配列に対応しているかどうか
3) public boolean isPrimitive(): 元のデータ型に対応しているかどうか

コード例:

package tmp;
class Simple
{
}
interface My
{
}
public class Test
{
 public static void main(String args[])
 {
 this.msg = s;
 {
 try63Class<&#
 System.out.println(c.isInterface());
 try63;> c2 = Class.forName("tmp.My");
 System.out.println(c2.isInterface());
 }
 catch (Exception e)
 {
 System.out.println(e);
 }
 }
}
false
true

反射を通じてインスタンスを生成します。

以下の2つの方法があります:

  1. ClassオブジェクトのnewInstance()メソッドを通じて作成され、無参のコンストラクタのみを呼び出すことができます。
  2. ConstructorオブジェクトのnewInstance()メソッドを通じて作成され、パラメータ付きのコンストラクタに適用され、またシングルトンパターンを破壊し、プライベートなコンストラクタを呼び出すことができます。

所以,通常来讲,第二种方式比第一种使用范围更广。

したがって、通常、第二种の方法は第一種の方法よりも使用範囲が広いです。

package tmp;
class Simple
{
 private String msg;
 {
 ClassオブジェクトがnewInstance()メソッドを呼び出す例
 }
}
public class Test
{
 public static void main(String args[])
 {
 this.msg = s;
 {
 try63Class<&#
 System.out.println("Hello Java");
 s.message();
 }
 catch (Exception e)
 {
 System.out.println(e);
 }
 }
}

Simple s = (Simple) c.newInstance();

Hello Java

ConstructorオブジェクトがnewInstance()メソッドを呼び出す例

package tmp;
ここでは、引数のタイプに応じて指定されたコンストラクタを取得することができます。また、コンストラクタのアクセス権限制限を変更することもできます。
class Simple
{
 import java.lang.reflect.Constructor;
 private String msg;
 {
 void message() + System.out.println("Hello Java,"
 }
 msg);
 private Simple(String s){
 }
}
public class Test
{
 public static void main(String args[])
 {
 this.msg = s;
 {
 try63Class<&#
 ;> c = Class.forName("tmp.Simple");63;> con = c.getDeclaredConstructor(String.class);
 con.setAccessible(true);
 Simple s = (Simple) con.newInstance("...");
 s.message();
 }
 catch (Exception e)
 {
 System.out.println(e);
 }
 }
}

Hello Java,...

プライベートメソッドの反射による呼び出し

反射を使用して、他のクラスのプライベートメソッドを呼び出すことができます。これは主にjava.lang.Classとjava.lang.reflect.Methodクラスに関連しています;

これは主にMethodクラスのsetAccessibleメソッドとinvokeメソッドを使用しており、前者はアクセス権限を変更し、後者はメソッドを呼び出します。

有参私有方法调用示例:

package tmp;
import java.lang.reflect.Method;
class A
{
 private void cube(int n)
 {
 System.out.println(n * n * n);
 }
}
class Test
{
 public static void main(String args[]) throws Exception
 {
 Class<A> c = A.class;
 Object obj = c.newInstance();
 Method m = c.getDeclaredMethod("cube", new Class[]{ int.class });
 m.setAccessible(true);
 m.invoke(obj, 4);
 }
}

javapツールについて

javapコマンドを使用して、javaのバイトコードファイルを逆コンパイルし、classファイル内のフィールド属性、コンストラクタ、通常のメソッド情報を表示できます;

使用説明:

javap java.lang.Object 例

javap -c Test 例:

以下のように簡単なTestクラスを作成してください:

package tmp;
class Simple
{
}
public class Test
{
 public static void main(String args[])
 {
 System.out.println("Hello");
 }
}

javapを入力してください -c Test:

参考文献

基本的には翻訳であり、少しの修正が行われています

http://www.javatpoint.com/java-refletion

これでこの記事のすべての内容が終わります。この記事の内容が皆様の学習や仕事に少しでも役立つことを願っています。また、呐喊教程!を多くのサポートをお願いします。

声明:この記事の内容はインターネットから取得しており、著作権者は所有者であり、インターネットユーザーが自発的に貢献し、自己でアップロードしたものであり、本サイトは所有権を有しておらず、人工的な編集処理も行われていません。著作権侵害の疑いがある場合は、以下のメールアドレスまでお知らせください:notice#oldtoolbag.com(メールを送信する際には、#を@に変更してください。通報を行い、関連する証拠を提供してください。一旦確認が取れましたら、本サイトは即座に侵害疑いの内容を削除します。)

おすすめ